blob: 107aed834641388108069fdf59debb2ca3035b2d [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"
ossuf515ab82016-12-07 04:52:58 -080019#include "webrtc/call/call.h"
pbosa96b60b2016-04-18 21:12:48 -070020#include "webrtc/common_video/include/frame_callback.h"
skvlad11a9cbf2016-10-07 11:53:05 -070021#include "webrtc/logging/rtc_event_log/rtc_event_log.h"
sakal55d932b2016-09-30 06:19:08 -070022#include "webrtc/media/base/fakevideorenderer.h"
brandtr5e171752017-05-23 03:32:16 -070023#include "webrtc/media/base/mediaconstants.h"
24#include "webrtc/media/engine/internalencoderfactory.h"
magjed6cc25612017-07-10 03:26:36 -070025#include "webrtc/media/engine/simulcast_encoder_adapter.h"
brandtr5e171752017-05-23 03:32:16 -070026#include "webrtc/media/engine/webrtcvideoencoderfactory.h"
danilchap5c35cf92016-02-03 14:14:49 -080027#include "webrtc/modules/include/module_common_types.h"
stefan32f81542016-01-20 07:13:58 -080028#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h"
sprang861c55e2015-10-16 10:01:21 -070029#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
Erik Språng737336d2016-07-29 12:59:36 +020030#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/nack.h"
Danil Chapovalov70ffead2016-07-20 15:26:59 +020031#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/rapid_resync_request.h"
brandtr5e171752017-05-23 03:32:16 -070032#include "webrtc/modules/rtp_rtcp/source/rtp_format.h"
sprangcd349d92016-07-13 09:11:28 -070033#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
hbosbab934b2016-01-27 01:36:03 -080034#include "webrtc/modules/video_coding/codecs/h264/include/h264.h"
marpan@webrtc.org5b883172014-11-01 06:10:48 +000035#include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h"
36#include "webrtc/modules/video_coding/codecs/vp9/include/vp9.h"
Henrik Kjellander2557b862015-11-18 22:00:21 +010037#include "webrtc/modules/video_coding/include/video_coding_defines.h"
Edward Lemurc20978e2017-07-06 19:44:34 +020038#include "webrtc/rtc_base/checks.h"
39#include "webrtc/rtc_base/event.h"
40#include "webrtc/rtc_base/file.h"
41#include "webrtc/rtc_base/optional.h"
eladalon413ee9a2017-08-22 04:02:52 -070042#include "webrtc/rtc_base/ptr_util.h"
Edward Lemurc20978e2017-07-06 19:44:34 +020043#include "webrtc/rtc_base/random.h"
44#include "webrtc/rtc_base/rate_limiter.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010045#include "webrtc/system_wrappers/include/metrics.h"
asapersson01d70a32016-05-20 06:29:46 -070046#include "webrtc/system_wrappers/include/metrics_default.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010047#include "webrtc/system_wrappers/include/sleep.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000048#include "webrtc/test/call_test.h"
49#include "webrtc/test/direct_transport.h"
50#include "webrtc/test/encoder_settings.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000051#include "webrtc/test/fake_decoder.h"
52#include "webrtc/test/fake_encoder.h"
philipel266f0a42016-11-28 08:49:07 -080053#include "webrtc/test/field_trial.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000054#include "webrtc/test/frame_generator.h"
55#include "webrtc/test/frame_generator_capturer.h"
brandtr56e119e2017-05-19 10:33:03 -070056#include "webrtc/test/gmock.h"
brandtr5e171752017-05-23 03:32:16 -070057#include "webrtc/test/gtest.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000058#include "webrtc/test/null_transport.h"
asapersson@webrtc.org37c05592015-01-28 13:58:27 +000059#include "webrtc/test/rtcp_packet_parser.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000060#include "webrtc/test/rtp_rtcp_observer.h"
61#include "webrtc/test/testsupport/fileutils.h"
62#include "webrtc/test/testsupport/perf_test.h"
charujainbf6a45b2016-11-03 04:21:42 -070063#include "webrtc/video/transport_adapter.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000064
oprypin45197522017-06-22 01:47:20 -070065// Flaky under MemorySanitizer: bugs.webrtc.org/7419
aleloi7057b6b2017-03-29 02:07:33 -070066#if defined(MEMORY_SANITIZER)
oprypin45197522017-06-22 01:47:20 -070067#define MAYBE_InitialProbing DISABLED_InitialProbing
68// Fails on iOS bots: bugs.webrtc.org/7851
69#elif defined(TARGET_IPHONE_SIMULATOR) && TARGET_IPHONE_SIMULATOR
aleloi7057b6b2017-03-29 02:07:33 -070070#define MAYBE_InitialProbing DISABLED_InitialProbing
71#else
72#define MAYBE_InitialProbing InitialProbing
73#endif
74
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000075namespace webrtc {
76
minyue20c84cc2017-04-10 16:57:57 -070077namespace {
78constexpr int kSilenceTimeoutMs = 2000;
79}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000080
philipel277a8b52017-03-16 05:19:49 -070081class EndToEndTest : public test::CallTest {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000082 public:
philipel277a8b52017-03-16 05:19:49 -070083 EndToEndTest() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000084
85 virtual ~EndToEndTest() {
stefanff483612015-12-21 03:14:00 -080086 EXPECT_EQ(nullptr, video_send_stream_);
87 EXPECT_TRUE(video_receive_streams_.empty());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000088 }
89
90 protected:
pbos2d566682015-09-28 09:59:31 -070091 class UnusedTransport : public Transport {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000092 private:
stefan1d8a5062015-10-02 03:39:33 -070093 bool SendRtp(const uint8_t* packet,
94 size_t length,
95 const PacketOptions& options) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000096 ADD_FAILURE() << "Unexpected RTP sent.";
97 return false;
98 }
99
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000100 bool SendRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +0000101 ADD_FAILURE() << "Unexpected RTCP sent.";
102 return false;
103 }
104 };
105
skvlad7a43d252016-03-22 15:32:27 -0700106 class RequiredTransport : public Transport {
107 public:
108 RequiredTransport(bool rtp_required, bool rtcp_required)
109 : need_rtp_(rtp_required), need_rtcp_(rtcp_required) {}
110 ~RequiredTransport() {
111 if (need_rtp_) {
112 ADD_FAILURE() << "Expected RTP packet not sent.";
113 }
114 if (need_rtcp_) {
115 ADD_FAILURE() << "Expected RTCP packet not sent.";
116 }
117 }
118
119 private:
120 bool SendRtp(const uint8_t* packet,
121 size_t length,
122 const PacketOptions& options) override {
Taylor Brandstetter14cf12b2016-08-22 18:14:14 -0700123 rtc::CritScope lock(&crit_);
skvlad7a43d252016-03-22 15:32:27 -0700124 need_rtp_ = false;
125 return true;
126 }
127
128 bool SendRtcp(const uint8_t* packet, size_t length) override {
Taylor Brandstetter14cf12b2016-08-22 18:14:14 -0700129 rtc::CritScope lock(&crit_);
skvlad7a43d252016-03-22 15:32:27 -0700130 need_rtcp_ = false;
131 return true;
132 }
133 bool need_rtp_;
134 bool need_rtcp_;
Taylor Brandstetter14cf12b2016-08-22 18:14:14 -0700135 rtc::CriticalSection crit_;
skvlad7a43d252016-03-22 15:32:27 -0700136 };
137
Peter Boström39593972016-02-15 11:27:15 +0100138 void DecodesRetransmittedFrame(bool enable_rtx, bool enable_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000139 void ReceivesPliAndRecovers(int rtp_history_ms);
pbosda903ea2015-10-02 02:36:56 -0700140 void RespectsRtcpMode(RtcpMode rtcp_mode);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000141 void TestSendsSetSsrcs(size_t num_ssrcs, bool send_single_ssrc_first);
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200142 void TestRtpStatePreservation(bool use_rtx, bool provoke_rtcpsr_before_rtp);
sprangb4a1ae52015-12-03 08:10:08 -0800143 void VerifyHistogramStats(bool use_rtx, bool use_red, bool screenshare);
skvlad7a43d252016-03-22 15:32:27 -0700144 void VerifyNewVideoSendStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -0800145 MediaType network_to_bring_up,
skvlad7a43d252016-03-22 15:32:27 -0700146 VideoEncoder* encoder,
147 Transport* transport);
148 void VerifyNewVideoReceiveStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -0800149 MediaType network_to_bring_up,
skvlad7a43d252016-03-22 15:32:27 -0700150 Transport* transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000151};
152
philipel277a8b52017-03-16 05:19:49 -0700153TEST_F(EndToEndTest, ReceiverCanBeStartedTwice) {
philipel4fb651d2017-04-10 03:54:05 -0700154 CreateCalls(Call::Config(event_log_.get()), Call::Config(event_log_.get()));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000155
solenberg4fbae2b2015-08-28 04:07:10 -0700156 test::NullTransport transport;
brandtr841de6a2016-11-15 07:10:52 -0800157 CreateSendConfig(1, 0, 0, &transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700158 CreateMatchingReceiveConfigs(&transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000159
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100160 CreateVideoStreams();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000161
stefanff483612015-12-21 03:14:00 -0800162 video_receive_streams_[0]->Start();
163 video_receive_streams_[0]->Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000164
165 DestroyStreams();
166}
167
philipel277a8b52017-03-16 05:19:49 -0700168TEST_F(EndToEndTest, ReceiverCanBeStoppedTwice) {
philipel4fb651d2017-04-10 03:54:05 -0700169 CreateCalls(Call::Config(event_log_.get()), Call::Config(event_log_.get()));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000170
solenberg4fbae2b2015-08-28 04:07:10 -0700171 test::NullTransport transport;
brandtr841de6a2016-11-15 07:10:52 -0800172 CreateSendConfig(1, 0, 0, &transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700173 CreateMatchingReceiveConfigs(&transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000174
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100175 CreateVideoStreams();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000176
stefanff483612015-12-21 03:14:00 -0800177 video_receive_streams_[0]->Stop();
178 video_receive_streams_[0]->Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000179
180 DestroyStreams();
181}
182
philipel277a8b52017-03-16 05:19:49 -0700183TEST_F(EndToEndTest, ReceiverCanBeStoppedAndRestarted) {
philipel4fb651d2017-04-10 03:54:05 -0700184 CreateCalls(Call::Config(event_log_.get()), Call::Config(event_log_.get()));
sprang113bdca2016-10-11 03:10:10 -0700185
186 test::NullTransport transport;
brandtr841de6a2016-11-15 07:10:52 -0800187 CreateSendConfig(1, 0, 0, &transport);
sprang113bdca2016-10-11 03:10:10 -0700188 CreateMatchingReceiveConfigs(&transport);
189
190 CreateVideoStreams();
191
192 video_receive_streams_[0]->Stop();
193 video_receive_streams_[0]->Start();
194 video_receive_streams_[0]->Stop();
195
196 DestroyStreams();
197}
198
philipel277a8b52017-03-16 05:19:49 -0700199TEST_F(EndToEndTest, RendersSingleDelayedFrame) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000200 static const int kWidth = 320;
201 static const int kHeight = 240;
202 // This constant is chosen to be higher than the timeout in the video_render
203 // module. This makes sure that frames aren't dropped if there are no other
204 // frames in the queue.
nisse76bc8e82017-02-07 09:37:41 -0800205 static const int kRenderDelayMs = 1000;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000206
nisse7ade7b32016-03-23 04:48:10 -0700207 class Renderer : public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000208 public:
Peter Boström5811a392015-12-10 13:02:50 +0100209 Renderer() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000210
nisse76bc8e82017-02-07 09:37:41 -0800211 void OnFrame(const VideoFrame& video_frame) override {
212 SleepMs(kRenderDelayMs);
213 event_.Set();
214 }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000215
Peter Boström5811a392015-12-10 13:02:50 +0100216 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000217
Peter Boström5811a392015-12-10 13:02:50 +0100218 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000219 } renderer;
220
perkja49cbd32016-09-16 07:53:41 -0700221 test::FrameForwarder frame_forwarder;
eladalon413ee9a2017-08-22 04:02:52 -0700222 std::unique_ptr<test::DirectTransport> sender_transport;
223 std::unique_ptr<test::DirectTransport> receiver_transport;
perkja49cbd32016-09-16 07:53:41 -0700224
eladalon413ee9a2017-08-22 04:02:52 -0700225 task_queue_.SendTask([this, &renderer, &frame_forwarder, &sender_transport,
226 &receiver_transport]() {
227 CreateCalls(Call::Config(event_log_.get()), Call::Config(event_log_.get()));
228
229 sender_transport = rtc::MakeUnique<test::DirectTransport>(
230 &task_queue_, sender_call_.get(), payload_type_map_);
231 receiver_transport = rtc::MakeUnique<test::DirectTransport>(
232 &task_queue_, receiver_call_.get(), payload_type_map_);
233 sender_transport->SetReceiver(receiver_call_->Receiver());
234 receiver_transport->SetReceiver(sender_call_->Receiver());
235
236 CreateSendConfig(1, 0, 0, sender_transport.get());
237 CreateMatchingReceiveConfigs(receiver_transport.get());
238
239 video_receive_configs_[0].renderer = &renderer;
240
241 CreateVideoStreams();
242 Start();
243
244 // Create frames that are smaller than the send width/height, this is done
245 // to check that the callbacks are done after processing video.
246 std::unique_ptr<test::FrameGenerator> frame_generator(
247 test::FrameGenerator::CreateSquareGenerator(kWidth, kHeight));
248 video_send_stream_->SetSource(
249 &frame_forwarder,
250 VideoSendStream::DegradationPreference::kMaintainFramerate);
251
252 frame_forwarder.IncomingCapturedFrame(*frame_generator->NextFrame());
253 });
254
Peter Boström5811a392015-12-10 13:02:50 +0100255 EXPECT_TRUE(renderer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000256 << "Timed out while waiting for the frame to render.";
257
eladalon413ee9a2017-08-22 04:02:52 -0700258 task_queue_.SendTask([this, &sender_transport, &receiver_transport]() {
259 Stop();
260 DestroyStreams();
261 sender_transport.reset();
262 receiver_transport.reset();
263 DestroyCalls();
264 });
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000265}
266
philipel277a8b52017-03-16 05:19:49 -0700267TEST_F(EndToEndTest, TransmitsFirstFrame) {
nisse7ade7b32016-03-23 04:48:10 -0700268 class Renderer : public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000269 public:
Peter Boström5811a392015-12-10 13:02:50 +0100270 Renderer() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000271
nisseeb83a1a2016-03-21 01:27:56 -0700272 void OnFrame(const VideoFrame& video_frame) override { event_.Set(); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000273
Peter Boström5811a392015-12-10 13:02:50 +0100274 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000275
Peter Boström5811a392015-12-10 13:02:50 +0100276 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000277 } renderer;
278
eladalon413ee9a2017-08-22 04:02:52 -0700279 std::unique_ptr<test::FrameGenerator> frame_generator;
perkja49cbd32016-09-16 07:53:41 -0700280 test::FrameForwarder frame_forwarder;
eladalon413ee9a2017-08-22 04:02:52 -0700281
282 std::unique_ptr<test::DirectTransport> sender_transport;
283 std::unique_ptr<test::DirectTransport> receiver_transport;
284
285 task_queue_.SendTask([this, &renderer, &frame_generator, &frame_forwarder,
286 &sender_transport, &receiver_transport]() {
287 CreateCalls(Call::Config(event_log_.get()), Call::Config(event_log_.get()));
288
289 sender_transport = rtc::MakeUnique<test::DirectTransport>(
290 &task_queue_, sender_call_.get(), payload_type_map_);
291 receiver_transport = rtc::MakeUnique<test::DirectTransport>(
292 &task_queue_, receiver_call_.get(), payload_type_map_);
293 sender_transport->SetReceiver(receiver_call_->Receiver());
294 receiver_transport->SetReceiver(sender_call_->Receiver());
295
296 CreateSendConfig(1, 0, 0, sender_transport.get());
297 CreateMatchingReceiveConfigs(receiver_transport.get());
298 video_receive_configs_[0].renderer = &renderer;
299
300 CreateVideoStreams();
301 Start();
302
303 frame_generator = test::FrameGenerator::CreateSquareGenerator(
304 kDefaultWidth, kDefaultHeight);
305 video_send_stream_->SetSource(
306 &frame_forwarder,
307 VideoSendStream::DegradationPreference::kMaintainFramerate);
308 frame_forwarder.IncomingCapturedFrame(*frame_generator->NextFrame());
309 });
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000310
Peter Boström5811a392015-12-10 13:02:50 +0100311 EXPECT_TRUE(renderer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000312 << "Timed out while waiting for the frame to render.";
313
eladalon413ee9a2017-08-22 04:02:52 -0700314 task_queue_.SendTask([this, &sender_transport, &receiver_transport]() {
315 Stop();
316 DestroyStreams();
317 sender_transport.reset();
318 receiver_transport.reset();
319 DestroyCalls();
320 });
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000321}
322
Perba7dc722016-04-19 15:01:23 +0200323class CodecObserver : public test::EndToEndTest,
nisse7ade7b32016-03-23 04:48:10 -0700324 public rtc::VideoSinkInterface<VideoFrame> {
Perba7dc722016-04-19 15:01:23 +0200325 public:
326 CodecObserver(int no_frames_to_wait_for,
327 VideoRotation rotation_to_test,
328 const std::string& payload_name,
329 webrtc::VideoEncoder* encoder,
330 webrtc::VideoDecoder* decoder)
hta9aa96882016-12-06 05:36:03 -0800331 : EndToEndTest(4 * webrtc::EndToEndTest::kDefaultTimeoutMs),
332 // TODO(hta): This timeout (120 seconds) is excessive.
333 // https://bugs.webrtc.org/6830
Perba7dc722016-04-19 15:01:23 +0200334 no_frames_to_wait_for_(no_frames_to_wait_for),
335 expected_rotation_(rotation_to_test),
336 payload_name_(payload_name),
337 encoder_(encoder),
338 decoder_(decoder),
339 frame_counter_(0) {}
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000340
Perba7dc722016-04-19 15:01:23 +0200341 void PerformTest() override {
342 EXPECT_TRUE(Wait())
343 << "Timed out while waiting for enough frames to be decoded.";
344 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000345
Perba7dc722016-04-19 15:01:23 +0200346 void ModifyVideoConfigs(
347 VideoSendStream::Config* send_config,
348 std::vector<VideoReceiveStream::Config>* receive_configs,
349 VideoEncoderConfig* encoder_config) override {
350 send_config->encoder_settings.encoder = encoder_.get();
351 send_config->encoder_settings.payload_name = payload_name_;
minyue20c84cc2017-04-10 16:57:57 -0700352 send_config->encoder_settings.payload_type =
353 test::CallTest::kVideoSendPayloadType;
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000354
Perba7dc722016-04-19 15:01:23 +0200355 (*receive_configs)[0].renderer = this;
356 (*receive_configs)[0].decoders.resize(1);
357 (*receive_configs)[0].decoders[0].payload_type =
358 send_config->encoder_settings.payload_type;
359 (*receive_configs)[0].decoders[0].payload_name =
360 send_config->encoder_settings.payload_name;
361 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
362 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000363
Perba7dc722016-04-19 15:01:23 +0200364 void OnFrame(const VideoFrame& video_frame) override {
365 EXPECT_EQ(expected_rotation_, video_frame.rotation());
366 if (++frame_counter_ == no_frames_to_wait_for_)
367 observation_complete_.Set();
368 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000369
Perba7dc722016-04-19 15:01:23 +0200370 void OnFrameGeneratorCapturerCreated(
371 test::FrameGeneratorCapturer* frame_generator_capturer) override {
372 frame_generator_capturer->SetFakeRotation(expected_rotation_);
373 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000374
Perba7dc722016-04-19 15:01:23 +0200375 private:
376 int no_frames_to_wait_for_;
377 VideoRotation expected_rotation_;
378 std::string payload_name_;
379 std::unique_ptr<webrtc::VideoEncoder> encoder_;
380 std::unique_ptr<webrtc::VideoDecoder> decoder_;
381 int frame_counter_;
382};
383
philipel277a8b52017-03-16 05:19:49 -0700384TEST_F(EndToEndTest, SendsAndReceivesVP8) {
philipel266f0a42016-11-28 08:49:07 -0800385 CodecObserver test(5, kVideoRotation_0, "VP8", VP8Encoder::Create(),
386 VP8Decoder::Create());
387 RunBaseTest(&test);
388}
389
philipel277a8b52017-03-16 05:19:49 -0700390TEST_F(EndToEndTest, SendsAndReceivesVP8Rotation90) {
magjed509e4fe2016-11-18 01:34:11 -0800391 CodecObserver test(5, kVideoRotation_90, "VP8", VP8Encoder::Create(),
Perba7dc722016-04-19 15:01:23 +0200392 VP8Decoder::Create());
393 RunBaseTest(&test);
394}
395
Peter Boström12996152016-05-14 02:03:18 +0200396#if !defined(RTC_DISABLE_VP9)
philipel277a8b52017-03-16 05:19:49 -0700397TEST_F(EndToEndTest, SendsAndReceivesVP9) {
magjed509e4fe2016-11-18 01:34:11 -0800398 CodecObserver test(500, kVideoRotation_0, "VP9", VP9Encoder::Create(),
Perba7dc722016-04-19 15:01:23 +0200399 VP9Decoder::Create());
400 RunBaseTest(&test);
401}
402
philipel277a8b52017-03-16 05:19:49 -0700403TEST_F(EndToEndTest, SendsAndReceivesVP9VideoRotation90) {
magjed509e4fe2016-11-18 01:34:11 -0800404 CodecObserver test(5, kVideoRotation_90, "VP9", VP9Encoder::Create(),
Perba7dc722016-04-19 15:01:23 +0200405 VP9Decoder::Create());
stefane74eef12016-01-08 06:47:13 -0800406 RunBaseTest(&test);
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000407}
Peter Boström12996152016-05-14 02:03:18 +0200408#endif // !defined(RTC_DISABLE_VP9)
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000409
brandtr445fb8f2016-11-14 04:11:23 -0800410#if defined(WEBRTC_USE_H264)
philipel277a8b52017-03-16 05:19:49 -0700411TEST_F(EndToEndTest, SendsAndReceivesH264) {
magjedceecea42016-11-28 07:20:21 -0800412 CodecObserver test(500, kVideoRotation_0, "H264",
413 H264Encoder::Create(cricket::VideoCodec("H264")),
Perba7dc722016-04-19 15:01:23 +0200414 H264Decoder::Create());
415 RunBaseTest(&test);
416}
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000417
philipel277a8b52017-03-16 05:19:49 -0700418TEST_F(EndToEndTest, SendsAndReceivesH264VideoRotation90) {
magjedceecea42016-11-28 07:20:21 -0800419 CodecObserver test(5, kVideoRotation_90, "H264",
420 H264Encoder::Create(cricket::VideoCodec("H264")),
Perba7dc722016-04-19 15:01:23 +0200421 H264Decoder::Create());
stefane74eef12016-01-08 06:47:13 -0800422 RunBaseTest(&test);
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000423}
hta9aa96882016-12-06 05:36:03 -0800424
philipel277a8b52017-03-16 05:19:49 -0700425TEST_F(EndToEndTest, SendsAndReceivesH264PacketizationMode0) {
hta9aa96882016-12-06 05:36:03 -0800426 cricket::VideoCodec codec = cricket::VideoCodec("H264");
427 codec.SetParam(cricket::kH264FmtpPacketizationMode, "0");
428 CodecObserver test(500, kVideoRotation_0, "H264", H264Encoder::Create(codec),
429 H264Decoder::Create());
430 RunBaseTest(&test);
431}
432
philipel277a8b52017-03-16 05:19:49 -0700433TEST_F(EndToEndTest, SendsAndReceivesH264PacketizationMode1) {
hta9aa96882016-12-06 05:36:03 -0800434 cricket::VideoCodec codec = cricket::VideoCodec("H264");
435 codec.SetParam(cricket::kH264FmtpPacketizationMode, "1");
436 CodecObserver test(500, kVideoRotation_0, "H264", H264Encoder::Create(codec),
437 H264Decoder::Create());
438 RunBaseTest(&test);
439}
440
brandtr445fb8f2016-11-14 04:11:23 -0800441#endif // defined(WEBRTC_USE_H264)
hbosbab934b2016-01-27 01:36:03 -0800442
philipel277a8b52017-03-16 05:19:49 -0700443TEST_F(EndToEndTest, ReceiverUsesLocalSsrc) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000444 class SyncRtcpObserver : public test::EndToEndTest {
445 public:
446 SyncRtcpObserver() : EndToEndTest(kDefaultTimeoutMs) {}
447
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000448 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
danilchap3dc929e2016-11-02 08:21:59 -0700449 test::RtcpPacketParser parser;
450 EXPECT_TRUE(parser.Parse(packet, length));
451 EXPECT_EQ(kReceiverLocalVideoSsrc, parser.sender_ssrc());
Peter Boström5811a392015-12-10 13:02:50 +0100452 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000453
454 return SEND_PACKET;
455 }
456
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000457 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100458 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000459 << "Timed out while waiting for a receiver RTCP packet to be sent.";
460 }
461 } test;
462
stefane74eef12016-01-08 06:47:13 -0800463 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000464}
465
philipel277a8b52017-03-16 05:19:49 -0700466TEST_F(EndToEndTest, ReceivesAndRetransmitsNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000467 static const int kNumberOfNacksToObserve = 2;
468 static const int kLossBurstSize = 2;
469 static const int kPacketsBetweenLossBursts = 9;
470 class NackObserver : public test::EndToEndTest {
471 public:
472 NackObserver()
473 : EndToEndTest(kLongTimeoutMs),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000474 sent_rtp_packets_(0),
475 packets_left_to_drop_(0),
476 nacks_left_(kNumberOfNacksToObserve) {}
477
478 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000479 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700480 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000481 RTPHeader header;
Peter Boström03671cb2015-12-07 15:22:24 +0100482 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000483
484 // Never drop retransmitted packets.
485 if (dropped_packets_.find(header.sequenceNumber) !=
486 dropped_packets_.end()) {
487 retransmitted_packets_.insert(header.sequenceNumber);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000488 return SEND_PACKET;
489 }
490
philipel8054c7e2017-01-10 05:19:19 -0800491 if (nacks_left_ <= 0 &&
492 retransmitted_packets_.size() == dropped_packets_.size()) {
493 observation_complete_.Set();
494 }
495
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000496 ++sent_rtp_packets_;
497
498 // Enough NACKs received, stop dropping packets.
Stefan Holmer586b19b2015-09-18 11:14:31 +0200499 if (nacks_left_ <= 0)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000500 return SEND_PACKET;
501
502 // Check if it's time for a new loss burst.
503 if (sent_rtp_packets_ % kPacketsBetweenLossBursts == 0)
504 packets_left_to_drop_ = kLossBurstSize;
505
Stefan Holmer01b48882015-05-05 10:21:24 +0200506 // Never drop padding packets as those won't be retransmitted.
507 if (packets_left_to_drop_ > 0 && header.paddingLength == 0) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000508 --packets_left_to_drop_;
509 dropped_packets_.insert(header.sequenceNumber);
510 return DROP_PACKET;
511 }
512
513 return SEND_PACKET;
514 }
515
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000516 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700517 rtc::CritScope lock(&crit_);
danilchap3dc929e2016-11-02 08:21:59 -0700518 test::RtcpPacketParser parser;
519 EXPECT_TRUE(parser.Parse(packet, length));
520 nacks_left_ -= parser.nack()->num_packets();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000521 return SEND_PACKET;
522 }
523
stefanff483612015-12-21 03:14:00 -0800524 void ModifyVideoConfigs(
525 VideoSendStream::Config* send_config,
526 std::vector<VideoReceiveStream::Config>* receive_configs,
527 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000528 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000529 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000530 }
531
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000532 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100533 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000534 << "Timed out waiting for packets to be NACKed, retransmitted and "
535 "rendered.";
536 }
537
stefanf116bd02015-10-27 08:29:42 -0700538 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000539 std::set<uint16_t> dropped_packets_;
540 std::set<uint16_t> retransmitted_packets_;
541 uint64_t sent_rtp_packets_;
542 int packets_left_to_drop_;
stefanf116bd02015-10-27 08:29:42 -0700543 int nacks_left_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000544 } test;
545
stefane74eef12016-01-08 06:47:13 -0800546 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000547}
548
philipel277a8b52017-03-16 05:19:49 -0700549TEST_F(EndToEndTest, ReceivesNackAndRetransmitsAudio) {
Erik Språng737336d2016-07-29 12:59:36 +0200550 class NackObserver : public test::EndToEndTest {
551 public:
552 NackObserver()
553 : EndToEndTest(kLongTimeoutMs),
554 local_ssrc_(0),
555 remote_ssrc_(0),
556 receive_transport_(nullptr) {}
557
558 private:
559 size_t GetNumVideoStreams() const override { return 0; }
560 size_t GetNumAudioStreams() const override { return 1; }
561
eladalon413ee9a2017-08-22 04:02:52 -0700562 test::PacketTransport* CreateReceiveTransport(
563 test::SingleThreadedTaskQueueForTesting* task_queue) override {
Erik Språng737336d2016-07-29 12:59:36 +0200564 test::PacketTransport* receive_transport = new test::PacketTransport(
eladalon413ee9a2017-08-22 04:02:52 -0700565 task_queue, nullptr, this, test::PacketTransport::kReceiver,
566 payload_type_map_, FakeNetworkPipe::Config());
Erik Språng737336d2016-07-29 12:59:36 +0200567 receive_transport_ = receive_transport;
568 return receive_transport;
569 }
570
571 Action OnSendRtp(const uint8_t* packet, size_t length) override {
572 RTPHeader header;
573 EXPECT_TRUE(parser_->Parse(packet, length, &header));
574
575 if (!sequence_number_to_retransmit_) {
576 sequence_number_to_retransmit_ =
577 rtc::Optional<uint16_t>(header.sequenceNumber);
578
579 // Don't ask for retransmission straight away, may be deduped in pacer.
580 } else if (header.sequenceNumber == *sequence_number_to_retransmit_) {
581 observation_complete_.Set();
582 } else {
583 // Send a NACK as often as necessary until retransmission is received.
584 rtcp::Nack nack;
danilchap822a16f2016-09-27 09:27:47 -0700585 nack.SetSenderSsrc(local_ssrc_);
586 nack.SetMediaSsrc(remote_ssrc_);
Erik Språng737336d2016-07-29 12:59:36 +0200587 uint16_t nack_list[] = {*sequence_number_to_retransmit_};
danilchap822a16f2016-09-27 09:27:47 -0700588 nack.SetPacketIds(nack_list, 1);
Erik Språng737336d2016-07-29 12:59:36 +0200589 rtc::Buffer buffer = nack.Build();
590
591 EXPECT_TRUE(receive_transport_->SendRtcp(buffer.data(), buffer.size()));
592 }
593
594 return SEND_PACKET;
595 }
596
597 void ModifyAudioConfigs(
598 AudioSendStream::Config* send_config,
599 std::vector<AudioReceiveStream::Config>* receive_configs) override {
600 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
601 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
602 local_ssrc_ = (*receive_configs)[0].rtp.local_ssrc;
603 remote_ssrc_ = (*receive_configs)[0].rtp.remote_ssrc;
604 }
605
606 void PerformTest() override {
607 EXPECT_TRUE(Wait())
608 << "Timed out waiting for packets to be NACKed, retransmitted and "
609 "rendered.";
610 }
611
612 uint32_t local_ssrc_;
613 uint32_t remote_ssrc_;
614 Transport* receive_transport_;
615 rtc::Optional<uint16_t> sequence_number_to_retransmit_;
616 } test;
617
618 RunBaseTest(&test);
619}
620
brandtrc55f27a2017-03-20 06:32:59 -0700621TEST_F(EndToEndTest, ReceivesUlpfec) {
brandtr535830e2016-10-31 03:45:58 -0700622 class UlpfecRenderObserver : public test::EndToEndTest,
623 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000624 public:
brandtr535830e2016-10-31 03:45:58 -0700625 UlpfecRenderObserver()
brandtr1134b7b2017-02-06 06:35:47 -0800626 : EndToEndTest(kDefaultTimeoutMs),
brandtrc55f27a2017-03-20 06:32:59 -0700627 encoder_(VP8Encoder::Create()),
brandtr1134b7b2017-02-06 06:35:47 -0800628 random_(0xcafef00d1),
629 num_packets_sent_(0) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000630
631 private:
stefanf116bd02015-10-27 08:29:42 -0700632 Action OnSendRtp(const uint8_t* packet, size_t length) override {
633 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000634 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000635 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000636
brandtrc55f27a2017-03-20 06:32:59 -0700637 EXPECT_TRUE(header.payloadType == kVideoSendPayloadType ||
brandtr1134b7b2017-02-06 06:35:47 -0800638 header.payloadType == kRedPayloadType)
639 << "Unknown payload type received.";
640 EXPECT_EQ(kVideoSendSsrcs[0], header.ssrc) << "Unknown SSRC received.";
641
642 // Parse RED header.
Stefan Holmer01b48882015-05-05 10:21:24 +0200643 int encapsulated_payload_type = -1;
644 if (header.payloadType == kRedPayloadType) {
645 encapsulated_payload_type =
646 static_cast<int>(packet[header.headerLength]);
brandtr1134b7b2017-02-06 06:35:47 -0800647
brandtrc55f27a2017-03-20 06:32:59 -0700648 EXPECT_TRUE(encapsulated_payload_type == kVideoSendPayloadType ||
brandtr1134b7b2017-02-06 06:35:47 -0800649 encapsulated_payload_type == kUlpfecPayloadType)
650 << "Unknown encapsulated payload type received.";
Stefan Holmer01b48882015-05-05 10:21:24 +0200651 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000652
brandtrc55f27a2017-03-20 06:32:59 -0700653 // To minimize test flakiness, always let ULPFEC packets through.
brandtr1134b7b2017-02-06 06:35:47 -0800654 if (encapsulated_payload_type == kUlpfecPayloadType) {
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000655 return SEND_PACKET;
656 }
657
brandtr1134b7b2017-02-06 06:35:47 -0800658 // Simulate 5% video packet loss after rampup period. Record the
659 // corresponding timestamps that were dropped.
660 if (num_packets_sent_++ > 100 && random_.Rand(1, 100) <= 5) {
brandtrc55f27a2017-03-20 06:32:59 -0700661 if (encapsulated_payload_type == kVideoSendPayloadType) {
brandtr1134b7b2017-02-06 06:35:47 -0800662 dropped_sequence_numbers_.insert(header.sequenceNumber);
663 dropped_timestamps_.insert(header.timestamp);
664 }
brandtr1134b7b2017-02-06 06:35:47 -0800665 return DROP_PACKET;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000666 }
667
668 return SEND_PACKET;
669 }
670
nisseeb83a1a2016-03-21 01:27:56 -0700671 void OnFrame(const VideoFrame& video_frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200672 rtc::CritScope lock(&crit_);
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000673 // Rendering frame with timestamp of packet that was dropped -> FEC
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000674 // protection worked.
brandtr1134b7b2017-02-06 06:35:47 -0800675 auto it = dropped_timestamps_.find(video_frame.timestamp());
676 if (it != dropped_timestamps_.end()) {
Peter Boström5811a392015-12-10 13:02:50 +0100677 observation_complete_.Set();
brandtr1134b7b2017-02-06 06:35:47 -0800678 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000679 }
680
stefanff483612015-12-21 03:14:00 -0800681 void ModifyVideoConfigs(
682 VideoSendStream::Config* send_config,
683 std::vector<VideoReceiveStream::Config>* receive_configs,
684 VideoEncoderConfig* encoder_config) override {
brandtrc55f27a2017-03-20 06:32:59 -0700685 // Use VP8 instead of FAKE, since the latter does not have PictureID
686 // in the packetization headers.
687 send_config->encoder_settings.encoder = encoder_.get();
688 send_config->encoder_settings.payload_name = "VP8";
689 send_config->encoder_settings.payload_type = kVideoSendPayloadType;
690 VideoReceiveStream::Decoder decoder =
691 test::CreateMatchingDecoder(send_config->encoder_settings);
692 decoder_.reset(decoder.decoder);
693 (*receive_configs)[0].decoders.clear();
694 (*receive_configs)[0].decoders.push_back(decoder);
695
696 // Enable ULPFEC over RED.
brandtrb5f2c3f2016-10-04 23:28:39 -0700697 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
698 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
brandtrb5f2c3f2016-10-04 23:28:39 -0700699 (*receive_configs)[0].rtp.ulpfec.red_payload_type = kRedPayloadType;
700 (*receive_configs)[0].rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
brandtrc55f27a2017-03-20 06:32:59 -0700701
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000702 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000703 }
704
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000705 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100706 EXPECT_TRUE(Wait())
brandtr1e3dfbf2016-11-16 22:45:19 -0800707 << "Timed out waiting for dropped frames to be rendered.";
708 }
709
710 rtc::CriticalSection crit_;
brandtrc55f27a2017-03-20 06:32:59 -0700711 std::unique_ptr<VideoEncoder> encoder_;
712 std::unique_ptr<VideoDecoder> decoder_;
brandtr1134b7b2017-02-06 06:35:47 -0800713 std::set<uint32_t> dropped_sequence_numbers_ GUARDED_BY(crit_);
714 // Several packets can have the same timestamp.
715 std::multiset<uint32_t> dropped_timestamps_ GUARDED_BY(crit_);
716 Random random_;
brandtrc55f27a2017-03-20 06:32:59 -0700717 int num_packets_sent_ GUARDED_BY(crit_);
brandtr1e3dfbf2016-11-16 22:45:19 -0800718 } test;
719
720 RunBaseTest(&test);
721}
722
brandtrfa5a3682017-01-17 01:33:54 -0800723class FlexfecRenderObserver : public test::EndToEndTest,
724 public rtc::VideoSinkInterface<VideoFrame> {
725 public:
726 static constexpr uint32_t kVideoLocalSsrc = 123;
727 static constexpr uint32_t kFlexfecLocalSsrc = 456;
brandtr1e3dfbf2016-11-16 22:45:19 -0800728
brandtr1134b7b2017-02-06 06:35:47 -0800729 explicit FlexfecRenderObserver(bool enable_nack, bool expect_flexfec_rtcp)
brandtrfa5a3682017-01-17 01:33:54 -0800730 : test::EndToEndTest(test::CallTest::kDefaultTimeoutMs),
brandtr1134b7b2017-02-06 06:35:47 -0800731 enable_nack_(enable_nack),
brandtrfa5a3682017-01-17 01:33:54 -0800732 expect_flexfec_rtcp_(expect_flexfec_rtcp),
733 received_flexfec_rtcp_(false),
brandtr1134b7b2017-02-06 06:35:47 -0800734 random_(0xcafef00d1),
735 num_packets_sent_(0) {}
brandtr1e3dfbf2016-11-16 22:45:19 -0800736
brandtrfa5a3682017-01-17 01:33:54 -0800737 size_t GetNumFlexfecStreams() const override { return 1; }
brandtr1e3dfbf2016-11-16 22:45:19 -0800738
brandtrfa5a3682017-01-17 01:33:54 -0800739 private:
740 Action OnSendRtp(const uint8_t* packet, size_t length) override {
741 rtc::CritScope lock(&crit_);
742 RTPHeader header;
743 EXPECT_TRUE(parser_->Parse(packet, length, &header));
brandtr1e3dfbf2016-11-16 22:45:19 -0800744
brandtr1134b7b2017-02-06 06:35:47 -0800745 EXPECT_TRUE(header.payloadType ==
746 test::CallTest::kFakeVideoSendPayloadType ||
747 header.payloadType == test::CallTest::kFlexfecPayloadType ||
748 (enable_nack_ &&
749 header.payloadType == test::CallTest::kSendRtxPayloadType))
750 << "Unknown payload type received.";
751 EXPECT_TRUE(
752 header.ssrc == test::CallTest::kVideoSendSsrcs[0] ||
753 header.ssrc == test::CallTest::kFlexfecSendSsrc ||
754 (enable_nack_ && header.ssrc == test::CallTest::kSendRtxSsrcs[0]))
755 << "Unknown SSRC received.";
756
757 // To reduce test flakiness, always let FlexFEC packets through.
758 if (header.payloadType == test::CallTest::kFlexfecPayloadType) {
759 EXPECT_EQ(test::CallTest::kFlexfecSendSsrc, header.ssrc);
760
761 return SEND_PACKET;
brandtr1e3dfbf2016-11-16 22:45:19 -0800762 }
763
brandtr1134b7b2017-02-06 06:35:47 -0800764 // To reduce test flakiness, always let RTX packets through.
765 if (header.payloadType == test::CallTest::kSendRtxPayloadType) {
766 EXPECT_EQ(test::CallTest::kSendRtxSsrcs[0], header.ssrc);
767
768 // Parse RTX header.
769 uint16_t original_sequence_number =
770 ByteReader<uint16_t>::ReadBigEndian(&packet[header.headerLength]);
771
772 // From the perspective of FEC, a retransmitted packet is no longer
773 // dropped, so remove it from list of dropped packets.
774 auto seq_num_it =
775 dropped_sequence_numbers_.find(original_sequence_number);
brandtrfa5a3682017-01-17 01:33:54 -0800776 if (seq_num_it != dropped_sequence_numbers_.end()) {
777 dropped_sequence_numbers_.erase(seq_num_it);
778 auto ts_it = dropped_timestamps_.find(header.timestamp);
779 EXPECT_NE(ts_it, dropped_timestamps_.end());
780 dropped_timestamps_.erase(ts_it);
brandtrfd8d2652017-02-06 06:19:51 -0800781 }
brandtr1134b7b2017-02-06 06:35:47 -0800782
783 return SEND_PACKET;
brandtrfa5a3682017-01-17 01:33:54 -0800784 }
785
brandtr1134b7b2017-02-06 06:35:47 -0800786 // Simulate 5% video packet loss after rampup period. Record the
787 // corresponding timestamps that were dropped.
788 if (num_packets_sent_++ > 100 && random_.Rand(1, 100) <= 5) {
789 EXPECT_EQ(test::CallTest::kFakeVideoSendPayloadType, header.payloadType);
790 EXPECT_EQ(test::CallTest::kVideoSendSsrcs[0], header.ssrc);
791
792 dropped_sequence_numbers_.insert(header.sequenceNumber);
793 dropped_timestamps_.insert(header.timestamp);
brandtrfa5a3682017-01-17 01:33:54 -0800794
795 return DROP_PACKET;
796 }
797
798 return SEND_PACKET;
799 }
800
801 Action OnReceiveRtcp(const uint8_t* data, size_t length) override {
802 test::RtcpPacketParser parser;
803
804 parser.Parse(data, length);
805 if (parser.sender_ssrc() == kFlexfecLocalSsrc) {
806 EXPECT_EQ(1, parser.receiver_report()->num_packets());
807 const std::vector<rtcp::ReportBlock>& report_blocks =
808 parser.receiver_report()->report_blocks();
809 if (!report_blocks.empty()) {
810 EXPECT_EQ(1U, report_blocks.size());
811 EXPECT_EQ(test::CallTest::kFlexfecSendSsrc,
812 report_blocks[0].source_ssrc());
brandtr1d2d7892017-01-18 00:40:07 -0800813 rtc::CritScope lock(&crit_);
brandtrfa5a3682017-01-17 01:33:54 -0800814 received_flexfec_rtcp_ = true;
815 }
816 }
817
818 return SEND_PACKET;
819 }
820
eladalon413ee9a2017-08-22 04:02:52 -0700821 test::PacketTransport* CreateSendTransport(
822 test::SingleThreadedTaskQueueForTesting* task_queue,
823 Call* sender_call) override {
brandtr1134b7b2017-02-06 06:35:47 -0800824 // At low RTT (< kLowRttNackMs) -> NACK only, no FEC.
825 const int kNetworkDelayMs = 100;
826 FakeNetworkPipe::Config config;
827 config.queue_delay_ms = kNetworkDelayMs;
eladalon413ee9a2017-08-22 04:02:52 -0700828 return new test::PacketTransport(task_queue, sender_call, this,
nissee5ad5ca2017-03-29 23:57:43 -0700829 test::PacketTransport::kSender,
minyue20c84cc2017-04-10 16:57:57 -0700830 test::CallTest::payload_type_map_, config);
brandtr1134b7b2017-02-06 06:35:47 -0800831 }
832
brandtrfa5a3682017-01-17 01:33:54 -0800833 void OnFrame(const VideoFrame& video_frame) override {
brandtrcaea68f2017-08-23 00:55:17 -0700834 EXPECT_EQ(kVideoRotation_90, video_frame.rotation());
835
brandtrfa5a3682017-01-17 01:33:54 -0800836 rtc::CritScope lock(&crit_);
837 // Rendering frame with timestamp of packet that was dropped -> FEC
838 // protection worked.
839 auto it = dropped_timestamps_.find(video_frame.timestamp());
840 if (it != dropped_timestamps_.end()) {
841 if (!expect_flexfec_rtcp_ || received_flexfec_rtcp_) {
brandtr1e3dfbf2016-11-16 22:45:19 -0800842 observation_complete_.Set();
brandtrfa5a3682017-01-17 01:33:54 -0800843 }
brandtr1e3dfbf2016-11-16 22:45:19 -0800844 }
brandtrfa5a3682017-01-17 01:33:54 -0800845 }
brandtr1e3dfbf2016-11-16 22:45:19 -0800846
brandtrfa5a3682017-01-17 01:33:54 -0800847 void ModifyVideoConfigs(
848 VideoSendStream::Config* send_config,
849 std::vector<VideoReceiveStream::Config>* receive_configs,
850 VideoEncoderConfig* encoder_config) override {
851 (*receive_configs)[0].rtp.local_ssrc = kVideoLocalSsrc;
852 (*receive_configs)[0].renderer = this;
brandtr1134b7b2017-02-06 06:35:47 -0800853
854 if (enable_nack_) {
855 send_config->rtp.nack.rtp_history_ms = test::CallTest::kNackRtpHistoryMs;
856 send_config->rtp.ulpfec.red_rtx_payload_type =
857 test::CallTest::kRtxRedPayloadType;
858 send_config->rtp.rtx.ssrcs.push_back(test::CallTest::kSendRtxSsrcs[0]);
859 send_config->rtp.rtx.payload_type = test::CallTest::kSendRtxPayloadType;
860
861 (*receive_configs)[0].rtp.nack.rtp_history_ms =
862 test::CallTest::kNackRtpHistoryMs;
863 (*receive_configs)[0].rtp.ulpfec.red_rtx_payload_type =
864 test::CallTest::kRtxRedPayloadType;
865
866 (*receive_configs)[0].rtp.rtx_ssrc = test::CallTest::kSendRtxSsrcs[0];
867 (*receive_configs)[0]
nisse26e3abb2017-08-25 04:44:25 -0700868 .rtp
869 .rtx_associated_payload_types[test::CallTest::kSendRtxPayloadType] =
870 test::CallTest::kVideoSendPayloadType;
brandtr1134b7b2017-02-06 06:35:47 -0800871 }
brandtrfa5a3682017-01-17 01:33:54 -0800872 }
brandtr1e3dfbf2016-11-16 22:45:19 -0800873
brandtrcaea68f2017-08-23 00:55:17 -0700874 void OnFrameGeneratorCapturerCreated(
875 test::FrameGeneratorCapturer* frame_generator_capturer) override {
876 frame_generator_capturer->SetFakeRotation(kVideoRotation_90);
877 }
878
brandtrfa5a3682017-01-17 01:33:54 -0800879 void ModifyFlexfecConfigs(
880 std::vector<FlexfecReceiveStream::Config>* receive_configs) override {
881 (*receive_configs)[0].local_ssrc = kFlexfecLocalSsrc;
882 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000883
brandtrfa5a3682017-01-17 01:33:54 -0800884 void PerformTest() override {
885 EXPECT_TRUE(Wait())
886 << "Timed out waiting for dropped frames to be rendered.";
887 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000888
brandtrfa5a3682017-01-17 01:33:54 -0800889 rtc::CriticalSection crit_;
890 std::set<uint32_t> dropped_sequence_numbers_ GUARDED_BY(crit_);
brandtr1134b7b2017-02-06 06:35:47 -0800891 // Several packets can have the same timestamp.
brandtrfa5a3682017-01-17 01:33:54 -0800892 std::multiset<uint32_t> dropped_timestamps_ GUARDED_BY(crit_);
brandtr1134b7b2017-02-06 06:35:47 -0800893 const bool enable_nack_;
brandtr1d2d7892017-01-18 00:40:07 -0800894 const bool expect_flexfec_rtcp_;
895 bool received_flexfec_rtcp_ GUARDED_BY(crit_);
brandtrfa5a3682017-01-17 01:33:54 -0800896 Random random_;
brandtr1134b7b2017-02-06 06:35:47 -0800897 int num_packets_sent_;
brandtrfa5a3682017-01-17 01:33:54 -0800898};
899
philipel277a8b52017-03-16 05:19:49 -0700900TEST_F(EndToEndTest, RecoversWithFlexfec) {
brandtr1134b7b2017-02-06 06:35:47 -0800901 FlexfecRenderObserver test(false, false);
brandtrfa5a3682017-01-17 01:33:54 -0800902 RunBaseTest(&test);
903}
904
philipel277a8b52017-03-16 05:19:49 -0700905TEST_F(EndToEndTest, RecoversWithFlexfecAndNack) {
brandtr1134b7b2017-02-06 06:35:47 -0800906 FlexfecRenderObserver test(true, false);
907 RunBaseTest(&test);
908}
909
philipel277a8b52017-03-16 05:19:49 -0700910TEST_F(EndToEndTest, RecoversWithFlexfecAndSendsCorrespondingRtcp) {
brandtr1134b7b2017-02-06 06:35:47 -0800911 FlexfecRenderObserver test(false, true);
stefane74eef12016-01-08 06:47:13 -0800912 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000913}
914
philipel277a8b52017-03-16 05:19:49 -0700915TEST_F(EndToEndTest, ReceivedUlpfecPacketsNotNacked) {
brandtr535830e2016-10-31 03:45:58 -0700916 class UlpfecNackObserver : public test::EndToEndTest {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000917 public:
brandtr535830e2016-10-31 03:45:58 -0700918 UlpfecNackObserver()
stefanf116bd02015-10-27 08:29:42 -0700919 : EndToEndTest(kDefaultTimeoutMs),
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000920 state_(kFirstPacket),
brandtr535830e2016-10-31 03:45:58 -0700921 ulpfec_sequence_number_(0),
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000922 has_last_sequence_number_(false),
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200923 last_sequence_number_(0),
magjed509e4fe2016-11-18 01:34:11 -0800924 encoder_(VP8Encoder::Create()),
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200925 decoder_(VP8Decoder::Create()) {}
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000926
927 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000928 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -0800929 rtc::CritScope lock_(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000930 RTPHeader header;
931 EXPECT_TRUE(parser_->Parse(packet, length, &header));
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000932
Stefan Holmer01b48882015-05-05 10:21:24 +0200933 int encapsulated_payload_type = -1;
934 if (header.payloadType == kRedPayloadType) {
935 encapsulated_payload_type =
936 static_cast<int>(packet[header.headerLength]);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100937 if (encapsulated_payload_type != kFakeVideoSendPayloadType)
Stefan Holmer01b48882015-05-05 10:21:24 +0200938 EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
939 } else {
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100940 EXPECT_EQ(kFakeVideoSendPayloadType, header.payloadType);
Stefan Holmer01b48882015-05-05 10:21:24 +0200941 }
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000942
943 if (has_last_sequence_number_ &&
944 !IsNewerSequenceNumber(header.sequenceNumber,
945 last_sequence_number_)) {
946 // Drop retransmitted packets.
947 return DROP_PACKET;
948 }
949 last_sequence_number_ = header.sequenceNumber;
950 has_last_sequence_number_ = true;
951
brandtr535830e2016-10-31 03:45:58 -0700952 bool ulpfec_packet = encapsulated_payload_type == kUlpfecPayloadType;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000953 switch (state_) {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000954 case kFirstPacket:
brandtr535830e2016-10-31 03:45:58 -0700955 state_ = kDropEveryOtherPacketUntilUlpfec;
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000956 break;
brandtr535830e2016-10-31 03:45:58 -0700957 case kDropEveryOtherPacketUntilUlpfec:
958 if (ulpfec_packet) {
959 state_ = kDropAllMediaPacketsUntilUlpfec;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000960 } else if (header.sequenceNumber % 2 == 0) {
961 return DROP_PACKET;
962 }
963 break;
brandtr535830e2016-10-31 03:45:58 -0700964 case kDropAllMediaPacketsUntilUlpfec:
965 if (!ulpfec_packet)
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000966 return DROP_PACKET;
brandtr535830e2016-10-31 03:45:58 -0700967 ulpfec_sequence_number_ = header.sequenceNumber;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200968 state_ = kDropOneMediaPacket;
969 break;
970 case kDropOneMediaPacket:
brandtr535830e2016-10-31 03:45:58 -0700971 if (ulpfec_packet)
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200972 return DROP_PACKET;
973 state_ = kPassOneMediaPacket;
974 return DROP_PACKET;
975 break;
976 case kPassOneMediaPacket:
brandtr535830e2016-10-31 03:45:58 -0700977 if (ulpfec_packet)
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200978 return DROP_PACKET;
979 // Pass one media packet after dropped packet after last FEC,
980 // otherwise receiver might never see a seq_no after
brandtr535830e2016-10-31 03:45:58 -0700981 // |ulpfec_sequence_number_|
982 state_ = kVerifyUlpfecPacketNotInNackList;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000983 break;
brandtr535830e2016-10-31 03:45:58 -0700984 case kVerifyUlpfecPacketNotInNackList:
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000985 // Continue to drop packets. Make sure no frame can be decoded.
brandtr535830e2016-10-31 03:45:58 -0700986 if (ulpfec_packet || header.sequenceNumber % 2 == 0)
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000987 return DROP_PACKET;
988 break;
989 }
990 return SEND_PACKET;
991 }
992
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000993 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -0800994 rtc::CritScope lock_(&crit_);
brandtr535830e2016-10-31 03:45:58 -0700995 if (state_ == kVerifyUlpfecPacketNotInNackList) {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000996 test::RtcpPacketParser rtcp_parser;
997 rtcp_parser.Parse(packet, length);
Danil Chapovalovba6f7be2016-09-02 18:29:10 +0200998 const std::vector<uint16_t>& nacks = rtcp_parser.nack()->packet_ids();
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200999 EXPECT_TRUE(std::find(nacks.begin(), nacks.end(),
brandtr535830e2016-10-31 03:45:58 -07001000 ulpfec_sequence_number_) == nacks.end())
1001 << "Got nack for ULPFEC packet";
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001002 if (!nacks.empty() &&
brandtr535830e2016-10-31 03:45:58 -07001003 IsNewerSequenceNumber(nacks.back(), ulpfec_sequence_number_)) {
Peter Boström5811a392015-12-10 13:02:50 +01001004 observation_complete_.Set();
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001005 }
1006 }
1007 return SEND_PACKET;
1008 }
1009
eladalon413ee9a2017-08-22 04:02:52 -07001010 test::PacketTransport* CreateSendTransport(
1011 test::SingleThreadedTaskQueueForTesting* task_queue,
1012 Call* sender_call) override {
stefane74eef12016-01-08 06:47:13 -08001013 // At low RTT (< kLowRttNackMs) -> NACK only, no FEC.
1014 // Configure some network delay.
1015 const int kNetworkDelayMs = 50;
1016 FakeNetworkPipe::Config config;
1017 config.queue_delay_ms = kNetworkDelayMs;
eladalon413ee9a2017-08-22 04:02:52 -07001018 return new test::PacketTransport(task_queue, sender_call, this,
nissee5ad5ca2017-03-29 23:57:43 -07001019 test::PacketTransport::kSender,
minyue20c84cc2017-04-10 16:57:57 -07001020 payload_type_map_, config);
stefane74eef12016-01-08 06:47:13 -08001021 }
1022
Stefan Holmere5904162015-03-26 11:11:06 +01001023 // TODO(holmer): Investigate why we don't send FEC packets when the bitrate
1024 // is 10 kbps.
1025 Call::Config GetSenderCallConfig() override {
philipel4fb651d2017-04-10 03:54:05 -07001026 Call::Config config(event_log_.get());
Stefan Holmere5904162015-03-26 11:11:06 +01001027 const int kMinBitrateBps = 30000;
1028 config.bitrate_config.min_bitrate_bps = kMinBitrateBps;
1029 return config;
1030 }
1031
stefanff483612015-12-21 03:14:00 -08001032 void ModifyVideoConfigs(
1033 VideoSendStream::Config* send_config,
1034 std::vector<VideoReceiveStream::Config>* receive_configs,
1035 VideoEncoderConfig* encoder_config) override {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001036 // Configure hybrid NACK/FEC.
1037 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
brandtrb5f2c3f2016-10-04 23:28:39 -07001038 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
1039 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
Danil Chapovalov895a2d22016-05-27 14:12:09 +02001040 // Set codec to VP8, otherwise NACK/FEC hybrid will be disabled.
1041 send_config->encoder_settings.encoder = encoder_.get();
1042 send_config->encoder_settings.payload_name = "VP8";
1043 send_config->encoder_settings.payload_type = kFakeVideoSendPayloadType;
Danil Chapovalov895a2d22016-05-27 14:12:09 +02001044
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001045 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
brandtrb5f2c3f2016-10-04 23:28:39 -07001046 (*receive_configs)[0].rtp.ulpfec.red_payload_type = kRedPayloadType;
1047 (*receive_configs)[0].rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
Danil Chapovalov895a2d22016-05-27 14:12:09 +02001048
1049 (*receive_configs)[0].decoders.resize(1);
1050 (*receive_configs)[0].decoders[0].payload_type =
1051 send_config->encoder_settings.payload_type;
1052 (*receive_configs)[0].decoders[0].payload_name =
1053 send_config->encoder_settings.payload_name;
1054 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001055 }
1056
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001057 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001058 EXPECT_TRUE(Wait())
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001059 << "Timed out while waiting for FEC packets to be received.";
1060 }
1061
1062 enum {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +00001063 kFirstPacket,
brandtr535830e2016-10-31 03:45:58 -07001064 kDropEveryOtherPacketUntilUlpfec,
1065 kDropAllMediaPacketsUntilUlpfec,
Danil Chapovalov895a2d22016-05-27 14:12:09 +02001066 kDropOneMediaPacket,
1067 kPassOneMediaPacket,
brandtr535830e2016-10-31 03:45:58 -07001068 kVerifyUlpfecPacketNotInNackList,
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001069 } state_;
1070
stefan608213e2015-11-01 14:56:10 -08001071 rtc::CriticalSection crit_;
brandtr535830e2016-10-31 03:45:58 -07001072 uint16_t ulpfec_sequence_number_ GUARDED_BY(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001073 bool has_last_sequence_number_;
1074 uint16_t last_sequence_number_;
Danil Chapovalov895a2d22016-05-27 14:12:09 +02001075 std::unique_ptr<webrtc::VideoEncoder> encoder_;
1076 std::unique_ptr<webrtc::VideoDecoder> decoder_;
stefanf116bd02015-10-27 08:29:42 -07001077 } test;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001078
stefane74eef12016-01-08 06:47:13 -08001079 RunBaseTest(&test);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +00001080}
1081
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001082// This test drops second RTP packet with a marker bit set, makes sure it's
1083// retransmitted and renders. Retransmission SSRCs are also checked.
Peter Boström39593972016-02-15 11:27:15 +01001084void EndToEndTest::DecodesRetransmittedFrame(bool enable_rtx, bool enable_red) {
Peter Boström67680c12016-02-17 11:10:04 +01001085 static const int kDroppedFrameNumber = 10;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001086 class RetransmissionObserver : public test::EndToEndTest,
nisse76bc8e82017-02-07 09:37:41 -08001087 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001088 public:
Peter Boström39593972016-02-15 11:27:15 +01001089 RetransmissionObserver(bool enable_rtx, bool enable_red)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001090 : EndToEndTest(kDefaultTimeoutMs),
Peter Boström39593972016-02-15 11:27:15 +01001091 payload_type_(GetPayloadType(false, enable_red)),
1092 retransmission_ssrc_(enable_rtx ? kSendRtxSsrcs[0]
1093 : kVideoSendSsrcs[0]),
1094 retransmission_payload_type_(GetPayloadType(enable_rtx, enable_red)),
magjed509e4fe2016-11-18 01:34:11 -08001095 encoder_(VP8Encoder::Create()),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001096 marker_bits_observed_(0),
danilchap192717e2016-07-25 08:20:51 -07001097 retransmitted_timestamp_(0) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001098
1099 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001100 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -07001101 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001102 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001103 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001104
Peter Boström67680c12016-02-17 11:10:04 +01001105 // Ignore padding-only packets over RTX.
1106 if (header.payloadType != payload_type_) {
1107 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
1108 if (length == header.headerLength + header.paddingLength)
1109 return SEND_PACKET;
Stefan Holmer586b19b2015-09-18 11:14:31 +02001110 }
Peter Boström67680c12016-02-17 11:10:04 +01001111
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001112 if (header.timestamp == retransmitted_timestamp_) {
1113 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
1114 EXPECT_EQ(retransmission_payload_type_, header.payloadType);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001115 return SEND_PACKET;
1116 }
1117
Stefan Holmer586b19b2015-09-18 11:14:31 +02001118 // Found the final packet of the frame to inflict loss to, drop this and
1119 // expect a retransmission.
danilchapfdd381c2016-07-25 04:03:20 -07001120 if (header.payloadType == payload_type_ && header.markerBit &&
1121 ++marker_bits_observed_ == kDroppedFrameNumber) {
Danil Chapovalov18c65a42016-06-29 15:29:34 +02001122 // This should be the only dropped packet.
1123 EXPECT_EQ(0u, retransmitted_timestamp_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001124 retransmitted_timestamp_ = header.timestamp;
danilchap192717e2016-07-25 08:20:51 -07001125 if (std::find(rendered_timestamps_.begin(), rendered_timestamps_.end(),
1126 retransmitted_timestamp_) != rendered_timestamps_.end()) {
1127 // Frame was rendered before last packet was scheduled for sending.
1128 // This is extremly rare but possible scenario because prober able to
1129 // resend packet before it was send.
1130 // TODO(danilchap): Remove this corner case when prober would not be
1131 // able to sneak in between packet saved to history for resending and
1132 // pacer notified about existance of that packet for sending.
1133 // See https://bugs.chromium.org/p/webrtc/issues/detail?id=5540 for
1134 // details.
1135 observation_complete_.Set();
1136 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001137 return DROP_PACKET;
1138 }
1139
1140 return SEND_PACKET;
1141 }
1142
nisse76bc8e82017-02-07 09:37:41 -08001143 void OnFrame(const VideoFrame& frame) override {
brandtrcaea68f2017-08-23 00:55:17 -07001144 EXPECT_EQ(kVideoRotation_90, frame.rotation());
stefan5d837802017-02-08 07:09:05 -08001145 {
1146 rtc::CritScope lock(&crit_);
1147 if (frame.timestamp() == retransmitted_timestamp_)
1148 observation_complete_.Set();
1149 rendered_timestamps_.push_back(frame.timestamp());
1150 }
nisse76bc8e82017-02-07 09:37:41 -08001151 orig_renderer_->OnFrame(frame);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001152 }
1153
stefanff483612015-12-21 03:14:00 -08001154 void ModifyVideoConfigs(
1155 VideoSendStream::Config* send_config,
1156 std::vector<VideoReceiveStream::Config>* receive_configs,
1157 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001158 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
nisse76bc8e82017-02-07 09:37:41 -08001159
1160 // Insert ourselves into the rendering pipeline.
1161 RTC_DCHECK(!orig_renderer_);
1162 orig_renderer_ = (*receive_configs)[0].renderer;
1163 RTC_DCHECK(orig_renderer_);
stefan5d837802017-02-08 07:09:05 -08001164 (*receive_configs)[0].disable_prerenderer_smoothing = true;
nisse76bc8e82017-02-07 09:37:41 -08001165 (*receive_configs)[0].renderer = this;
1166
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001167 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
Shao Changbine62202f2015-04-21 20:24:50 +08001168
1169 if (payload_type_ == kRedPayloadType) {
brandtrb5f2c3f2016-10-04 23:28:39 -07001170 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
1171 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
Stefan Holmer10880012016-02-03 13:29:59 +01001172 if (retransmission_ssrc_ == kSendRtxSsrcs[0])
brandtrb5f2c3f2016-10-04 23:28:39 -07001173 send_config->rtp.ulpfec.red_rtx_payload_type = kRtxRedPayloadType;
1174 (*receive_configs)[0].rtp.ulpfec.ulpfec_payload_type =
1175 send_config->rtp.ulpfec.ulpfec_payload_type;
1176 (*receive_configs)[0].rtp.ulpfec.red_payload_type =
1177 send_config->rtp.ulpfec.red_payload_type;
1178 (*receive_configs)[0].rtp.ulpfec.red_rtx_payload_type =
1179 send_config->rtp.ulpfec.red_rtx_payload_type;
Shao Changbine62202f2015-04-21 20:24:50 +08001180 }
1181
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001182 if (retransmission_ssrc_ == kSendRtxSsrcs[0]) {
1183 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001184 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
brandtr14742122017-01-27 04:53:07 -08001185 (*receive_configs)[0].rtp.rtx_ssrc = kSendRtxSsrcs[0];
nisse26e3abb2017-08-25 04:44:25 -07001186 (*receive_configs)[0]
nisse5c0f6c62017-09-04 03:14:40 -07001187 .rtp.rtx_associated_payload_types[(payload_type_ == kRedPayloadType)
1188 ? kRtxRedPayloadType
1189 : kSendRtxPayloadType] =
nisse26e3abb2017-08-25 04:44:25 -07001190 payload_type_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001191 }
Peter Boström39593972016-02-15 11:27:15 +01001192 // Configure encoding and decoding with VP8, since generic packetization
1193 // doesn't support FEC with NACK.
kwibergaf476c72016-11-28 15:21:39 -08001194 RTC_DCHECK_EQ(1, (*receive_configs)[0].decoders.size());
Peter Boström39593972016-02-15 11:27:15 +01001195 send_config->encoder_settings.encoder = encoder_.get();
1196 send_config->encoder_settings.payload_name = "VP8";
1197 (*receive_configs)[0].decoders[0].payload_name = "VP8";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001198 }
1199
brandtrcaea68f2017-08-23 00:55:17 -07001200 void OnFrameGeneratorCapturerCreated(
1201 test::FrameGeneratorCapturer* frame_generator_capturer) override {
1202 frame_generator_capturer->SetFakeRotation(kVideoRotation_90);
1203 }
1204
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001205 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001206 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001207 << "Timed out while waiting for retransmission to render.";
1208 }
1209
Shao Changbine62202f2015-04-21 20:24:50 +08001210 int GetPayloadType(bool use_rtx, bool use_red) {
Stefan Holmer10880012016-02-03 13:29:59 +01001211 if (use_red) {
1212 if (use_rtx)
1213 return kRtxRedPayloadType;
1214 return kRedPayloadType;
1215 }
1216 if (use_rtx)
1217 return kSendRtxPayloadType;
1218 return kFakeVideoSendPayloadType;
Shao Changbine62202f2015-04-21 20:24:50 +08001219 }
1220
stefanf116bd02015-10-27 08:29:42 -07001221 rtc::CriticalSection crit_;
nisse76bc8e82017-02-07 09:37:41 -08001222 rtc::VideoSinkInterface<VideoFrame>* orig_renderer_ = nullptr;
Shao Changbine62202f2015-04-21 20:24:50 +08001223 const int payload_type_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001224 const uint32_t retransmission_ssrc_;
1225 const int retransmission_payload_type_;
kwiberg27f982b2016-03-01 11:52:33 -08001226 std::unique_ptr<VideoEncoder> encoder_;
Peter Boström39593972016-02-15 11:27:15 +01001227 const std::string payload_name_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001228 int marker_bits_observed_;
stefanf116bd02015-10-27 08:29:42 -07001229 uint32_t retransmitted_timestamp_ GUARDED_BY(&crit_);
danilchap192717e2016-07-25 08:20:51 -07001230 std::vector<uint32_t> rendered_timestamps_ GUARDED_BY(&crit_);
Peter Boström39593972016-02-15 11:27:15 +01001231 } test(enable_rtx, enable_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001232
stefane74eef12016-01-08 06:47:13 -08001233 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001234}
1235
philipel277a8b52017-03-16 05:19:49 -07001236TEST_F(EndToEndTest, DecodesRetransmittedFrame) {
Shao Changbine62202f2015-04-21 20:24:50 +08001237 DecodesRetransmittedFrame(false, false);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001238}
1239
philipel277a8b52017-03-16 05:19:49 -07001240TEST_F(EndToEndTest, DecodesRetransmittedFrameOverRtx) {
Shao Changbine62202f2015-04-21 20:24:50 +08001241 DecodesRetransmittedFrame(true, false);
1242}
1243
philipel277a8b52017-03-16 05:19:49 -07001244TEST_F(EndToEndTest, DecodesRetransmittedFrameByRed) {
Shao Changbine62202f2015-04-21 20:24:50 +08001245 DecodesRetransmittedFrame(false, true);
1246}
1247
philipel277a8b52017-03-16 05:19:49 -07001248TEST_F(EndToEndTest, DecodesRetransmittedFrameByRedOverRtx) {
Shao Changbine62202f2015-04-21 20:24:50 +08001249 DecodesRetransmittedFrame(true, true);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001250}
1251
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001252void EndToEndTest::ReceivesPliAndRecovers(int rtp_history_ms) {
1253 static const int kPacketsToDrop = 1;
1254
nisse7ade7b32016-03-23 04:48:10 -07001255 class PliObserver : public test::EndToEndTest,
1256 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001257 public:
1258 explicit PliObserver(int rtp_history_ms)
1259 : EndToEndTest(kLongTimeoutMs),
1260 rtp_history_ms_(rtp_history_ms),
1261 nack_enabled_(rtp_history_ms > 0),
1262 highest_dropped_timestamp_(0),
1263 frames_to_drop_(0),
1264 received_pli_(false) {}
1265
1266 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001267 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -07001268 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001269 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001270 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001271
1272 // Drop all retransmitted packets to force a PLI.
1273 if (header.timestamp <= highest_dropped_timestamp_)
1274 return DROP_PACKET;
1275
1276 if (frames_to_drop_ > 0) {
1277 highest_dropped_timestamp_ = header.timestamp;
1278 --frames_to_drop_;
1279 return DROP_PACKET;
1280 }
1281
1282 return SEND_PACKET;
1283 }
1284
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001285 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -07001286 rtc::CritScope lock(&crit_);
danilchap3dc929e2016-11-02 08:21:59 -07001287 test::RtcpPacketParser parser;
1288 EXPECT_TRUE(parser.Parse(packet, length));
1289 if (!nack_enabled_)
1290 EXPECT_EQ(0, parser.nack()->num_packets());
1291 if (parser.pli()->num_packets() > 0)
1292 received_pli_ = true;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001293 return SEND_PACKET;
1294 }
1295
nisseeb83a1a2016-03-21 01:27:56 -07001296 void OnFrame(const VideoFrame& video_frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02001297 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001298 if (received_pli_ &&
1299 video_frame.timestamp() > highest_dropped_timestamp_) {
Peter Boström5811a392015-12-10 13:02:50 +01001300 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001301 }
1302 if (!received_pli_)
1303 frames_to_drop_ = kPacketsToDrop;
1304 }
1305
stefanff483612015-12-21 03:14:00 -08001306 void ModifyVideoConfigs(
1307 VideoSendStream::Config* send_config,
1308 std::vector<VideoReceiveStream::Config>* receive_configs,
1309 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001310 send_config->rtp.nack.rtp_history_ms = rtp_history_ms_;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001311 (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms_;
1312 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001313 }
1314
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001315 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001316 EXPECT_TRUE(Wait()) << "Timed out waiting for PLI to be "
1317 "received and a frame to be "
1318 "rendered afterwards.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001319 }
1320
stefanf116bd02015-10-27 08:29:42 -07001321 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001322 int rtp_history_ms_;
1323 bool nack_enabled_;
stefanf116bd02015-10-27 08:29:42 -07001324 uint32_t highest_dropped_timestamp_ GUARDED_BY(&crit_);
1325 int frames_to_drop_ GUARDED_BY(&crit_);
1326 bool received_pli_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001327 } test(rtp_history_ms);
1328
stefane74eef12016-01-08 06:47:13 -08001329 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001330}
1331
philipel277a8b52017-03-16 05:19:49 -07001332TEST_F(EndToEndTest, ReceivesPliAndRecoversWithNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001333 ReceivesPliAndRecovers(1000);
1334}
1335
philipel277a8b52017-03-16 05:19:49 -07001336TEST_F(EndToEndTest, ReceivesPliAndRecoversWithoutNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001337 ReceivesPliAndRecovers(0);
1338}
1339
philipel277a8b52017-03-16 05:19:49 -07001340TEST_F(EndToEndTest, UnknownRtpPacketGivesUnknownSsrcReturnCode) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001341 class PacketInputObserver : public PacketReceiver {
1342 public:
1343 explicit PacketInputObserver(PacketReceiver* receiver)
Peter Boström5811a392015-12-10 13:02:50 +01001344 : receiver_(receiver), delivered_packet_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001345
Peter Boström5811a392015-12-10 13:02:50 +01001346 bool Wait() { return delivered_packet_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001347
1348 private:
stefan68786d22015-09-08 05:36:15 -07001349 DeliveryStatus DeliverPacket(MediaType media_type,
1350 const uint8_t* packet,
1351 size_t length,
1352 const PacketTime& packet_time) override {
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001353 if (RtpHeaderParser::IsRtcp(packet, length)) {
stefan68786d22015-09-08 05:36:15 -07001354 return receiver_->DeliverPacket(media_type, packet, length,
1355 packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001356 } else {
1357 DeliveryStatus delivery_status =
stefan68786d22015-09-08 05:36:15 -07001358 receiver_->DeliverPacket(media_type, packet, length, packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001359 EXPECT_EQ(DELIVERY_UNKNOWN_SSRC, delivery_status);
Peter Boström5811a392015-12-10 13:02:50 +01001360 delivered_packet_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001361 return delivery_status;
1362 }
1363 }
1364
1365 PacketReceiver* receiver_;
Peter Boström5811a392015-12-10 13:02:50 +01001366 rtc::Event delivered_packet_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001367 };
1368
eladalon413ee9a2017-08-22 04:02:52 -07001369 std::unique_ptr<test::DirectTransport> send_transport;
1370 std::unique_ptr<test::DirectTransport> receive_transport;
1371 std::unique_ptr<PacketInputObserver> input_observer;
solenberg4fbae2b2015-08-28 04:07:10 -07001372
eladalon413ee9a2017-08-22 04:02:52 -07001373 task_queue_.SendTask([this, &send_transport, &receive_transport,
1374 &input_observer]() {
1375 CreateCalls(Call::Config(event_log_.get()), Call::Config(event_log_.get()));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001376
eladalon413ee9a2017-08-22 04:02:52 -07001377 send_transport = rtc::MakeUnique<test::DirectTransport>(
1378 &task_queue_, sender_call_.get(), payload_type_map_);
1379 receive_transport = rtc::MakeUnique<test::DirectTransport>(
1380 &task_queue_, receiver_call_.get(), payload_type_map_);
1381 input_observer =
1382 rtc::MakeUnique<PacketInputObserver>(receiver_call_->Receiver());
1383 send_transport->SetReceiver(input_observer.get());
1384 receive_transport->SetReceiver(sender_call_->Receiver());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001385
eladalon413ee9a2017-08-22 04:02:52 -07001386 CreateSendConfig(1, 0, 0, send_transport.get());
1387 CreateMatchingReceiveConfigs(receive_transport.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001388
eladalon413ee9a2017-08-22 04:02:52 -07001389 CreateVideoStreams();
1390 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
1391 kDefaultHeight);
1392 Start();
1393
1394 receiver_call_->DestroyVideoReceiveStream(video_receive_streams_[0]);
1395 video_receive_streams_.clear();
1396 });
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001397
1398 // Wait() waits for a received packet.
eladalon413ee9a2017-08-22 04:02:52 -07001399 EXPECT_TRUE(input_observer->Wait());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001400
eladalon413ee9a2017-08-22 04:02:52 -07001401 task_queue_.SendTask([this, &send_transport, &receive_transport]() {
1402 Stop();
1403 DestroyStreams();
1404 send_transport.reset();
1405 receive_transport.reset();
1406 DestroyCalls();
1407 });
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001408}
1409
pbosda903ea2015-10-02 02:36:56 -07001410void EndToEndTest::RespectsRtcpMode(RtcpMode rtcp_mode) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001411 static const int kNumCompoundRtcpPacketsToObserve = 10;
1412 class RtcpModeObserver : public test::EndToEndTest {
1413 public:
pbosda903ea2015-10-02 02:36:56 -07001414 explicit RtcpModeObserver(RtcpMode rtcp_mode)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001415 : EndToEndTest(kDefaultTimeoutMs),
1416 rtcp_mode_(rtcp_mode),
1417 sent_rtp_(0),
1418 sent_rtcp_(0) {}
1419
1420 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001421 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanb77c7162017-02-06 06:29:38 -08001422 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001423 if (++sent_rtp_ % 3 == 0)
1424 return DROP_PACKET;
1425
1426 return SEND_PACKET;
1427 }
1428
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001429 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanb77c7162017-02-06 06:29:38 -08001430 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001431 ++sent_rtcp_;
danilchap3dc929e2016-11-02 08:21:59 -07001432 test::RtcpPacketParser parser;
1433 EXPECT_TRUE(parser.Parse(packet, length));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001434
danilchap3dc929e2016-11-02 08:21:59 -07001435 EXPECT_EQ(0, parser.sender_report()->num_packets());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001436
1437 switch (rtcp_mode_) {
pbosda903ea2015-10-02 02:36:56 -07001438 case RtcpMode::kCompound:
stefanb77c7162017-02-06 06:29:38 -08001439 // TODO(holmer): We shouldn't send transport feedback alone if
1440 // compound RTCP is negotiated.
1441 if (parser.receiver_report()->num_packets() == 0 &&
1442 parser.transport_feedback()->num_packets() == 0) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001443 ADD_FAILURE() << "Received RTCP packet without receiver report for "
pbosda903ea2015-10-02 02:36:56 -07001444 "RtcpMode::kCompound.";
Peter Boström5811a392015-12-10 13:02:50 +01001445 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001446 }
1447
1448 if (sent_rtcp_ >= kNumCompoundRtcpPacketsToObserve)
Peter Boström5811a392015-12-10 13:02:50 +01001449 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001450
1451 break;
pbosda903ea2015-10-02 02:36:56 -07001452 case RtcpMode::kReducedSize:
danilchap3dc929e2016-11-02 08:21:59 -07001453 if (parser.receiver_report()->num_packets() == 0)
Peter Boström5811a392015-12-10 13:02:50 +01001454 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001455 break;
pbosda903ea2015-10-02 02:36:56 -07001456 case RtcpMode::kOff:
1457 RTC_NOTREACHED();
1458 break;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001459 }
1460
1461 return SEND_PACKET;
1462 }
1463
stefanff483612015-12-21 03:14:00 -08001464 void ModifyVideoConfigs(
1465 VideoSendStream::Config* send_config,
1466 std::vector<VideoReceiveStream::Config>* receive_configs,
1467 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001468 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001469 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
1470 (*receive_configs)[0].rtp.rtcp_mode = rtcp_mode_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001471 }
1472
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001473 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001474 EXPECT_TRUE(Wait())
pbosda903ea2015-10-02 02:36:56 -07001475 << (rtcp_mode_ == RtcpMode::kCompound
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001476 ? "Timed out before observing enough compound packets."
1477 : "Timed out before receiving a non-compound RTCP packet.");
1478 }
1479
pbosda903ea2015-10-02 02:36:56 -07001480 RtcpMode rtcp_mode_;
stefanb77c7162017-02-06 06:29:38 -08001481 rtc::CriticalSection crit_;
1482 // Must be protected since RTCP can be sent by both the process thread
1483 // and the pacer thread.
1484 int sent_rtp_ GUARDED_BY(&crit_);
1485 int sent_rtcp_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001486 } test(rtcp_mode);
1487
stefane74eef12016-01-08 06:47:13 -08001488 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001489}
1490
philipel277a8b52017-03-16 05:19:49 -07001491TEST_F(EndToEndTest, UsesRtcpCompoundMode) {
pbosda903ea2015-10-02 02:36:56 -07001492 RespectsRtcpMode(RtcpMode::kCompound);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001493}
1494
philipel277a8b52017-03-16 05:19:49 -07001495TEST_F(EndToEndTest, UsesRtcpReducedSizeMode) {
pbosda903ea2015-10-02 02:36:56 -07001496 RespectsRtcpMode(RtcpMode::kReducedSize);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001497}
1498
1499// Test sets up a Call multiple senders with different resolutions and SSRCs.
1500// Another is set up to receive all three of these with different renderers.
sprang867fb522015-08-03 04:38:41 -07001501class MultiStreamTest {
1502 public:
minyue20c84cc2017-04-10 16:57:57 -07001503 static constexpr size_t kNumStreams = 3;
1504 const uint8_t kVideoPayloadType = 124;
1505 const std::map<uint8_t, MediaType> payload_type_map_ = {
1506 {kVideoPayloadType, MediaType::VIDEO}};
1507
sprang867fb522015-08-03 04:38:41 -07001508 struct CodecSettings {
1509 uint32_t ssrc;
1510 int width;
1511 int height;
1512 } codec_settings[kNumStreams];
1513
eladalon413ee9a2017-08-22 04:02:52 -07001514 explicit MultiStreamTest(test::SingleThreadedTaskQueueForTesting* task_queue)
1515 : task_queue_(task_queue) {
sprang867fb522015-08-03 04:38:41 -07001516 // TODO(sprang): Cleanup when msvc supports explicit initializers for array.
1517 codec_settings[0] = {1, 640, 480};
1518 codec_settings[1] = {2, 320, 240};
1519 codec_settings[2] = {3, 240, 160};
1520 }
1521
1522 virtual ~MultiStreamTest() {}
1523
1524 void RunTest() {
skvlad11a9cbf2016-10-07 11:53:05 -07001525 webrtc::RtcEventLogNullImpl event_log;
1526 Call::Config config(&event_log);
eladalon413ee9a2017-08-22 04:02:52 -07001527 std::unique_ptr<Call> sender_call;
1528 std::unique_ptr<Call> receiver_call;
1529 std::unique_ptr<test::DirectTransport> sender_transport;
1530 std::unique_ptr<test::DirectTransport> receiver_transport;
sprang867fb522015-08-03 04:38:41 -07001531
1532 VideoSendStream* send_streams[kNumStreams];
1533 VideoReceiveStream* receive_streams[kNumStreams];
sprang867fb522015-08-03 04:38:41 -07001534 test::FrameGeneratorCapturer* frame_generators[kNumStreams];
kwiberg4a206a92016-03-31 10:24:26 -07001535 std::vector<std::unique_ptr<VideoDecoder>> allocated_decoders;
eladalon413ee9a2017-08-22 04:02:52 -07001536 std::unique_ptr<VideoEncoder> encoders[kNumStreams];
sprang867fb522015-08-03 04:38:41 -07001537
eladalon413ee9a2017-08-22 04:02:52 -07001538 task_queue_->SendTask([&]() {
1539 sender_call = rtc::WrapUnique(Call::Create(config));
1540 receiver_call = rtc::WrapUnique(Call::Create(config));
1541 sender_transport =
1542 rtc::WrapUnique(CreateSendTransport(task_queue_, sender_call.get()));
1543 receiver_transport = rtc::WrapUnique(
1544 CreateReceiveTransport(task_queue_, receiver_call.get()));
sprang867fb522015-08-03 04:38:41 -07001545
eladalon413ee9a2017-08-22 04:02:52 -07001546 sender_transport->SetReceiver(receiver_call->Receiver());
1547 receiver_transport->SetReceiver(sender_call->Receiver());
sprang867fb522015-08-03 04:38:41 -07001548
eladalon413ee9a2017-08-22 04:02:52 -07001549 for (size_t i = 0; i < kNumStreams; ++i)
1550 encoders[i].reset(VP8Encoder::Create());
sprang867fb522015-08-03 04:38:41 -07001551
eladalon413ee9a2017-08-22 04:02:52 -07001552 for (size_t i = 0; i < kNumStreams; ++i) {
1553 uint32_t ssrc = codec_settings[i].ssrc;
1554 int width = codec_settings[i].width;
1555 int height = codec_settings[i].height;
sprang867fb522015-08-03 04:38:41 -07001556
eladalon413ee9a2017-08-22 04:02:52 -07001557 VideoSendStream::Config send_config(sender_transport.get());
1558 send_config.rtp.ssrcs.push_back(ssrc);
1559 send_config.encoder_settings.encoder = encoders[i].get();
1560 send_config.encoder_settings.payload_name = "VP8";
1561 send_config.encoder_settings.payload_type = kVideoPayloadType;
1562 VideoEncoderConfig encoder_config;
1563 test::FillEncoderConfiguration(1, &encoder_config);
1564 encoder_config.max_bitrate_bps = 100000;
sprang867fb522015-08-03 04:38:41 -07001565
eladalon413ee9a2017-08-22 04:02:52 -07001566 UpdateSendConfig(i, &send_config, &encoder_config,
1567 &frame_generators[i]);
sprang867fb522015-08-03 04:38:41 -07001568
eladalon413ee9a2017-08-22 04:02:52 -07001569 send_streams[i] = sender_call->CreateVideoSendStream(
1570 send_config.Copy(), encoder_config.Copy());
1571 send_streams[i]->Start();
1572
1573 VideoReceiveStream::Config receive_config(receiver_transport.get());
1574 receive_config.rtp.remote_ssrc = ssrc;
1575 receive_config.rtp.local_ssrc = test::CallTest::kReceiverLocalVideoSsrc;
1576 VideoReceiveStream::Decoder decoder =
1577 test::CreateMatchingDecoder(send_config.encoder_settings);
1578 allocated_decoders.push_back(
1579 std::unique_ptr<VideoDecoder>(decoder.decoder));
1580 receive_config.decoders.push_back(decoder);
1581
1582 UpdateReceiveConfig(i, &receive_config);
1583
1584 receive_streams[i] =
1585 receiver_call->CreateVideoReceiveStream(std::move(receive_config));
1586 receive_streams[i]->Start();
1587
1588 frame_generators[i] = test::FrameGeneratorCapturer::Create(
1589 width, height, 30, Clock::GetRealTimeClock());
1590 send_streams[i]->SetSource(
1591 frame_generators[i],
1592 VideoSendStream::DegradationPreference::kMaintainFramerate);
1593 frame_generators[i]->Start();
1594 }
1595 });
sprang867fb522015-08-03 04:38:41 -07001596
1597 Wait();
1598
eladalon413ee9a2017-08-22 04:02:52 -07001599 task_queue_->SendTask([&]() {
1600 for (size_t i = 0; i < kNumStreams; ++i) {
1601 frame_generators[i]->Stop();
1602 sender_call->DestroyVideoSendStream(send_streams[i]);
1603 receiver_call->DestroyVideoReceiveStream(receive_streams[i]);
1604 delete frame_generators[i];
1605 }
sprang867fb522015-08-03 04:38:41 -07001606
eladalon413ee9a2017-08-22 04:02:52 -07001607 sender_transport.reset();
1608 receiver_transport.reset();
1609
1610 sender_call.reset();
1611 receiver_call.reset();
1612 });
sprang867fb522015-08-03 04:38:41 -07001613 }
1614
1615 protected:
1616 virtual void Wait() = 0;
1617 // Note: frame_generator is a point-to-pointer, since the actual instance
1618 // hasn't been created at the time of this call. Only when packets/frames
1619 // start flowing should this be dereferenced.
1620 virtual void UpdateSendConfig(
1621 size_t stream_index,
1622 VideoSendStream::Config* send_config,
1623 VideoEncoderConfig* encoder_config,
1624 test::FrameGeneratorCapturer** frame_generator) {}
1625 virtual void UpdateReceiveConfig(size_t stream_index,
1626 VideoReceiveStream::Config* receive_config) {
1627 }
eladalon413ee9a2017-08-22 04:02:52 -07001628 virtual test::DirectTransport* CreateSendTransport(
1629 test::SingleThreadedTaskQueueForTesting* task_queue,
1630 Call* sender_call) {
1631 return new test::DirectTransport(task_queue, sender_call,
1632 payload_type_map_);
sprang867fb522015-08-03 04:38:41 -07001633 }
eladalon413ee9a2017-08-22 04:02:52 -07001634 virtual test::DirectTransport* CreateReceiveTransport(
1635 test::SingleThreadedTaskQueueForTesting* task_queue,
1636 Call* receiver_call) {
1637 return new test::DirectTransport(task_queue, receiver_call,
1638 payload_type_map_);
sprang867fb522015-08-03 04:38:41 -07001639 }
eladalon413ee9a2017-08-22 04:02:52 -07001640
1641 test::SingleThreadedTaskQueueForTesting* const task_queue_;
sprang867fb522015-08-03 04:38:41 -07001642};
1643
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001644// Each renderer verifies that it receives the expected resolution, and as soon
1645// as every renderer has received a frame, the test finishes.
philipel277a8b52017-03-16 05:19:49 -07001646TEST_F(EndToEndTest, SendsAndReceivesMultipleStreams) {
nisse7ade7b32016-03-23 04:48:10 -07001647 class VideoOutputObserver : public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001648 public:
sprang867fb522015-08-03 04:38:41 -07001649 VideoOutputObserver(const MultiStreamTest::CodecSettings& settings,
1650 uint32_t ssrc,
1651 test::FrameGeneratorCapturer** frame_generator)
1652 : settings_(settings),
1653 ssrc_(ssrc),
1654 frame_generator_(frame_generator),
Peter Boström5811a392015-12-10 13:02:50 +01001655 done_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001656
nisseeb83a1a2016-03-21 01:27:56 -07001657 void OnFrame(const VideoFrame& video_frame) override {
sprang867fb522015-08-03 04:38:41 -07001658 EXPECT_EQ(settings_.width, video_frame.width());
1659 EXPECT_EQ(settings_.height, video_frame.height());
1660 (*frame_generator_)->Stop();
Peter Boström5811a392015-12-10 13:02:50 +01001661 done_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001662 }
1663
sprang867fb522015-08-03 04:38:41 -07001664 uint32_t Ssrc() { return ssrc_; }
1665
Peter Boström5811a392015-12-10 13:02:50 +01001666 bool Wait() { return done_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001667
1668 private:
sprang867fb522015-08-03 04:38:41 -07001669 const MultiStreamTest::CodecSettings& settings_;
1670 const uint32_t ssrc_;
1671 test::FrameGeneratorCapturer** const frame_generator_;
Peter Boström5811a392015-12-10 13:02:50 +01001672 rtc::Event done_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001673 };
1674
sprang867fb522015-08-03 04:38:41 -07001675 class Tester : public MultiStreamTest {
1676 public:
eladalon413ee9a2017-08-22 04:02:52 -07001677 explicit Tester(test::SingleThreadedTaskQueueForTesting* task_queue)
1678 : MultiStreamTest(task_queue) {}
sprang867fb522015-08-03 04:38:41 -07001679 virtual ~Tester() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001680
sprang867fb522015-08-03 04:38:41 -07001681 protected:
1682 void Wait() override {
1683 for (const auto& observer : observers_) {
Peter Boström5811a392015-12-10 13:02:50 +01001684 EXPECT_TRUE(observer->Wait()) << "Time out waiting for from on ssrc "
1685 << observer->Ssrc();
sprang867fb522015-08-03 04:38:41 -07001686 }
1687 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001688
sprang867fb522015-08-03 04:38:41 -07001689 void UpdateSendConfig(
1690 size_t stream_index,
1691 VideoSendStream::Config* send_config,
1692 VideoEncoderConfig* encoder_config,
1693 test::FrameGeneratorCapturer** frame_generator) override {
1694 observers_[stream_index].reset(new VideoOutputObserver(
1695 codec_settings[stream_index], send_config->rtp.ssrcs.front(),
1696 frame_generator));
1697 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001698
sprang867fb522015-08-03 04:38:41 -07001699 void UpdateReceiveConfig(
1700 size_t stream_index,
1701 VideoReceiveStream::Config* receive_config) override {
1702 receive_config->renderer = observers_[stream_index].get();
1703 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001704
sprang867fb522015-08-03 04:38:41 -07001705 private:
kwiberg27f982b2016-03-01 11:52:33 -08001706 std::unique_ptr<VideoOutputObserver> observers_[kNumStreams];
eladalon413ee9a2017-08-22 04:02:52 -07001707 } tester(&task_queue_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001708
sprang867fb522015-08-03 04:38:41 -07001709 tester.RunTest();
1710}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001711
philipel277a8b52017-03-16 05:19:49 -07001712TEST_F(EndToEndTest, AssignsTransportSequenceNumbers) {
sprang867fb522015-08-03 04:38:41 -07001713 static const int kExtensionId = 5;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001714
sprang867fb522015-08-03 04:38:41 -07001715 class RtpExtensionHeaderObserver : public test::DirectTransport {
1716 public:
minyue20c84cc2017-04-10 16:57:57 -07001717 RtpExtensionHeaderObserver(
eladalon413ee9a2017-08-22 04:02:52 -07001718 test::SingleThreadedTaskQueueForTesting* task_queue,
minyue20c84cc2017-04-10 16:57:57 -07001719 Call* sender_call,
1720 const uint32_t& first_media_ssrc,
1721 const std::map<uint32_t, uint32_t>& ssrc_map,
1722 const std::map<uint8_t, MediaType>& payload_type_map)
eladalon413ee9a2017-08-22 04:02:52 -07001723 : DirectTransport(task_queue, sender_call, payload_type_map),
Peter Boström5811a392015-12-10 13:02:50 +01001724 done_(false, false),
sprang867fb522015-08-03 04:38:41 -07001725 parser_(RtpHeaderParser::Create()),
sprang861c55e2015-10-16 10:01:21 -07001726 first_media_ssrc_(first_media_ssrc),
1727 rtx_to_media_ssrcs_(ssrc_map),
sprang867fb522015-08-03 04:38:41 -07001728 padding_observed_(false),
sprang861c55e2015-10-16 10:01:21 -07001729 rtx_padding_observed_(false),
1730 retransmit_observed_(false),
1731 started_(false) {
sprang867fb522015-08-03 04:38:41 -07001732 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
1733 kExtensionId);
1734 }
1735 virtual ~RtpExtensionHeaderObserver() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001736
stefan1d8a5062015-10-02 03:39:33 -07001737 bool SendRtp(const uint8_t* data,
1738 size_t length,
1739 const PacketOptions& options) override {
sprang861c55e2015-10-16 10:01:21 -07001740 {
1741 rtc::CritScope cs(&lock_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001742
Erik Språng8d629712015-08-04 16:24:03 +02001743 if (IsDone())
sprang861c55e2015-10-16 10:01:21 -07001744 return false;
1745
1746 if (started_) {
1747 RTPHeader header;
1748 EXPECT_TRUE(parser_->Parse(data, length, &header));
1749 bool drop_packet = false;
1750
1751 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
1752 EXPECT_EQ(options.packet_id,
1753 header.extension.transportSequenceNumber);
1754 if (!streams_observed_.empty()) {
1755 // Unwrap packet id and verify uniqueness.
1756 int64_t packet_id = unwrapper_.Unwrap(options.packet_id);
1757 EXPECT_TRUE(received_packed_ids_.insert(packet_id).second);
1758 }
1759
1760 // Drop (up to) every 17th packet, so we get retransmits.
1761 // Only drop media, and not on the first stream (otherwise it will be
1762 // hard to distinguish from padding, which is always sent on the first
1763 // stream).
1764 if (header.payloadType != kSendRtxPayloadType &&
1765 header.ssrc != first_media_ssrc_ &&
1766 header.extension.transportSequenceNumber % 17 == 0) {
1767 dropped_seq_[header.ssrc].insert(header.sequenceNumber);
1768 drop_packet = true;
1769 }
1770
perkja8ba1952017-02-27 06:52:10 -08001771 if (header.payloadType == kSendRtxPayloadType) {
sprang861c55e2015-10-16 10:01:21 -07001772 uint16_t original_sequence_number =
1773 ByteReader<uint16_t>::ReadBigEndian(&data[header.headerLength]);
1774 uint32_t original_ssrc =
1775 rtx_to_media_ssrcs_.find(header.ssrc)->second;
1776 std::set<uint16_t>* seq_no_map = &dropped_seq_[original_ssrc];
1777 auto it = seq_no_map->find(original_sequence_number);
1778 if (it != seq_no_map->end()) {
1779 retransmit_observed_ = true;
1780 seq_no_map->erase(it);
1781 } else {
1782 rtx_padding_observed_ = true;
1783 }
1784 } else {
1785 streams_observed_.insert(header.ssrc);
1786 }
1787
1788 if (IsDone())
Peter Boström5811a392015-12-10 13:02:50 +01001789 done_.Set();
sprang861c55e2015-10-16 10:01:21 -07001790
1791 if (drop_packet)
1792 return true;
1793 }
sprang867fb522015-08-03 04:38:41 -07001794 }
sprang861c55e2015-10-16 10:01:21 -07001795
stefan1d8a5062015-10-02 03:39:33 -07001796 return test::DirectTransport::SendRtp(data, length, options);
sprang867fb522015-08-03 04:38:41 -07001797 }
1798
Erik Språng8d629712015-08-04 16:24:03 +02001799 bool IsDone() {
sprang861c55e2015-10-16 10:01:21 -07001800 bool observed_types_ok =
1801 streams_observed_.size() == MultiStreamTest::kNumStreams &&
perkja8ba1952017-02-27 06:52:10 -08001802 retransmit_observed_ && rtx_padding_observed_;
sprang861c55e2015-10-16 10:01:21 -07001803 if (!observed_types_ok)
1804 return false;
1805 // We should not have any gaps in the sequence number range.
1806 size_t seqno_range =
1807 *received_packed_ids_.rbegin() - *received_packed_ids_.begin() + 1;
1808 return seqno_range == received_packed_ids_.size();
Erik Språng8d629712015-08-04 16:24:03 +02001809 }
1810
Peter Boström5811a392015-12-10 13:02:50 +01001811 bool Wait() {
sprang861c55e2015-10-16 10:01:21 -07001812 {
1813 // Can't be sure until this point that rtx_to_media_ssrcs_ etc have
1814 // been initialized and are OK to read.
1815 rtc::CritScope cs(&lock_);
1816 started_ = true;
1817 }
Peter Boström5811a392015-12-10 13:02:50 +01001818 return done_.Wait(kDefaultTimeoutMs);
sprang861c55e2015-10-16 10:01:21 -07001819 }
sprang867fb522015-08-03 04:38:41 -07001820
sprang861c55e2015-10-16 10:01:21 -07001821 rtc::CriticalSection lock_;
Peter Boström5811a392015-12-10 13:02:50 +01001822 rtc::Event done_;
kwiberg27f982b2016-03-01 11:52:33 -08001823 std::unique_ptr<RtpHeaderParser> parser_;
sprang861c55e2015-10-16 10:01:21 -07001824 SequenceNumberUnwrapper unwrapper_;
1825 std::set<int64_t> received_packed_ids_;
sprang867fb522015-08-03 04:38:41 -07001826 std::set<uint32_t> streams_observed_;
sprang861c55e2015-10-16 10:01:21 -07001827 std::map<uint32_t, std::set<uint16_t>> dropped_seq_;
1828 const uint32_t& first_media_ssrc_;
1829 const std::map<uint32_t, uint32_t>& rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001830 bool padding_observed_;
1831 bool rtx_padding_observed_;
sprang861c55e2015-10-16 10:01:21 -07001832 bool retransmit_observed_;
1833 bool started_;
sprang867fb522015-08-03 04:38:41 -07001834 };
1835
1836 class TransportSequenceNumberTester : public MultiStreamTest {
1837 public:
eladalon413ee9a2017-08-22 04:02:52 -07001838 explicit TransportSequenceNumberTester(
1839 test::SingleThreadedTaskQueueForTesting* task_queue)
1840 : MultiStreamTest(task_queue),
1841 first_media_ssrc_(0),
1842 observer_(nullptr) {}
sprang867fb522015-08-03 04:38:41 -07001843 virtual ~TransportSequenceNumberTester() {}
1844
1845 protected:
1846 void Wait() override {
Peter Boström74f6e9e2016-04-04 17:56:10 +02001847 RTC_DCHECK(observer_);
Peter Boström5811a392015-12-10 13:02:50 +01001848 EXPECT_TRUE(observer_->Wait());
sprang867fb522015-08-03 04:38:41 -07001849 }
1850
1851 void UpdateSendConfig(
1852 size_t stream_index,
1853 VideoSendStream::Config* send_config,
1854 VideoEncoderConfig* encoder_config,
1855 test::FrameGeneratorCapturer** frame_generator) override {
1856 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07001857 send_config->rtp.extensions.push_back(RtpExtension(
1858 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
sprang867fb522015-08-03 04:38:41 -07001859
perkja8ba1952017-02-27 06:52:10 -08001860 // Force some padding to be sent. Note that since we do send media
1861 // packets we can not guarantee that a padding only packet is sent.
1862 // Instead, padding will most likely be send as an RTX packet.
sprang867fb522015-08-03 04:38:41 -07001863 const int kPaddingBitrateBps = 50000;
perkja8ba1952017-02-27 06:52:10 -08001864 encoder_config->max_bitrate_bps = 200000;
sprang867fb522015-08-03 04:38:41 -07001865 encoder_config->min_transmit_bitrate_bps =
perkjfa10b552016-10-02 23:45:26 -07001866 encoder_config->max_bitrate_bps + kPaddingBitrateBps;
sprang867fb522015-08-03 04:38:41 -07001867
1868 // Configure RTX for redundant payload padding.
1869 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang861c55e2015-10-16 10:01:21 -07001870 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[stream_index]);
sprang867fb522015-08-03 04:38:41 -07001871 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
sprang861c55e2015-10-16 10:01:21 -07001872 rtx_to_media_ssrcs_[kSendRtxSsrcs[stream_index]] =
1873 send_config->rtp.ssrcs[0];
1874
1875 if (stream_index == 0)
1876 first_media_ssrc_ = send_config->rtp.ssrcs[0];
sprang867fb522015-08-03 04:38:41 -07001877 }
1878
1879 void UpdateReceiveConfig(
1880 size_t stream_index,
1881 VideoReceiveStream::Config* receive_config) override {
sprang861c55e2015-10-16 10:01:21 -07001882 receive_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang867fb522015-08-03 04:38:41 -07001883 receive_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07001884 receive_config->rtp.extensions.push_back(RtpExtension(
1885 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
sakal55d932b2016-09-30 06:19:08 -07001886 receive_config->renderer = &fake_renderer_;
sprang867fb522015-08-03 04:38:41 -07001887 }
1888
eladalon413ee9a2017-08-22 04:02:52 -07001889 test::DirectTransport* CreateSendTransport(
1890 test::SingleThreadedTaskQueueForTesting* task_queue,
1891 Call* sender_call) override {
minyue20c84cc2017-04-10 16:57:57 -07001892 std::map<uint8_t, MediaType> payload_type_map =
1893 MultiStreamTest::payload_type_map_;
1894 RTC_DCHECK(payload_type_map.find(kSendRtxPayloadType) ==
1895 payload_type_map.end());
1896 payload_type_map[kSendRtxPayloadType] = MediaType::VIDEO;
eladalon413ee9a2017-08-22 04:02:52 -07001897 observer_ = new RtpExtensionHeaderObserver(
1898 task_queue, sender_call, first_media_ssrc_, rtx_to_media_ssrcs_,
1899 payload_type_map);
sprang867fb522015-08-03 04:38:41 -07001900 return observer_;
1901 }
1902
1903 private:
sakal55d932b2016-09-30 06:19:08 -07001904 test::FakeVideoRenderer fake_renderer_;
sprang861c55e2015-10-16 10:01:21 -07001905 uint32_t first_media_ssrc_;
1906 std::map<uint32_t, uint32_t> rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001907 RtpExtensionHeaderObserver* observer_;
eladalon413ee9a2017-08-22 04:02:52 -07001908 } tester(&task_queue_);
sprang867fb522015-08-03 04:38:41 -07001909
1910 tester.RunTest();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001911}
1912
Stefan Holmer04cb7632016-01-14 20:34:30 +01001913class TransportFeedbackTester : public test::EndToEndTest {
1914 public:
stefan9e117c5e12017-08-16 08:16:25 -07001915 TransportFeedbackTester(bool feedback_enabled,
1916 size_t num_video_streams,
1917 size_t num_audio_streams)
Stefan Holmer04cb7632016-01-14 20:34:30 +01001918 : EndToEndTest(::webrtc::EndToEndTest::kDefaultTimeoutMs),
1919 feedback_enabled_(feedback_enabled),
1920 num_video_streams_(num_video_streams),
sprangcd349d92016-07-13 09:11:28 -07001921 num_audio_streams_(num_audio_streams),
1922 receiver_call_(nullptr) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001923 // Only one stream of each supported for now.
1924 EXPECT_LE(num_video_streams, 1u);
1925 EXPECT_LE(num_audio_streams, 1u);
1926 }
1927
1928 protected:
1929 Action OnSendRtcp(const uint8_t* data, size_t length) override {
1930 EXPECT_FALSE(HasTransportFeedback(data, length));
1931 return SEND_PACKET;
1932 }
1933
1934 Action OnReceiveRtcp(const uint8_t* data, size_t length) override {
1935 if (HasTransportFeedback(data, length))
1936 observation_complete_.Set();
1937 return SEND_PACKET;
1938 }
1939
1940 bool HasTransportFeedback(const uint8_t* data, size_t length) const {
danilchap3dc929e2016-11-02 08:21:59 -07001941 test::RtcpPacketParser parser;
1942 EXPECT_TRUE(parser.Parse(data, length));
1943 return parser.transport_feedback()->num_packets() > 0;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001944 }
1945
1946 void PerformTest() override {
1947 const int64_t kDisabledFeedbackTimeoutMs = 5000;
1948 EXPECT_EQ(feedback_enabled_,
1949 observation_complete_.Wait(feedback_enabled_
1950 ? test::CallTest::kDefaultTimeoutMs
1951 : kDisabledFeedbackTimeoutMs));
1952 }
1953
1954 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
1955 receiver_call_ = receiver_call;
1956 }
1957
1958 size_t GetNumVideoStreams() const override { return num_video_streams_; }
1959 size_t GetNumAudioStreams() const override { return num_audio_streams_; }
1960
1961 void ModifyVideoConfigs(
1962 VideoSendStream::Config* send_config,
1963 std::vector<VideoReceiveStream::Config>* receive_configs,
1964 VideoEncoderConfig* encoder_config) override {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001965 (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
1966 }
1967
1968 void ModifyAudioConfigs(
1969 AudioSendStream::Config* send_config,
1970 std::vector<AudioReceiveStream::Config>* receive_configs) override {
1971 send_config->rtp.extensions.clear();
1972 send_config->rtp.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001973 RtpExtension(RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer04cb7632016-01-14 20:34:30 +01001974 (*receive_configs)[0].rtp.extensions.clear();
1975 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1976 (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001977 }
1978
1979 private:
Erik Språng6b8d3552015-09-24 15:06:57 +02001980 static const int kExtensionId = 5;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001981 const bool feedback_enabled_;
1982 const size_t num_video_streams_;
1983 const size_t num_audio_streams_;
1984 Call* receiver_call_;
1985};
Erik Språng6b8d3552015-09-24 15:06:57 +02001986
philipel277a8b52017-03-16 05:19:49 -07001987TEST_F(EndToEndTest, VideoReceivesTransportFeedback) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001988 TransportFeedbackTester test(true, 1, 0);
1989 RunBaseTest(&test);
Erik Språng6b8d3552015-09-24 15:06:57 +02001990}
stefan43edf0f2015-11-20 18:05:48 -08001991
philipel277a8b52017-03-16 05:19:49 -07001992TEST_F(EndToEndTest, VideoTransportFeedbackNotConfigured) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001993 TransportFeedbackTester test(false, 1, 0);
1994 RunBaseTest(&test);
stefan43edf0f2015-11-20 18:05:48 -08001995}
1996
philipel277a8b52017-03-16 05:19:49 -07001997TEST_F(EndToEndTest, AudioReceivesTransportFeedback) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001998 TransportFeedbackTester test(true, 0, 1);
1999 RunBaseTest(&test);
2000}
2001
philipel277a8b52017-03-16 05:19:49 -07002002TEST_F(EndToEndTest, AudioTransportFeedbackNotConfigured) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01002003 TransportFeedbackTester test(false, 0, 1);
2004 RunBaseTest(&test);
2005}
2006
philipel277a8b52017-03-16 05:19:49 -07002007TEST_F(EndToEndTest, AudioVideoReceivesTransportFeedback) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01002008 TransportFeedbackTester test(true, 1, 1);
2009 RunBaseTest(&test);
stefan43edf0f2015-11-20 18:05:48 -08002010}
2011
stefan9e117c5e12017-08-16 08:16:25 -07002012TEST_F(EndToEndTest, StopsSendingMediaWithoutFeedback) {
2013 test::ScopedFieldTrials override_field_trials(
stefan74418272017-08-17 02:13:54 -07002014 "WebRTC-CwndExperiment/Enabled-250/");
stefan9e117c5e12017-08-16 08:16:25 -07002015
2016 class TransportFeedbackTester : public test::EndToEndTest {
2017 public:
2018 TransportFeedbackTester(size_t num_video_streams, size_t num_audio_streams)
2019 : EndToEndTest(::webrtc::EndToEndTest::kDefaultTimeoutMs),
2020 num_video_streams_(num_video_streams),
2021 num_audio_streams_(num_audio_streams),
2022 media_sent_(0),
2023 padding_sent_(0) {
2024 // Only one stream of each supported for now.
2025 EXPECT_LE(num_video_streams, 1u);
2026 EXPECT_LE(num_audio_streams, 1u);
2027 }
2028
2029 protected:
2030 Action OnSendRtp(const uint8_t* packet, size_t length) override {
2031 RTPHeader header;
2032 EXPECT_TRUE(parser_->Parse(packet, length, &header));
2033 const bool only_padding =
2034 header.headerLength + header.paddingLength == length;
2035 rtc::CritScope lock(&crit_);
2036 if (only_padding) {
2037 ++padding_sent_;
2038 } else {
2039 ++media_sent_;
2040 EXPECT_LT(media_sent_, 40) << "Media sent without feedback.";
2041 }
2042
2043 return SEND_PACKET;
2044 }
2045
2046 Action OnReceiveRtcp(const uint8_t* data, size_t length) override {
2047 rtc::CritScope lock(&crit_);
2048 if (media_sent_ > 20 && HasTransportFeedback(data, length)) {
2049 return DROP_PACKET;
2050 }
2051 return SEND_PACKET;
2052 }
2053
2054 bool HasTransportFeedback(const uint8_t* data, size_t length) const {
2055 test::RtcpPacketParser parser;
2056 EXPECT_TRUE(parser.Parse(data, length));
2057 return parser.transport_feedback()->num_packets() > 0;
2058 }
2059
2060 Call::Config GetSenderCallConfig() override {
2061 Call::Config config = EndToEndTest::GetSenderCallConfig();
2062 config.bitrate_config.max_bitrate_bps = 300000;
2063 return config;
2064 }
2065
2066 void PerformTest() override {
2067 const int64_t kDisabledFeedbackTimeoutMs = 10000;
2068 observation_complete_.Wait(kDisabledFeedbackTimeoutMs);
2069 rtc::CritScope lock(&crit_);
2070 EXPECT_GT(padding_sent_, 0);
2071 }
2072
2073 size_t GetNumVideoStreams() const override { return num_video_streams_; }
2074 size_t GetNumAudioStreams() const override { return num_audio_streams_; }
2075
2076 private:
2077 const size_t num_video_streams_;
2078 const size_t num_audio_streams_;
2079 rtc::CriticalSection crit_;
2080 int media_sent_ GUARDED_BY(crit_);
2081 int padding_sent_ GUARDED_BY(crit_);
2082 } test(1, 0);
2083 RunBaseTest(&test);
2084}
2085
philipel277a8b52017-03-16 05:19:49 -07002086TEST_F(EndToEndTest, ObserversEncodedFrames) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002087 class EncodedFrameTestObserver : public EncodedFrameObserver {
2088 public:
2089 EncodedFrameTestObserver()
Peter Boström5811a392015-12-10 13:02:50 +01002090 : length_(0), frame_type_(kEmptyFrame), called_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002091 virtual ~EncodedFrameTestObserver() {}
2092
2093 virtual void EncodedFrameCallback(const EncodedFrame& encoded_frame) {
2094 frame_type_ = encoded_frame.frame_type_;
2095 length_ = encoded_frame.length_;
2096 buffer_.reset(new uint8_t[length_]);
2097 memcpy(buffer_.get(), encoded_frame.data_, length_);
Peter Boström5811a392015-12-10 13:02:50 +01002098 called_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002099 }
2100
Peter Boström5811a392015-12-10 13:02:50 +01002101 bool Wait() { return called_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002102
2103 void ExpectEqualFrames(const EncodedFrameTestObserver& observer) {
2104 ASSERT_EQ(length_, observer.length_)
2105 << "Observed frames are of different lengths.";
2106 EXPECT_EQ(frame_type_, observer.frame_type_)
2107 << "Observed frames have different frame types.";
2108 EXPECT_EQ(0, memcmp(buffer_.get(), observer.buffer_.get(), length_))
2109 << "Observed encoded frames have different content.";
2110 }
2111
2112 private:
kwiberg27f982b2016-03-01 11:52:33 -08002113 std::unique_ptr<uint8_t[]> buffer_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002114 size_t length_;
2115 FrameType frame_type_;
Peter Boström5811a392015-12-10 13:02:50 +01002116 rtc::Event called_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002117 };
2118
2119 EncodedFrameTestObserver post_encode_observer;
2120 EncodedFrameTestObserver pre_decode_observer;
perkja49cbd32016-09-16 07:53:41 -07002121 test::FrameForwarder forwarder;
eladalon413ee9a2017-08-22 04:02:52 -07002122 std::unique_ptr<test::FrameGenerator> frame_generator;
2123
2124 std::unique_ptr<test::DirectTransport> sender_transport;
2125 std::unique_ptr<test::DirectTransport> receiver_transport;
2126
2127 task_queue_.SendTask([&]() {
2128 CreateCalls(Call::Config(event_log_.get()), Call::Config(event_log_.get()));
2129
2130 sender_transport = rtc::MakeUnique<test::DirectTransport>(
2131 &task_queue_, sender_call_.get(), payload_type_map_);
2132 receiver_transport = rtc::MakeUnique<test::DirectTransport>(
2133 &task_queue_, receiver_call_.get(), payload_type_map_);
2134 sender_transport->SetReceiver(receiver_call_->Receiver());
2135 receiver_transport->SetReceiver(sender_call_->Receiver());
2136
2137 CreateSendConfig(1, 0, 0, sender_transport.get());
2138 CreateMatchingReceiveConfigs(receiver_transport.get());
2139 video_send_config_.post_encode_callback = &post_encode_observer;
2140 video_receive_configs_[0].pre_decode_callback = &pre_decode_observer;
2141
2142 CreateVideoStreams();
2143 Start();
2144
2145 frame_generator = test::FrameGenerator::CreateSquareGenerator(
2146 kDefaultWidth, kDefaultHeight);
2147 video_send_stream_->SetSource(
2148 &forwarder, VideoSendStream::DegradationPreference::kMaintainFramerate);
2149 forwarder.IncomingCapturedFrame(*frame_generator->NextFrame());
2150 });
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002151
Peter Boström5811a392015-12-10 13:02:50 +01002152 EXPECT_TRUE(post_encode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002153 << "Timed out while waiting for send-side encoded-frame callback.";
2154
Peter Boström5811a392015-12-10 13:02:50 +01002155 EXPECT_TRUE(pre_decode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002156 << "Timed out while waiting for pre-decode encoded-frame callback.";
2157
2158 post_encode_observer.ExpectEqualFrames(pre_decode_observer);
2159
eladalon413ee9a2017-08-22 04:02:52 -07002160 task_queue_.SendTask([this, &sender_transport, &receiver_transport]() {
2161 Stop();
2162 DestroyStreams();
2163 sender_transport.reset();
2164 receiver_transport.reset();
2165 DestroyCalls();
2166 });
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002167}
2168
philipel277a8b52017-03-16 05:19:49 -07002169TEST_F(EndToEndTest, ReceiveStreamSendsRemb) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002170 class RembObserver : public test::EndToEndTest {
2171 public:
2172 RembObserver() : EndToEndTest(kDefaultTimeoutMs) {}
2173
stefanb77c7162017-02-06 06:29:38 -08002174 void ModifyVideoConfigs(
2175 VideoSendStream::Config* send_config,
2176 std::vector<VideoReceiveStream::Config>* receive_configs,
2177 VideoEncoderConfig* encoder_config) override {
2178 send_config->rtp.extensions.clear();
2179 send_config->rtp.extensions.push_back(RtpExtension(
2180 RtpExtension::kAbsSendTimeUri, test::kAbsSendTimeExtensionId));
2181 (*receive_configs)[0].rtp.remb = true;
2182 (*receive_configs)[0].rtp.transport_cc = false;
2183 }
2184
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002185 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
danilchap3dc929e2016-11-02 08:21:59 -07002186 test::RtcpPacketParser parser;
2187 EXPECT_TRUE(parser.Parse(packet, length));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002188
danilchap3dc929e2016-11-02 08:21:59 -07002189 if (parser.remb()->num_packets() > 0) {
2190 EXPECT_EQ(kReceiverLocalVideoSsrc, parser.remb()->sender_ssrc());
2191 EXPECT_LT(0U, parser.remb()->bitrate_bps());
2192 EXPECT_EQ(1U, parser.remb()->ssrcs().size());
2193 EXPECT_EQ(kVideoSendSsrcs[0], parser.remb()->ssrcs()[0]);
Peter Boström5811a392015-12-10 13:02:50 +01002194 observation_complete_.Set();
danilchap3dc929e2016-11-02 08:21:59 -07002195 }
2196
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002197 return SEND_PACKET;
2198 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002199 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002200 EXPECT_TRUE(Wait()) << "Timed out while waiting for a "
2201 "receiver RTCP REMB packet to be "
2202 "sent.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002203 }
2204 } test;
2205
stefane74eef12016-01-08 06:47:13 -08002206 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002207}
2208
stefanb77c7162017-02-06 06:29:38 -08002209class BandwidthStatsTest : public test::EndToEndTest {
2210 public:
2211 explicit BandwidthStatsTest(bool send_side_bwe)
2212 : EndToEndTest(test::CallTest::kDefaultTimeoutMs),
2213 sender_call_(nullptr),
2214 receiver_call_(nullptr),
2215 has_seen_pacer_delay_(false),
2216 send_side_bwe_(send_side_bwe) {}
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002217
stefanb77c7162017-02-06 06:29:38 -08002218 void ModifyVideoConfigs(
2219 VideoSendStream::Config* send_config,
2220 std::vector<VideoReceiveStream::Config>* receive_configs,
2221 VideoEncoderConfig* encoder_config) override {
2222 if (!send_side_bwe_) {
2223 send_config->rtp.extensions.clear();
2224 send_config->rtp.extensions.push_back(RtpExtension(
2225 RtpExtension::kAbsSendTimeUri, test::kAbsSendTimeExtensionId));
2226 (*receive_configs)[0].rtp.remb = true;
2227 (*receive_configs)[0].rtp.transport_cc = false;
2228 }
2229 }
2230
2231 Action OnSendRtp(const uint8_t* packet, size_t length) override {
2232 Call::Stats sender_stats = sender_call_->GetStats();
2233 Call::Stats receiver_stats = receiver_call_->GetStats();
2234 if (!has_seen_pacer_delay_)
2235 has_seen_pacer_delay_ = sender_stats.pacer_delay_ms > 0;
2236 if (sender_stats.send_bandwidth_bps > 0 && has_seen_pacer_delay_) {
2237 if (send_side_bwe_ || receiver_stats.recv_bandwidth_bps > 0)
Peter Boström5811a392015-12-10 13:02:50 +01002238 observation_complete_.Set();
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002239 }
stefanb77c7162017-02-06 06:29:38 -08002240 return SEND_PACKET;
2241 }
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002242
stefanb77c7162017-02-06 06:29:38 -08002243 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2244 sender_call_ = sender_call;
2245 receiver_call_ = receiver_call;
2246 }
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002247
stefanb77c7162017-02-06 06:29:38 -08002248 void PerformTest() override {
2249 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
2250 "non-zero bandwidth stats.";
2251 }
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002252
stefanb77c7162017-02-06 06:29:38 -08002253 private:
2254 Call* sender_call_;
2255 Call* receiver_call_;
2256 bool has_seen_pacer_delay_;
2257 const bool send_side_bwe_;
2258};
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002259
philipel277a8b52017-03-16 05:19:49 -07002260TEST_F(EndToEndTest, VerifySendSideBweStats) {
stefanb77c7162017-02-06 06:29:38 -08002261 BandwidthStatsTest test(true);
stefane74eef12016-01-08 06:47:13 -08002262 RunBaseTest(&test);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002263}
2264
philipel277a8b52017-03-16 05:19:49 -07002265TEST_F(EndToEndTest, VerifyRecvSideBweStats) {
stefanb77c7162017-02-06 06:29:38 -08002266 BandwidthStatsTest test(false);
2267 RunBaseTest(&test);
2268}
stefan32f81542016-01-20 07:13:58 -08002269
2270// Verifies that it's possible to limit the send BWE by sending a REMB.
2271// This is verified by allowing the send BWE to ramp-up to >1000 kbps,
2272// then have the test generate a REMB of 500 kbps and verify that the send BWE
2273// is reduced to exactly 500 kbps. Then a REMB of 1000 kbps is generated and the
2274// test verifies that the send BWE ramps back up to exactly 1000 kbps.
philipel277a8b52017-03-16 05:19:49 -07002275TEST_F(EndToEndTest, RembWithSendSideBwe) {
stefan32f81542016-01-20 07:13:58 -08002276 class BweObserver : public test::EndToEndTest {
2277 public:
2278 BweObserver()
2279 : EndToEndTest(kDefaultTimeoutMs),
2280 sender_call_(nullptr),
2281 clock_(Clock::GetRealTimeClock()),
2282 sender_ssrc_(0),
2283 remb_bitrate_bps_(1000000),
2284 receive_transport_(nullptr),
Tommi5dd5f5a2017-02-21 14:22:59 +01002285 stop_event_(false, false),
stefan32f81542016-01-20 07:13:58 -08002286 poller_thread_(&BitrateStatsPollingThread,
2287 this,
2288 "BitrateStatsPollingThread"),
Erik Språng737336d2016-07-29 12:59:36 +02002289 state_(kWaitForFirstRampUp),
2290 retransmission_rate_limiter_(clock_, 1000) {}
stefan32f81542016-01-20 07:13:58 -08002291
2292 ~BweObserver() {}
2293
eladalon413ee9a2017-08-22 04:02:52 -07002294 test::PacketTransport* CreateReceiveTransport(
2295 test::SingleThreadedTaskQueueForTesting* task_queue) override {
stefan32f81542016-01-20 07:13:58 -08002296 receive_transport_ = new test::PacketTransport(
eladalon413ee9a2017-08-22 04:02:52 -07002297 task_queue, nullptr, this, test::PacketTransport::kReceiver,
2298 payload_type_map_, FakeNetworkPipe::Config());
stefan32f81542016-01-20 07:13:58 -08002299 return receive_transport_;
2300 }
2301
2302 Call::Config GetSenderCallConfig() override {
philipel4fb651d2017-04-10 03:54:05 -07002303 Call::Config config(event_log_.get());
stefan32f81542016-01-20 07:13:58 -08002304 // Set a high start bitrate to reduce the test completion time.
2305 config.bitrate_config.start_bitrate_bps = remb_bitrate_bps_;
2306 return config;
2307 }
2308
2309 void ModifyVideoConfigs(
2310 VideoSendStream::Config* send_config,
2311 std::vector<VideoReceiveStream::Config>* receive_configs,
2312 VideoEncoderConfig* encoder_config) override {
2313 ASSERT_EQ(1u, send_config->rtp.ssrcs.size());
stefan32f81542016-01-20 07:13:58 -08002314 sender_ssrc_ = send_config->rtp.ssrcs[0];
2315
perkjfa10b552016-10-02 23:45:26 -07002316 encoder_config->max_bitrate_bps = 2000000;
stefan32f81542016-01-20 07:13:58 -08002317
2318 ASSERT_EQ(1u, receive_configs->size());
stefan32f81542016-01-20 07:13:58 -08002319 RtpRtcp::Configuration config;
2320 config.receiver_only = true;
2321 config.clock = clock_;
2322 config.outgoing_transport = receive_transport_;
Erik Språng737336d2016-07-29 12:59:36 +02002323 config.retransmission_rate_limiter = &retransmission_rate_limiter_;
stefan32f81542016-01-20 07:13:58 -08002324 rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(config));
2325 rtp_rtcp_->SetRemoteSSRC((*receive_configs)[0].rtp.remote_ssrc);
2326 rtp_rtcp_->SetSSRC((*receive_configs)[0].rtp.local_ssrc);
2327 rtp_rtcp_->SetREMBStatus(true);
stefan32f81542016-01-20 07:13:58 -08002328 rtp_rtcp_->SetRTCPStatus(RtcpMode::kReducedSize);
2329 }
2330
2331 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2332 sender_call_ = sender_call;
2333 }
2334
tommi0f8b4032017-02-22 11:22:05 -08002335 static void BitrateStatsPollingThread(void* obj) {
2336 static_cast<BweObserver*>(obj)->PollStats();
stefan32f81542016-01-20 07:13:58 -08002337 }
2338
tommi0f8b4032017-02-22 11:22:05 -08002339 void PollStats() {
2340 do {
2341 if (sender_call_) {
2342 Call::Stats stats = sender_call_->GetStats();
2343 switch (state_) {
2344 case kWaitForFirstRampUp:
2345 if (stats.send_bandwidth_bps >= remb_bitrate_bps_) {
2346 state_ = kWaitForRemb;
2347 remb_bitrate_bps_ /= 2;
2348 rtp_rtcp_->SetREMBData(
2349 remb_bitrate_bps_,
2350 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
2351 rtp_rtcp_->SendRTCP(kRtcpRr);
2352 }
2353 break;
stefan32f81542016-01-20 07:13:58 -08002354
tommi0f8b4032017-02-22 11:22:05 -08002355 case kWaitForRemb:
2356 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
2357 state_ = kWaitForSecondRampUp;
2358 remb_bitrate_bps_ *= 2;
2359 rtp_rtcp_->SetREMBData(
2360 remb_bitrate_bps_,
2361 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
2362 rtp_rtcp_->SendRTCP(kRtcpRr);
2363 }
2364 break;
stefan32f81542016-01-20 07:13:58 -08002365
tommi0f8b4032017-02-22 11:22:05 -08002366 case kWaitForSecondRampUp:
2367 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
2368 observation_complete_.Set();
2369 }
2370 break;
2371 }
stefan32f81542016-01-20 07:13:58 -08002372 }
tommi0f8b4032017-02-22 11:22:05 -08002373 } while (!stop_event_.Wait(1000));
stefan32f81542016-01-20 07:13:58 -08002374 }
2375
2376 void PerformTest() override {
2377 poller_thread_.Start();
2378 EXPECT_TRUE(Wait())
2379 << "Timed out while waiting for bitrate to change according to REMB.";
Tommi5dd5f5a2017-02-21 14:22:59 +01002380 stop_event_.Set();
stefan32f81542016-01-20 07:13:58 -08002381 poller_thread_.Stop();
2382 }
2383
2384 private:
2385 enum TestState { kWaitForFirstRampUp, kWaitForRemb, kWaitForSecondRampUp };
2386
2387 Call* sender_call_;
2388 Clock* const clock_;
2389 uint32_t sender_ssrc_;
2390 int remb_bitrate_bps_;
kwiberg27f982b2016-03-01 11:52:33 -08002391 std::unique_ptr<RtpRtcp> rtp_rtcp_;
stefan32f81542016-01-20 07:13:58 -08002392 test::PacketTransport* receive_transport_;
Tommi5dd5f5a2017-02-21 14:22:59 +01002393 rtc::Event stop_event_;
stefan32f81542016-01-20 07:13:58 -08002394 rtc::PlatformThread poller_thread_;
2395 TestState state_;
Erik Språng737336d2016-07-29 12:59:36 +02002396 RateLimiter retransmission_rate_limiter_;
stefan32f81542016-01-20 07:13:58 -08002397 } test;
2398
2399 RunBaseTest(&test);
2400}
2401
philipel3184f8e2017-05-18 08:08:53 -07002402TEST_F(EndToEndTest, StopSendingKeyframeRequestsForInactiveStream) {
2403 class KeyframeRequestObserver : public test::EndToEndTest {
2404 public:
eladalon413ee9a2017-08-22 04:02:52 -07002405 explicit KeyframeRequestObserver(
2406 test::SingleThreadedTaskQueueForTesting* task_queue)
2407 : clock_(Clock::GetRealTimeClock()), task_queue_(task_queue) {}
philipel3184f8e2017-05-18 08:08:53 -07002408
2409 void OnVideoStreamsCreated(
2410 VideoSendStream* send_stream,
2411 const std::vector<VideoReceiveStream*>& receive_streams) override {
2412 RTC_DCHECK_EQ(1, receive_streams.size());
2413 send_stream_ = send_stream;
2414 receive_stream_ = receive_streams[0];
2415 }
2416
2417 void PerformTest() override {
2418 bool frame_decoded = false;
2419 int64_t start_time = clock_->TimeInMilliseconds();
2420 while (clock_->TimeInMilliseconds() - start_time <= 5000) {
2421 if (receive_stream_->GetStats().frames_decoded > 0) {
2422 frame_decoded = true;
2423 break;
2424 }
2425 SleepMs(100);
2426 }
2427 ASSERT_TRUE(frame_decoded);
eladalon413ee9a2017-08-22 04:02:52 -07002428 task_queue_->SendTask([this]() { send_stream_->Stop(); });
philipel3184f8e2017-05-18 08:08:53 -07002429 SleepMs(10000);
2430 ASSERT_EQ(
2431 1U, receive_stream_->GetStats().rtcp_packet_type_counts.pli_packets);
2432 }
2433
2434 private:
2435 Clock* clock_;
2436 VideoSendStream* send_stream_;
2437 VideoReceiveStream* receive_stream_;
eladalon413ee9a2017-08-22 04:02:52 -07002438 test::SingleThreadedTaskQueueForTesting* const task_queue_;
2439 } test(&task_queue_);
philipel3184f8e2017-05-18 08:08:53 -07002440
2441 RunBaseTest(&test);
2442}
2443
philipele828c962017-03-21 03:24:27 -07002444class ProbingTest : public test::EndToEndTest {
2445 public:
2446 explicit ProbingTest(int start_bitrate_bps)
2447 : clock_(Clock::GetRealTimeClock()),
2448 start_bitrate_bps_(start_bitrate_bps),
2449 state_(0),
2450 sender_call_(nullptr) {}
2451
2452 ~ProbingTest() {}
2453
2454 Call::Config GetSenderCallConfig() override {
philipel4fb651d2017-04-10 03:54:05 -07002455 Call::Config config(event_log_.get());
philipele828c962017-03-21 03:24:27 -07002456 config.bitrate_config.start_bitrate_bps = start_bitrate_bps_;
2457 return config;
2458 }
2459
2460 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2461 sender_call_ = sender_call;
2462 }
2463
2464 protected:
2465 Clock* const clock_;
2466 const int start_bitrate_bps_;
2467 int state_;
2468 Call* sender_call_;
2469};
2470
aleloi7057b6b2017-03-29 02:07:33 -07002471TEST_F(EndToEndTest, MAYBE_InitialProbing) {
philipele828c962017-03-21 03:24:27 -07002472 class InitialProbingTest : public ProbingTest {
2473 public:
philipel8a256522017-03-30 05:06:22 -07002474 explicit InitialProbingTest(bool* success)
eladaloncf038f72017-08-10 10:42:53 -07002475 : ProbingTest(300000), success_(success) {
2476 *success_ = false;
2477 }
philipele828c962017-03-21 03:24:27 -07002478
2479 void PerformTest() override {
2480 int64_t start_time_ms = clock_->TimeInMilliseconds();
2481 do {
philipel8a256522017-03-30 05:06:22 -07002482 if (clock_->TimeInMilliseconds() - start_time_ms > kTimeoutMs)
philipele828c962017-03-21 03:24:27 -07002483 break;
philipele828c962017-03-21 03:24:27 -07002484
2485 Call::Stats stats = sender_call_->GetStats();
2486 // Initial probing is done with a x3 and x6 multiplier of the start
2487 // bitrate, so a x4 multiplier is a high enough threshold.
philipel8a256522017-03-30 05:06:22 -07002488 if (stats.send_bandwidth_bps > 4 * 300000) {
2489 *success_ = true;
philipele828c962017-03-21 03:24:27 -07002490 break;
philipel8a256522017-03-30 05:06:22 -07002491 }
philipele828c962017-03-21 03:24:27 -07002492 } while (!observation_complete_.Wait(20));
2493 }
2494
2495 private:
2496 const int kTimeoutMs = 1000;
philipel8a256522017-03-30 05:06:22 -07002497 bool* const success_;
2498 };
philipele828c962017-03-21 03:24:27 -07002499
eladaloncf038f72017-08-10 10:42:53 -07002500 bool success = false;
philipel8a256522017-03-30 05:06:22 -07002501 const int kMaxAttempts = 3;
2502 for (int i = 0; i < kMaxAttempts; ++i) {
2503 InitialProbingTest test(&success);
2504 RunBaseTest(&test);
2505 if (success)
2506 return;
2507 }
eladaloncf038f72017-08-10 10:42:53 -07002508 EXPECT_TRUE(success) << "Failed to perform mid initial probing ("
2509 << kMaxAttempts << " attempts).";
philipele828c962017-03-21 03:24:27 -07002510}
2511
aleloi18703f92017-03-30 04:24:08 -07002512// Fails on Linux MSan: bugs.webrtc.org/7428
2513#if defined(MEMORY_SANITIZER)
2514TEST_F(EndToEndTest, DISABLED_TriggerMidCallProbing) {
oprypin45197522017-06-22 01:47:20 -07002515// Fails on iOS bots: bugs.webrtc.org/7851
2516#elif defined(TARGET_IPHONE_SIMULATOR) && TARGET_IPHONE_SIMULATOR
2517TEST_F(EndToEndTest, DISABLED_TriggerMidCallProbing) {
aleloi18703f92017-03-30 04:24:08 -07002518#else
philipele828c962017-03-21 03:24:27 -07002519TEST_F(EndToEndTest, TriggerMidCallProbing) {
aleloi18703f92017-03-30 04:24:08 -07002520#endif
2521
philipele828c962017-03-21 03:24:27 -07002522 class TriggerMidCallProbingTest : public ProbingTest {
2523 public:
eladalon413ee9a2017-08-22 04:02:52 -07002524 TriggerMidCallProbingTest(
2525 test::SingleThreadedTaskQueueForTesting* task_queue,
2526 bool* success)
2527 : ProbingTest(300000), success_(success), task_queue_(task_queue) {}
philipele828c962017-03-21 03:24:27 -07002528
2529 void PerformTest() override {
philipel8a256522017-03-30 05:06:22 -07002530 *success_ = false;
philipele828c962017-03-21 03:24:27 -07002531 int64_t start_time_ms = clock_->TimeInMilliseconds();
2532 do {
philipel8a256522017-03-30 05:06:22 -07002533 if (clock_->TimeInMilliseconds() - start_time_ms > kTimeoutMs)
philipele828c962017-03-21 03:24:27 -07002534 break;
philipele828c962017-03-21 03:24:27 -07002535
2536 Call::Stats stats = sender_call_->GetStats();
2537
2538 switch (state_) {
2539 case 0:
2540 if (stats.send_bandwidth_bps > 5 * 300000) {
2541 Call::Config::BitrateConfig bitrate_config;
2542 bitrate_config.max_bitrate_bps = 100000;
eladalon413ee9a2017-08-22 04:02:52 -07002543 task_queue_->SendTask([this, &bitrate_config]() {
2544 sender_call_->SetBitrateConfig(bitrate_config);
2545 });
philipele828c962017-03-21 03:24:27 -07002546 ++state_;
2547 }
2548 break;
2549 case 1:
2550 if (stats.send_bandwidth_bps < 110000) {
2551 Call::Config::BitrateConfig bitrate_config;
2552 bitrate_config.max_bitrate_bps = 2500000;
eladalon413ee9a2017-08-22 04:02:52 -07002553 task_queue_->SendTask([this, &bitrate_config]() {
2554 sender_call_->SetBitrateConfig(bitrate_config);
2555 });
philipele828c962017-03-21 03:24:27 -07002556 ++state_;
2557 }
2558 break;
2559 case 2:
2560 // During high cpu load the pacer will not be able to pace packets
2561 // at the correct speed, but if we go from 110 to 1250 kbps
2562 // in 5 seconds then it is due to probing.
philipel8a256522017-03-30 05:06:22 -07002563 if (stats.send_bandwidth_bps > 1250000) {
2564 *success_ = true;
philipele828c962017-03-21 03:24:27 -07002565 observation_complete_.Set();
philipel8a256522017-03-30 05:06:22 -07002566 }
philipele828c962017-03-21 03:24:27 -07002567 break;
2568 }
2569 } while (!observation_complete_.Wait(20));
2570 }
2571
2572 private:
2573 const int kTimeoutMs = 5000;
philipel8a256522017-03-30 05:06:22 -07002574 bool* const success_;
eladalon413ee9a2017-08-22 04:02:52 -07002575 test::SingleThreadedTaskQueueForTesting* const task_queue_;
philipel8a256522017-03-30 05:06:22 -07002576 };
philipele828c962017-03-21 03:24:27 -07002577
eladaloncf038f72017-08-10 10:42:53 -07002578 bool success = false;
philipel8a256522017-03-30 05:06:22 -07002579 const int kMaxAttempts = 3;
2580 for (int i = 0; i < kMaxAttempts; ++i) {
eladalon413ee9a2017-08-22 04:02:52 -07002581 TriggerMidCallProbingTest test(&task_queue_, &success);
philipel8a256522017-03-30 05:06:22 -07002582 RunBaseTest(&test);
2583 if (success)
2584 return;
2585 }
stefan9e117c5e12017-08-16 08:16:25 -07002586 EXPECT_TRUE(success) << "Failed to perform mid call probing (" << kMaxAttempts
2587 << " attempts).";
philipele828c962017-03-21 03:24:27 -07002588}
2589
philipel277a8b52017-03-16 05:19:49 -07002590TEST_F(EndToEndTest, VerifyNackStats) {
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002591 static const int kPacketNumberToDrop = 200;
2592 class NackObserver : public test::EndToEndTest {
2593 public:
2594 NackObserver()
2595 : EndToEndTest(kLongTimeoutMs),
2596 sent_rtp_packets_(0),
2597 dropped_rtp_packet_(0),
2598 dropped_rtp_packet_requested_(false),
2599 send_stream_(nullptr),
2600 start_runtime_ms_(-1) {}
2601
2602 private:
2603 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002604 rtc::CritScope lock(&crit_);
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002605 if (++sent_rtp_packets_ == kPacketNumberToDrop) {
kwiberg27f982b2016-03-01 11:52:33 -08002606 std::unique_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002607 RTPHeader header;
2608 EXPECT_TRUE(parser->Parse(packet, length, &header));
2609 dropped_rtp_packet_ = header.sequenceNumber;
2610 return DROP_PACKET;
2611 }
2612 VerifyStats();
2613 return SEND_PACKET;
2614 }
2615
2616 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002617 rtc::CritScope lock(&crit_);
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002618 test::RtcpPacketParser rtcp_parser;
2619 rtcp_parser.Parse(packet, length);
Danil Chapovalovba6f7be2016-09-02 18:29:10 +02002620 const std::vector<uint16_t>& nacks = rtcp_parser.nack()->packet_ids();
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002621 if (!nacks.empty() && std::find(
2622 nacks.begin(), nacks.end(), dropped_rtp_packet_) != nacks.end()) {
2623 dropped_rtp_packet_requested_ = true;
2624 }
2625 return SEND_PACKET;
2626 }
2627
stefan608213e2015-11-01 14:56:10 -08002628 void VerifyStats() EXCLUSIVE_LOCKS_REQUIRED(&crit_) {
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002629 if (!dropped_rtp_packet_requested_)
2630 return;
2631 int send_stream_nack_packets = 0;
2632 int receive_stream_nack_packets = 0;
2633 VideoSendStream::Stats stats = send_stream_->GetStats();
2634 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
2635 stats.substreams.begin(); it != stats.substreams.end(); ++it) {
2636 const VideoSendStream::StreamStats& stream_stats = it->second;
2637 send_stream_nack_packets +=
2638 stream_stats.rtcp_packet_type_counts.nack_packets;
2639 }
2640 for (size_t i = 0; i < receive_streams_.size(); ++i) {
2641 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
2642 receive_stream_nack_packets +=
2643 stats.rtcp_packet_type_counts.nack_packets;
2644 }
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002645 if (send_stream_nack_packets >= 1 && receive_stream_nack_packets >= 1) {
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002646 // NACK packet sent on receive stream and received on sent stream.
2647 if (MinMetricRunTimePassed())
Peter Boström5811a392015-12-10 13:02:50 +01002648 observation_complete_.Set();
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002649 }
2650 }
2651
2652 bool MinMetricRunTimePassed() {
2653 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
2654 if (start_runtime_ms_ == -1) {
2655 start_runtime_ms_ = now;
2656 return false;
2657 }
2658 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
2659 return elapsed_sec > metrics::kMinRunTimeInSeconds;
2660 }
2661
stefanff483612015-12-21 03:14:00 -08002662 void ModifyVideoConfigs(
2663 VideoSendStream::Config* send_config,
2664 std::vector<VideoReceiveStream::Config>* receive_configs,
2665 VideoEncoderConfig* encoder_config) override {
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002666 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2667 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sakal55d932b2016-09-30 06:19:08 -07002668 (*receive_configs)[0].renderer = &fake_renderer_;
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002669 }
2670
stefanff483612015-12-21 03:14:00 -08002671 void OnVideoStreamsCreated(
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002672 VideoSendStream* send_stream,
2673 const std::vector<VideoReceiveStream*>& receive_streams) override {
2674 send_stream_ = send_stream;
2675 receive_streams_ = receive_streams;
2676 }
2677
2678 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002679 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002680 }
2681
sakal55d932b2016-09-30 06:19:08 -07002682 test::FakeVideoRenderer fake_renderer_;
stefan608213e2015-11-01 14:56:10 -08002683 rtc::CriticalSection crit_;
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002684 uint64_t sent_rtp_packets_;
stefan608213e2015-11-01 14:56:10 -08002685 uint16_t dropped_rtp_packet_ GUARDED_BY(&crit_);
2686 bool dropped_rtp_packet_requested_ GUARDED_BY(&crit_);
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002687 std::vector<VideoReceiveStream*> receive_streams_;
2688 VideoSendStream* send_stream_;
2689 int64_t start_runtime_ms_;
2690 } test;
2691
asapersson01d70a32016-05-20 06:29:46 -07002692 metrics::Reset();
stefane74eef12016-01-08 06:47:13 -08002693 RunBaseTest(&test);
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002694
asapersson01d70a32016-05-20 06:29:46 -07002695 EXPECT_EQ(
2696 1, metrics::NumSamples("WebRTC.Video.UniqueNackRequestsSentInPercent"));
2697 EXPECT_EQ(1, metrics::NumSamples(
2698 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
2699 EXPECT_GT(metrics::MinSample("WebRTC.Video.NackPacketsSentPerMinute"), 0);
Ã…sa Persson352b2d72015-04-15 18:00:40 +02002700}
2701
sprangb4a1ae52015-12-03 08:10:08 -08002702void EndToEndTest::VerifyHistogramStats(bool use_rtx,
2703 bool use_red,
2704 bool screenshare) {
tommi2e82f382016-06-21 00:26:43 -07002705 class StatsObserver : public test::EndToEndTest,
2706 public rtc::VideoSinkInterface<VideoFrame> {
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002707 public:
sprangb4a1ae52015-12-03 08:10:08 -08002708 StatsObserver(bool use_rtx, bool use_red, bool screenshare)
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002709 : EndToEndTest(kLongTimeoutMs),
2710 use_rtx_(use_rtx),
2711 use_red_(use_red),
sprangb4a1ae52015-12-03 08:10:08 -08002712 screenshare_(screenshare),
Peter Boström39593972016-02-15 11:27:15 +01002713 // This test uses NACK, so to send FEC we can't use a fake encoder.
magjed509e4fe2016-11-18 01:34:11 -08002714 vp8_encoder_(use_red ? VP8Encoder::Create() : nullptr),
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002715 sender_call_(nullptr),
2716 receiver_call_(nullptr),
asapersson1394c7b2016-10-18 11:50:50 -07002717 start_runtime_ms_(-1),
2718 num_frames_received_(0) {}
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002719
2720 private:
asapersson1394c7b2016-10-18 11:50:50 -07002721 void OnFrame(const VideoFrame& video_frame) override {
2722 // The RTT is needed to estimate |ntp_time_ms| which is used by
2723 // end-to-end delay stats. Therefore, start counting received frames once
2724 // |ntp_time_ms| is valid.
2725 if (video_frame.ntp_time_ms() > 0 &&
2726 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds() >=
2727 video_frame.ntp_time_ms()) {
2728 rtc::CritScope lock(&crit_);
2729 ++num_frames_received_;
2730 }
2731 }
tommi2e82f382016-06-21 00:26:43 -07002732
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002733 Action OnSendRtp(const uint8_t* packet, size_t length) override {
asapersson1394c7b2016-10-18 11:50:50 -07002734 if (MinMetricRunTimePassed() && MinNumberOfFramesReceived())
Peter Boström5811a392015-12-10 13:02:50 +01002735 observation_complete_.Set();
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002736
stefanf116bd02015-10-27 08:29:42 -07002737 return SEND_PACKET;
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002738 }
2739
2740 bool MinMetricRunTimePassed() {
2741 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
2742 if (start_runtime_ms_ == -1) {
2743 start_runtime_ms_ = now;
2744 return false;
2745 }
2746 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
2747 return elapsed_sec > metrics::kMinRunTimeInSeconds * 2;
2748 }
2749
asapersson1394c7b2016-10-18 11:50:50 -07002750 bool MinNumberOfFramesReceived() const {
2751 const int kMinRequiredHistogramSamples = 200;
2752 rtc::CritScope lock(&crit_);
2753 return num_frames_received_ > kMinRequiredHistogramSamples;
2754 }
2755
stefanff483612015-12-21 03:14:00 -08002756 void ModifyVideoConfigs(
2757 VideoSendStream::Config* send_config,
2758 std::vector<VideoReceiveStream::Config>* receive_configs,
2759 VideoEncoderConfig* encoder_config) override {
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002760 // NACK
2761 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2762 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
tommi2e82f382016-06-21 00:26:43 -07002763 (*receive_configs)[0].renderer = this;
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002764 // FEC
2765 if (use_red_) {
brandtrb5f2c3f2016-10-04 23:28:39 -07002766 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
2767 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
Peter Boström39593972016-02-15 11:27:15 +01002768 send_config->encoder_settings.encoder = vp8_encoder_.get();
2769 send_config->encoder_settings.payload_name = "VP8";
2770 (*receive_configs)[0].decoders[0].payload_name = "VP8";
brandtrb5f2c3f2016-10-04 23:28:39 -07002771 (*receive_configs)[0].rtp.ulpfec.red_payload_type = kRedPayloadType;
2772 (*receive_configs)[0].rtp.ulpfec.ulpfec_payload_type =
2773 kUlpfecPayloadType;
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002774 }
2775 // RTX
2776 if (use_rtx_) {
2777 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
2778 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
brandtr14742122017-01-27 04:53:07 -08002779 (*receive_configs)[0].rtp.rtx_ssrc = kSendRtxSsrcs[0];
nisse26e3abb2017-08-25 04:44:25 -07002780 (*receive_configs)[0]
2781 .rtp.rtx_associated_payload_types[kSendRtxPayloadType] =
2782 kFakeVideoSendPayloadType;
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002783 }
asapersson1490f7a2016-09-23 02:09:46 -07002784 // RTT needed for RemoteNtpTimeEstimator for the receive stream.
2785 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report = true;
sprangb4a1ae52015-12-03 08:10:08 -08002786 encoder_config->content_type =
2787 screenshare_ ? VideoEncoderConfig::ContentType::kScreen
2788 : VideoEncoderConfig::ContentType::kRealtimeVideo;
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002789 }
2790
2791 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2792 sender_call_ = sender_call;
2793 receiver_call_ = receiver_call;
2794 }
2795
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002796 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002797 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002798 }
2799
asapersson1394c7b2016-10-18 11:50:50 -07002800 rtc::CriticalSection crit_;
sprangb4a1ae52015-12-03 08:10:08 -08002801 const bool use_rtx_;
2802 const bool use_red_;
2803 const bool screenshare_;
kwiberg27f982b2016-03-01 11:52:33 -08002804 const std::unique_ptr<VideoEncoder> vp8_encoder_;
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002805 Call* sender_call_;
2806 Call* receiver_call_;
2807 int64_t start_runtime_ms_;
asapersson1394c7b2016-10-18 11:50:50 -07002808 int num_frames_received_ GUARDED_BY(&crit_);
sprangb4a1ae52015-12-03 08:10:08 -08002809 } test(use_rtx, use_red, screenshare);
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002810
asapersson01d70a32016-05-20 06:29:46 -07002811 metrics::Reset();
stefane74eef12016-01-08 06:47:13 -08002812 RunBaseTest(&test);
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002813
sprangb4a1ae52015-12-03 08:10:08 -08002814 std::string video_prefix =
2815 screenshare ? "WebRTC.Video.Screenshare." : "WebRTC.Video.";
ilnik6d5b4d62017-08-30 03:32:14 -07002816 // The content type extension is disabled in non screenshare test,
2817 // therefore no slicing on simulcast id should be present.
2818 std::string video_suffix = screenshare ? ".S0" : "";
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002819 // Verify that stats have been updated once.
asapersson4374a092016-07-27 00:39:09 -07002820 EXPECT_EQ(2, metrics::NumSamples("WebRTC.Call.LifetimeInSeconds"));
saza0d7f04d2017-07-04 04:05:06 -07002821 EXPECT_EQ(1, metrics::NumSamples(
2822 "WebRTC.Call.TimeReceivingVideoRtpPacketsInSeconds"));
asapersson01d70a32016-05-20 06:29:46 -07002823 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.VideoBitrateReceivedInKbps"));
2824 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.RtcpBitrateReceivedInBps"));
2825 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.BitrateReceivedInKbps"));
2826 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.EstimatedSendBitrateInKbps"));
2827 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.PacerBitrateInKbps"));
2828
asapersson4374a092016-07-27 00:39:09 -07002829 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SendStreamLifetimeInSeconds"));
2830 EXPECT_EQ(1,
2831 metrics::NumSamples("WebRTC.Video.ReceiveStreamLifetimeInSeconds"));
2832
asapersson01d70a32016-05-20 06:29:46 -07002833 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
stefan91d92602015-11-11 10:13:02 -08002834 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002835 metrics::NumSamples(video_prefix + "NackPacketsReceivedPerMinute"));
2836 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
asaperssond89920b2015-07-22 06:52:00 -07002837 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002838 metrics::NumSamples(video_prefix + "FirPacketsReceivedPerMinute"));
2839 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
sprangb4a1ae52015-12-03 08:10:08 -08002840 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002841 metrics::NumSamples(video_prefix + "PliPacketsReceivedPerMinute"));
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002842
asapersson01d70a32016-05-20 06:29:46 -07002843 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "KeyFramesSentInPermille"));
2844 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
2845
2846 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentPacketsLostInPercent"));
2847 EXPECT_EQ(1,
2848 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
2849
2850 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputWidthInPixels"));
2851 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputHeightInPixels"));
2852 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentWidthInPixels"));
2853 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentHeightInPixels"));
ilnik6d5b4d62017-08-30 03:32:14 -07002854 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "ReceivedWidthInPixels"));
2855 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "ReceivedHeightInPixels"));
asapersson01d70a32016-05-20 06:29:46 -07002856
perkjfa10b552016-10-02 23:45:26 -07002857 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "InputWidthInPixels",
2858 kDefaultWidth));
2859 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "InputHeightInPixels",
2860 kDefaultHeight));
2861 EXPECT_EQ(
2862 1, metrics::NumEvents(video_prefix + "SentWidthInPixels", kDefaultWidth));
2863 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "SentHeightInPixels",
2864 kDefaultHeight));
ilnik6d5b4d62017-08-30 03:32:14 -07002865 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "ReceivedWidthInPixels",
perkjfa10b552016-10-02 23:45:26 -07002866 kDefaultWidth));
ilnik6d5b4d62017-08-30 03:32:14 -07002867 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "ReceivedHeightInPixels",
perkjfa10b552016-10-02 23:45:26 -07002868 kDefaultHeight));
asapersson01d70a32016-05-20 06:29:46 -07002869
2870 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputFramesPerSecond"));
2871 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentFramesPerSecond"));
2872 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
2873 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
2874
2875 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
2876 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
2877 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
2878 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
2879
ilnik6d5b4d62017-08-30 03:32:14 -07002880 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "EndToEndDelayInMs" +
2881 video_suffix));
2882 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "EndToEndDelayMaxInMs" +
2883 video_suffix));
2884 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InterframeDelayInMs" +
2885 video_suffix));
2886 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InterframeDelayMaxInMs" +
2887 video_suffix));
ilnik4257ab22017-07-03 01:15:58 -07002888
asapersson01d70a32016-05-20 06:29:46 -07002889 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
2890
2891 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "EncodeTimeInMs"));
2892 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodeTimeInMs"));
2893
asapersson66d4b372016-12-19 06:50:53 -08002894 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "NumberOfPauseEvents"));
2895 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "PausedTimeInPercent"));
2896
asapersson01d70a32016-05-20 06:29:46 -07002897 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "BitrateSentInKbps"));
2898 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateReceivedInKbps"));
2899 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "MediaBitrateSentInKbps"));
2900 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.MediaBitrateReceivedInKbps"));
2901 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "PaddingBitrateSentInKbps"));
2902 EXPECT_EQ(1,
2903 metrics::NumSamples("WebRTC.Video.PaddingBitrateReceivedInKbps"));
asapersson6f14be82015-11-16 00:40:49 -08002904 EXPECT_EQ(
asapersson01d70a32016-05-20 06:29:46 -07002905 1, metrics::NumSamples(video_prefix + "RetransmittedBitrateSentInKbps"));
2906 EXPECT_EQ(1, metrics::NumSamples(
2907 "WebRTC.Video.RetransmittedBitrateReceivedInKbps"));
asapersson6f14be82015-11-16 00:40:49 -08002908
asapersson01d70a32016-05-20 06:29:46 -07002909 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SendDelayInMs"));
2910 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SendSideDelayInMs"));
2911 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SendSideDelayMaxInMs"));
asapersson6f14be82015-11-16 00:40:49 -08002912
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002913 int num_rtx_samples = use_rtx ? 1 : 0;
asapersson01d70a32016-05-20 06:29:46 -07002914 EXPECT_EQ(num_rtx_samples,
2915 metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2916 EXPECT_EQ(num_rtx_samples,
2917 metrics::NumSamples("WebRTC.Video.RtxBitrateReceivedInKbps"));
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002918
2919 int num_red_samples = use_red ? 1 : 0;
asapersson01d70a32016-05-20 06:29:46 -07002920 EXPECT_EQ(num_red_samples,
2921 metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2922 EXPECT_EQ(num_red_samples,
2923 metrics::NumSamples("WebRTC.Video.FecBitrateReceivedInKbps"));
2924 EXPECT_EQ(num_red_samples,
2925 metrics::NumSamples("WebRTC.Video.ReceivedFecPacketsInPercent"));
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02002926}
2927
Lu Liufb9e7512017-04-13 14:09:56 -07002928#if defined(WEBRTC_WIN)
2929// Disabled due to flakiness on Windows (bugs.webrtc.org/7483).
2930#define MAYBE_ContentTypeSwitches DISABLED_ContentTypeSwitches
2931#else
2932#define MAYBE_ContentTypeSwitches ContentTypeSwitches
2933#endif
2934TEST_F(EndToEndTest, MAYBE_ContentTypeSwitches) {
ilnik00d802b2017-04-11 10:34:31 -07002935 class StatsObserver : public test::BaseTest,
2936 public rtc::VideoSinkInterface<VideoFrame> {
2937 public:
2938 StatsObserver() : BaseTest(kLongTimeoutMs), num_frames_received_(0) {}
2939
2940 bool ShouldCreateReceivers() const override { return true; }
2941
2942 void OnFrame(const VideoFrame& video_frame) override {
2943 // The RTT is needed to estimate |ntp_time_ms| which is used by
2944 // end-to-end delay stats. Therefore, start counting received frames once
2945 // |ntp_time_ms| is valid.
2946 if (video_frame.ntp_time_ms() > 0 &&
2947 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds() >=
2948 video_frame.ntp_time_ms()) {
2949 rtc::CritScope lock(&crit_);
2950 ++num_frames_received_;
2951 }
2952 }
2953
2954 Action OnSendRtp(const uint8_t* packet, size_t length) override {
2955 if (MinNumberOfFramesReceived())
2956 observation_complete_.Set();
2957 return SEND_PACKET;
2958 }
2959
2960 bool MinNumberOfFramesReceived() const {
ilnikf6f808f2017-04-18 09:17:53 -07002961 // Have some room for frames with wrong content type during switch.
2962 const int kMinRequiredHistogramSamples = 200+50;
ilnik00d802b2017-04-11 10:34:31 -07002963 rtc::CritScope lock(&crit_);
2964 return num_frames_received_ > kMinRequiredHistogramSamples;
2965 }
2966
2967 // May be called several times.
2968 void PerformTest() override {
2969 EXPECT_TRUE(Wait()) << "Timed out waiting for enough packets.";
2970 // Reset frame counter so next PerformTest() call will do something.
2971 {
2972 rtc::CritScope lock(&crit_);
2973 num_frames_received_ = 0;
2974 }
2975 }
2976
2977 rtc::CriticalSection crit_;
2978 int num_frames_received_ GUARDED_BY(&crit_);
2979 } test;
2980
2981 metrics::Reset();
2982
2983 Call::Config send_config(test.GetSenderCallConfig());
ilnik00d802b2017-04-11 10:34:31 -07002984 Call::Config recv_config(test.GetReceiverCallConfig());
eladalon413ee9a2017-08-22 04:02:52 -07002985 VideoEncoderConfig encoder_config_with_screenshare;
ilnik00d802b2017-04-11 10:34:31 -07002986
ilnik41cadbc2017-08-23 00:44:27 -07002987 task_queue_.SendTask([this, &test, &send_config,
eladalon413ee9a2017-08-22 04:02:52 -07002988 &recv_config, &encoder_config_with_screenshare]() {
2989 CreateSenderCall(send_config);
2990 CreateReceiverCall(recv_config);
ilnik00d802b2017-04-11 10:34:31 -07002991
eladalon413ee9a2017-08-22 04:02:52 -07002992 receive_transport_.reset(test.CreateReceiveTransport(&task_queue_));
2993 send_transport_.reset(
2994 test.CreateSendTransport(&task_queue_, sender_call_.get()));
2995 send_transport_->SetReceiver(receiver_call_->Receiver());
2996 receive_transport_->SetReceiver(sender_call_->Receiver());
2997
2998 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
2999 CreateSendConfig(1, 0, 0, send_transport_.get());
3000 CreateMatchingReceiveConfigs(receive_transport_.get());
3001
3002 // Modify send and receive configs.
3003 video_send_config_.rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
3004 video_receive_configs_[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
3005 video_receive_configs_[0].renderer = &test;
3006 // RTT needed for RemoteNtpTimeEstimator for the receive stream.
3007 video_receive_configs_[0].rtp.rtcp_xr.receiver_reference_time_report = true;
3008 // Start with realtime video.
3009 video_encoder_config_.content_type =
3010 VideoEncoderConfig::ContentType::kRealtimeVideo;
3011 // Second encoder config for the second part of the test uses screenshare
3012 encoder_config_with_screenshare = video_encoder_config_.Copy();
3013 encoder_config_with_screenshare.content_type =
3014 VideoEncoderConfig::ContentType::kScreen;
3015
3016 CreateVideoStreams();
3017 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
3018 kDefaultHeight);
3019 Start();
3020 });
ilnik00d802b2017-04-11 10:34:31 -07003021
3022 test.PerformTest();
3023
3024 // Replace old send stream.
eladalon413ee9a2017-08-22 04:02:52 -07003025 task_queue_.SendTask([this, &encoder_config_with_screenshare]() {
3026 sender_call_->DestroyVideoSendStream(video_send_stream_);
3027 video_send_stream_ = sender_call_->CreateVideoSendStream(
3028 video_send_config_.Copy(), encoder_config_with_screenshare.Copy());
3029 video_send_stream_->SetSource(
3030 frame_generator_capturer_.get(),
3031 VideoSendStream::DegradationPreference::kBalanced);
3032 video_send_stream_->Start();
3033 });
ilnik00d802b2017-04-11 10:34:31 -07003034
3035 // Continue to run test but now with screenshare.
3036 test.PerformTest();
3037
eladalon413ee9a2017-08-22 04:02:52 -07003038 task_queue_.SendTask([this]() {
3039 Stop();
3040 DestroyStreams();
3041 send_transport_.reset();
3042 receive_transport_.reset();
3043 DestroyCalls();
3044 });
ilnik00d802b2017-04-11 10:34:31 -07003045
3046 // Verify that stats have been updated for both screenshare and video.
3047 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.EndToEndDelayInMs"));
3048 EXPECT_EQ(1,
3049 metrics::NumSamples("WebRTC.Video.Screenshare.EndToEndDelayInMs"));
3050 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.EndToEndDelayMaxInMs"));
3051 EXPECT_EQ(
3052 1, metrics::NumSamples("WebRTC.Video.Screenshare.EndToEndDelayMaxInMs"));
ilnik4257ab22017-07-03 01:15:58 -07003053 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs"));
3054 EXPECT_EQ(1,
3055 metrics::NumSamples(
3056 "WebRTC.Video.Screenshare.InterframeDelayInMs"));
3057 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs"));
3058 EXPECT_EQ(1,
3059 metrics::NumSamples(
3060 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs"));
ilnik00d802b2017-04-11 10:34:31 -07003061}
3062
philipel277a8b52017-03-16 05:19:49 -07003063TEST_F(EndToEndTest, VerifyHistogramStatsWithRtx) {
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02003064 const bool kEnabledRtx = true;
3065 const bool kEnabledRed = false;
sprangb4a1ae52015-12-03 08:10:08 -08003066 const bool kScreenshare = false;
3067 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02003068}
3069
philipel277a8b52017-03-16 05:19:49 -07003070TEST_F(EndToEndTest, VerifyHistogramStatsWithRed) {
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02003071 const bool kEnabledRtx = false;
3072 const bool kEnabledRed = true;
sprangb4a1ae52015-12-03 08:10:08 -08003073 const bool kScreenshare = false;
3074 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
3075}
3076
philipel277a8b52017-03-16 05:19:49 -07003077TEST_F(EndToEndTest, VerifyHistogramStatsWithScreenshare) {
sprangb4a1ae52015-12-03 08:10:08 -08003078 const bool kEnabledRtx = false;
3079 const bool kEnabledRed = false;
3080 const bool kScreenshare = true;
3081 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Ã…sa Persson3c391cb2015-04-27 10:09:49 +02003082}
3083
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003084void EndToEndTest::TestSendsSetSsrcs(size_t num_ssrcs,
3085 bool send_single_ssrc_first) {
3086 class SendsSetSsrcs : public test::EndToEndTest {
3087 public:
3088 SendsSetSsrcs(const uint32_t* ssrcs,
3089 size_t num_ssrcs,
3090 bool send_single_ssrc_first)
3091 : EndToEndTest(kDefaultTimeoutMs),
3092 num_ssrcs_(num_ssrcs),
3093 send_single_ssrc_first_(send_single_ssrc_first),
3094 ssrcs_to_observe_(num_ssrcs),
sprang867fb522015-08-03 04:38:41 -07003095 expect_single_ssrc_(send_single_ssrc_first),
3096 send_stream_(nullptr) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003097 for (size_t i = 0; i < num_ssrcs; ++i)
3098 valid_ssrcs_[ssrcs[i]] = true;
3099 }
3100
3101 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003102 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003103 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00003104 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003105
3106 EXPECT_TRUE(valid_ssrcs_[header.ssrc])
3107 << "Received unknown SSRC: " << header.ssrc;
3108
3109 if (!valid_ssrcs_[header.ssrc])
Peter Boström5811a392015-12-10 13:02:50 +01003110 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003111
3112 if (!is_observed_[header.ssrc]) {
3113 is_observed_[header.ssrc] = true;
3114 --ssrcs_to_observe_;
3115 if (expect_single_ssrc_) {
3116 expect_single_ssrc_ = false;
Peter Boström5811a392015-12-10 13:02:50 +01003117 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003118 }
3119 }
3120
3121 if (ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01003122 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003123
3124 return SEND_PACKET;
3125 }
3126
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003127 size_t GetNumVideoStreams() const override { return num_ssrcs_; }
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003128
perkjfa10b552016-10-02 23:45:26 -07003129 // This test use other VideoStream settings than the the default settings
3130 // implemented in DefaultVideoStreamFactory. Therefore this test implement
3131 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
3132 // in ModifyVideoConfigs.
3133 class VideoStreamFactory
3134 : public VideoEncoderConfig::VideoStreamFactoryInterface {
3135 public:
3136 VideoStreamFactory() {}
3137
3138 private:
3139 std::vector<VideoStream> CreateEncoderStreams(
3140 int width,
3141 int height,
3142 const VideoEncoderConfig& encoder_config) override {
3143 std::vector<VideoStream> streams =
3144 test::CreateVideoStreams(width, height, encoder_config);
3145 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
3146 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
3147 streams[i].min_bitrate_bps = 10000;
3148 streams[i].target_bitrate_bps = 15000;
3149 streams[i].max_bitrate_bps = 20000;
3150 }
3151 return streams;
3152 }
3153 };
3154
stefanff483612015-12-21 03:14:00 -08003155 void ModifyVideoConfigs(
3156 VideoSendStream::Config* send_config,
3157 std::vector<VideoReceiveStream::Config>* receive_configs,
3158 VideoEncoderConfig* encoder_config) override {
perkjfa10b552016-10-02 23:45:26 -07003159 encoder_config->video_stream_factory =
3160 new rtc::RefCountedObject<VideoStreamFactory>();
perkj26091b12016-09-01 01:17:40 -07003161 video_encoder_config_all_streams_ = encoder_config->Copy();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003162 if (send_single_ssrc_first_)
perkjfa10b552016-10-02 23:45:26 -07003163 encoder_config->number_of_streams = 1;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003164 }
3165
stefanff483612015-12-21 03:14:00 -08003166 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003167 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00003168 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003169 send_stream_ = send_stream;
3170 }
3171
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003172 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003173 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
3174 << (send_single_ssrc_first_ ? "first SSRC."
3175 : "SSRCs.");
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003176
3177 if (send_single_ssrc_first_) {
3178 // Set full simulcast and continue with the rest of the SSRCs.
stefanff483612015-12-21 03:14:00 -08003179 send_stream_->ReconfigureVideoEncoder(
perkj26091b12016-09-01 01:17:40 -07003180 std::move(video_encoder_config_all_streams_));
Peter Boström5811a392015-12-10 13:02:50 +01003181 EXPECT_TRUE(Wait()) << "Timed out while waiting on additional SSRCs.";
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003182 }
3183 }
3184
3185 private:
3186 std::map<uint32_t, bool> valid_ssrcs_;
3187 std::map<uint32_t, bool> is_observed_;
3188
3189 const size_t num_ssrcs_;
3190 const bool send_single_ssrc_first_;
3191
3192 size_t ssrcs_to_observe_;
3193 bool expect_single_ssrc_;
3194
3195 VideoSendStream* send_stream_;
stefanff483612015-12-21 03:14:00 -08003196 VideoEncoderConfig video_encoder_config_all_streams_;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003197 } test(kVideoSendSsrcs, num_ssrcs, send_single_ssrc_first);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003198
stefane74eef12016-01-08 06:47:13 -08003199 RunBaseTest(&test);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003200}
3201
philipel277a8b52017-03-16 05:19:49 -07003202TEST_F(EndToEndTest, ReportsSetEncoderRates) {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003203 class EncoderRateStatsTest : public test::EndToEndTest,
3204 public test::FakeEncoder {
3205 public:
eladalon413ee9a2017-08-22 04:02:52 -07003206 explicit EncoderRateStatsTest(
3207 test::SingleThreadedTaskQueueForTesting* task_queue)
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003208 : EndToEndTest(kDefaultTimeoutMs),
sprang867fb522015-08-03 04:38:41 -07003209 FakeEncoder(Clock::GetRealTimeClock()),
eladalon413ee9a2017-08-22 04:02:52 -07003210 task_queue_(task_queue),
sprang867fb522015-08-03 04:38:41 -07003211 send_stream_(nullptr),
3212 bitrate_kbps_(0) {}
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003213
stefanff483612015-12-21 03:14:00 -08003214 void OnVideoStreamsCreated(
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003215 VideoSendStream* send_stream,
3216 const std::vector<VideoReceiveStream*>& receive_streams) override {
3217 send_stream_ = send_stream;
3218 }
3219
stefanff483612015-12-21 03:14:00 -08003220 void ModifyVideoConfigs(
3221 VideoSendStream::Config* send_config,
3222 std::vector<VideoReceiveStream::Config>* receive_configs,
3223 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003224 send_config->encoder_settings.encoder = this;
kwibergaf476c72016-11-28 15:21:39 -08003225 RTC_DCHECK_EQ(1, encoder_config->number_of_streams);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003226 }
3227
Erik Språng08127a92016-11-16 16:41:30 +01003228 int32_t SetRateAllocation(const BitrateAllocation& rate_allocation,
3229 uint32_t framerate) override {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003230 // Make sure not to trigger on any default zero bitrates.
Erik Språng08127a92016-11-16 16:41:30 +01003231 if (rate_allocation.get_sum_bps() == 0)
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003232 return 0;
Peter Boströmf2f82832015-05-01 13:00:41 +02003233 rtc::CritScope lock(&crit_);
Erik Språng08127a92016-11-16 16:41:30 +01003234 bitrate_kbps_ = rate_allocation.get_sum_kbps();
Peter Boström5811a392015-12-10 13:02:50 +01003235 observation_complete_.Set();
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003236 return 0;
3237 }
3238
3239 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003240 ASSERT_TRUE(Wait())
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003241 << "Timed out while waiting for encoder SetRates() call.";
eladalon413ee9a2017-08-22 04:02:52 -07003242
3243 task_queue_->SendTask([this]() {
3244 WaitForEncoderTargetBitrateMatchStats();
3245 send_stream_->Stop();
3246 WaitForStatsReportZeroTargetBitrate();
3247 send_stream_->Start();
3248 WaitForEncoderTargetBitrateMatchStats();
3249 });
perkjf5b2e512016-07-05 08:34:04 -07003250 }
3251
3252 void WaitForEncoderTargetBitrateMatchStats() {
Peter Boström5811a392015-12-10 13:02:50 +01003253 for (int i = 0; i < kDefaultTimeoutMs; ++i) {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003254 VideoSendStream::Stats stats = send_stream_->GetStats();
3255 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003256 rtc::CritScope lock(&crit_);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003257 if ((stats.target_media_bitrate_bps + 500) / 1000 ==
3258 static_cast<int>(bitrate_kbps_)) {
3259 return;
3260 }
3261 }
3262 SleepMs(1);
3263 }
3264 FAIL()
3265 << "Timed out waiting for stats reporting the currently set bitrate.";
3266 }
3267
perkjf5b2e512016-07-05 08:34:04 -07003268 void WaitForStatsReportZeroTargetBitrate() {
3269 for (int i = 0; i < kDefaultTimeoutMs; ++i) {
3270 if (send_stream_->GetStats().target_media_bitrate_bps == 0) {
3271 return;
3272 }
3273 SleepMs(1);
3274 }
3275 FAIL() << "Timed out waiting for stats reporting zero bitrate.";
3276 }
3277
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003278 private:
eladalon413ee9a2017-08-22 04:02:52 -07003279 test::SingleThreadedTaskQueueForTesting* const task_queue_;
stefanf116bd02015-10-27 08:29:42 -07003280 rtc::CriticalSection crit_;
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003281 VideoSendStream* send_stream_;
3282 uint32_t bitrate_kbps_ GUARDED_BY(crit_);
eladalon413ee9a2017-08-22 04:02:52 -07003283 } test(&task_queue_);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003284
stefane74eef12016-01-08 06:47:13 -08003285 RunBaseTest(&test);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003286}
3287
philipel277a8b52017-03-16 05:19:49 -07003288TEST_F(EndToEndTest, GetStats) {
pbos@webrtc.orgba253472014-11-25 09:39:04 +00003289 static const int kStartBitrateBps = 3000000;
Peter Boströmdef398832015-05-27 17:59:11 +02003290 static const int kExpectedRenderDelayMs = 20;
tommi2e82f382016-06-21 00:26:43 -07003291
3292 class ReceiveStreamRenderer : public rtc::VideoSinkInterface<VideoFrame> {
3293 public:
3294 ReceiveStreamRenderer() {}
3295
3296 private:
3297 void OnFrame(const VideoFrame& video_frame) override {}
3298 };
3299
nissed30a1112016-04-18 05:15:22 -07003300 class StatsObserver : public test::EndToEndTest,
3301 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003302 public:
stefanf116bd02015-10-27 08:29:42 -07003303 StatsObserver()
3304 : EndToEndTest(kLongTimeoutMs),
Peter Boströmc6e16e32016-02-05 14:15:53 +01003305 encoder_(Clock::GetRealTimeClock(), 10),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00003306 send_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003307 expected_send_ssrcs_(),
Peter Boström5811a392015-12-10 13:02:50 +01003308 check_stats_event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003309
3310 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003311 Action OnSendRtp(const uint8_t* packet, size_t length) override {
sprangcd349d92016-07-13 09:11:28 -07003312 // Drop every 25th packet => 4% loss.
3313 static const int kPacketLossFrac = 25;
3314 RTPHeader header;
3315 RtpUtility::RtpHeaderParser parser(packet, length);
3316 if (parser.Parse(&header) &&
3317 expected_send_ssrcs_.find(header.ssrc) !=
3318 expected_send_ssrcs_.end() &&
3319 header.sequenceNumber % kPacketLossFrac == 0) {
3320 return DROP_PACKET;
3321 }
Peter Boström5811a392015-12-10 13:02:50 +01003322 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003323 return SEND_PACKET;
3324 }
3325
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003326 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01003327 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003328 return SEND_PACKET;
3329 }
3330
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003331 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01003332 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003333 return SEND_PACKET;
3334 }
3335
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003336 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01003337 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003338 return SEND_PACKET;
3339 }
3340
nissed30a1112016-04-18 05:15:22 -07003341 void OnFrame(const VideoFrame& video_frame) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003342 // Ensure that we have at least 5ms send side delay.
nissed30a1112016-04-18 05:15:22 -07003343 SleepMs(5);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003344 }
3345
3346 bool CheckReceiveStats() {
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003347 for (size_t i = 0; i < receive_streams_.size(); ++i) {
3348 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
3349 EXPECT_EQ(expected_receive_ssrcs_[i], stats.ssrc);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003350
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003351 // Make sure all fields have been populated.
3352 // TODO(pbos): Use CompoundKey if/when we ever know that all stats are
3353 // always filled for all receivers.
3354 receive_stats_filled_["IncomingRate"] |=
3355 stats.network_frame_rate != 0 || stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003356
Peter Boströmb7d9a972015-12-18 16:01:11 +01003357 send_stats_filled_["DecoderImplementationName"] |=
3358 stats.decoder_implementation_name ==
3359 test::FakeDecoder::kImplementationName;
Peter Boströmdef398832015-05-27 17:59:11 +02003360 receive_stats_filled_["RenderDelayAsHighAsExpected"] |=
3361 stats.render_delay_ms >= kExpectedRenderDelayMs;
3362
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003363 receive_stats_filled_["FrameCallback"] |= stats.decode_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003364
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003365 receive_stats_filled_["FrameRendered"] |= stats.render_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003366
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003367 receive_stats_filled_["StatisticsUpdated"] |=
srte186d9c32017-08-04 05:03:53 -07003368 stats.rtcp_stats.packets_lost != 0 ||
3369 stats.rtcp_stats.extended_highest_sequence_number != 0 ||
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003370 stats.rtcp_stats.fraction_lost != 0 || stats.rtcp_stats.jitter != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003371
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003372 receive_stats_filled_["DataCountersUpdated"] |=
3373 stats.rtp_stats.transmitted.payload_bytes != 0 ||
3374 stats.rtp_stats.fec.packets != 0 ||
3375 stats.rtp_stats.transmitted.header_bytes != 0 ||
3376 stats.rtp_stats.transmitted.packets != 0 ||
3377 stats.rtp_stats.transmitted.padding_bytes != 0 ||
3378 stats.rtp_stats.retransmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003379
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003380 receive_stats_filled_["CodecStats"] |=
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00003381 stats.target_delay_ms != 0 || stats.discarded_packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003382
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003383 receive_stats_filled_["FrameCounts"] |=
3384 stats.frame_counts.key_frames != 0 ||
3385 stats.frame_counts.delta_frames != 0;
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00003386
pbosbb36fdf2015-07-09 07:48:14 -07003387 receive_stats_filled_["CName"] |= !stats.c_name.empty();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00003388
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003389 receive_stats_filled_["RtcpPacketTypeCount"] |=
3390 stats.rtcp_packet_type_counts.fir_packets != 0 ||
3391 stats.rtcp_packet_type_counts.nack_packets != 0 ||
3392 stats.rtcp_packet_type_counts.pli_packets != 0 ||
3393 stats.rtcp_packet_type_counts.nack_requests != 0 ||
3394 stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbosf42376c2015-08-28 07:35:32 -07003395
3396 assert(stats.current_payload_type == -1 ||
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003397 stats.current_payload_type == kFakeVideoSendPayloadType);
pbosf42376c2015-08-28 07:35:32 -07003398 receive_stats_filled_["IncomingPayloadType"] |=
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003399 stats.current_payload_type == kFakeVideoSendPayloadType;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003400 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003401
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003402 return AllStatsFilled(receive_stats_filled_);
3403 }
3404
3405 bool CheckSendStats() {
Peter Boström74f6e9e2016-04-04 17:56:10 +02003406 RTC_DCHECK(send_stream_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003407 VideoSendStream::Stats stats = send_stream_->GetStats();
3408
philipel20d05a92016-12-19 04:17:27 -08003409 size_t expected_num_streams = kNumSsrcs + expected_send_ssrcs_.size();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003410 send_stats_filled_["NumStreams"] |=
philipel20d05a92016-12-19 04:17:27 -08003411 stats.substreams.size() == expected_num_streams;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003412
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00003413 send_stats_filled_["CpuOveruseMetrics"] |=
Peter Boströme4499152016-02-05 11:13:28 +01003414 stats.avg_encode_time_ms != 0 && stats.encode_usage_percent != 0;
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00003415
Peter Boströmb7d9a972015-12-18 16:01:11 +01003416 send_stats_filled_["EncoderImplementationName"] |=
3417 stats.encoder_implementation_name ==
3418 test::FakeEncoder::kImplementationName;
3419
Pera48ddb72016-09-29 11:48:50 +02003420 send_stats_filled_["EncoderPreferredBitrate"] |=
3421 stats.preferred_media_bitrate_bps > 0;
3422
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00003423 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003424 stats.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00003425 it != stats.substreams.end(); ++it) {
sprangcd349d92016-07-13 09:11:28 -07003426 if (expected_send_ssrcs_.find(it->first) == expected_send_ssrcs_.end())
3427 continue; // Probably RTX.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003428
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003429 send_stats_filled_[CompoundKey("CapturedFrameRate", it->first)] |=
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003430 stats.input_frame_rate != 0;
3431
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00003432 const VideoSendStream::StreamStats& stream_stats = it->second;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003433
3434 send_stats_filled_[CompoundKey("StatisticsUpdated", it->first)] |=
srte186d9c32017-08-04 05:03:53 -07003435 stream_stats.rtcp_stats.packets_lost != 0 ||
3436 stream_stats.rtcp_stats.extended_highest_sequence_number != 0 ||
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003437 stream_stats.rtcp_stats.fraction_lost != 0;
3438
3439 send_stats_filled_[CompoundKey("DataCountersUpdated", it->first)] |=
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00003440 stream_stats.rtp_stats.fec.packets != 0 ||
3441 stream_stats.rtp_stats.transmitted.padding_bytes != 0 ||
3442 stream_stats.rtp_stats.retransmitted.packets != 0 ||
3443 stream_stats.rtp_stats.transmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003444
sprangcd349d92016-07-13 09:11:28 -07003445 send_stats_filled_[CompoundKey("BitrateStatisticsObserver.Total",
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003446 it->first)] |=
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00003447 stream_stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003448
sprangcd349d92016-07-13 09:11:28 -07003449 send_stats_filled_[CompoundKey("BitrateStatisticsObserver.Retransmit",
3450 it->first)] |=
3451 stream_stats.retransmit_bitrate_bps != 0;
3452
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003453 send_stats_filled_[CompoundKey("FrameCountObserver", it->first)] |=
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00003454 stream_stats.frame_counts.delta_frames != 0 ||
3455 stream_stats.frame_counts.key_frames != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003456
3457 send_stats_filled_[CompoundKey("OutgoingRate", it->first)] |=
3458 stats.encode_frame_rate != 0;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +00003459
3460 send_stats_filled_[CompoundKey("Delay", it->first)] |=
3461 stream_stats.avg_delay_ms != 0 || stream_stats.max_delay_ms != 0;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003462
3463 // TODO(pbos): Use CompoundKey when the test makes sure that all SSRCs
3464 // report dropped packets.
3465 send_stats_filled_["RtcpPacketTypeCount"] |=
3466 stream_stats.rtcp_packet_type_counts.fir_packets != 0 ||
3467 stream_stats.rtcp_packet_type_counts.nack_packets != 0 ||
3468 stream_stats.rtcp_packet_type_counts.pli_packets != 0 ||
3469 stream_stats.rtcp_packet_type_counts.nack_requests != 0 ||
3470 stream_stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003471 }
3472
3473 return AllStatsFilled(send_stats_filled_);
3474 }
3475
3476 std::string CompoundKey(const char* name, uint32_t ssrc) {
3477 std::ostringstream oss;
3478 oss << name << "_" << ssrc;
3479 return oss.str();
3480 }
3481
3482 bool AllStatsFilled(const std::map<std::string, bool>& stats_map) {
sprangcd349d92016-07-13 09:11:28 -07003483 for (const auto& stat : stats_map) {
3484 if (!stat.second)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003485 return false;
3486 }
3487 return true;
3488 }
3489
eladalon413ee9a2017-08-22 04:02:52 -07003490 test::PacketTransport* CreateSendTransport(
3491 test::SingleThreadedTaskQueueForTesting* task_queue,
3492 Call* sender_call) override {
stefane74eef12016-01-08 06:47:13 -08003493 FakeNetworkPipe::Config network_config;
3494 network_config.loss_percent = 5;
eladalon413ee9a2017-08-22 04:02:52 -07003495 return new test::PacketTransport(task_queue, sender_call, this,
minyue20c84cc2017-04-10 16:57:57 -07003496 test::PacketTransport::kSender,
3497 payload_type_map_, network_config);
stefane74eef12016-01-08 06:47:13 -08003498 }
3499
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00003500 Call::Config GetSenderCallConfig() override {
pbos@webrtc.orgba253472014-11-25 09:39:04 +00003501 Call::Config config = EndToEndTest::GetSenderCallConfig();
Stefan Holmere5904162015-03-26 11:11:06 +01003502 config.bitrate_config.start_bitrate_bps = kStartBitrateBps;
pbos@webrtc.orgba253472014-11-25 09:39:04 +00003503 return config;
3504 }
3505
perkjfa10b552016-10-02 23:45:26 -07003506 // This test use other VideoStream settings than the the default settings
3507 // implemented in DefaultVideoStreamFactory. Therefore this test implement
3508 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
3509 // in ModifyVideoConfigs.
3510 class VideoStreamFactory
3511 : public VideoEncoderConfig::VideoStreamFactoryInterface {
3512 public:
3513 VideoStreamFactory() {}
3514
3515 private:
3516 std::vector<VideoStream> CreateEncoderStreams(
3517 int width,
3518 int height,
3519 const VideoEncoderConfig& encoder_config) override {
3520 std::vector<VideoStream> streams =
3521 test::CreateVideoStreams(width, height, encoder_config);
3522 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
3523 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
3524 streams[i].min_bitrate_bps = 10000;
3525 streams[i].target_bitrate_bps = 15000;
3526 streams[i].max_bitrate_bps = 20000;
3527 }
3528 return streams;
3529 }
3530 };
3531
stefanff483612015-12-21 03:14:00 -08003532 void ModifyVideoConfigs(
3533 VideoSendStream::Config* send_config,
3534 std::vector<VideoReceiveStream::Config>* receive_configs,
3535 VideoEncoderConfig* encoder_config) override {
perkjfa10b552016-10-02 23:45:26 -07003536 encoder_config->video_stream_factory =
3537 new rtc::RefCountedObject<VideoStreamFactory>();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003538 send_config->pre_encode_callback = this; // Used to inject delay.
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003539 expected_cname_ = send_config->rtp.c_name = "SomeCName";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003540
sprangcd349d92016-07-13 09:11:28 -07003541 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
3542 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
3543
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003544 const std::vector<uint32_t>& ssrcs = send_config->rtp.ssrcs;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003545 for (size_t i = 0; i < ssrcs.size(); ++i) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003546 expected_send_ssrcs_.insert(ssrcs[i]);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003547 expected_receive_ssrcs_.push_back(
3548 (*receive_configs)[i].rtp.remote_ssrc);
Peter Boströmdef398832015-05-27 17:59:11 +02003549 (*receive_configs)[i].render_delay_ms = kExpectedRenderDelayMs;
tommi2e82f382016-06-21 00:26:43 -07003550 (*receive_configs)[i].renderer = &receive_stream_renderer_;
sprangcd349d92016-07-13 09:11:28 -07003551 (*receive_configs)[i].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
3552
brandtr14742122017-01-27 04:53:07 -08003553 (*receive_configs)[i].rtp.rtx_ssrc = kSendRtxSsrcs[i];
nisse26e3abb2017-08-25 04:44:25 -07003554 (*receive_configs)[i]
3555 .rtp.rtx_associated_payload_types[kSendRtxPayloadType] =
3556 kFakeVideoSendPayloadType;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003557 }
sprangcd349d92016-07-13 09:11:28 -07003558
3559 for (size_t i = 0; i < kNumSsrcs; ++i)
3560 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
3561
Peter Boströmc6e16e32016-02-05 14:15:53 +01003562 // Use a delayed encoder to make sure we see CpuOveruseMetrics stats that
3563 // are non-zero.
3564 send_config->encoder_settings.encoder = &encoder_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003565 }
3566
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003567 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.orgece38902014-11-14 11:52:04 +00003568
stefanff483612015-12-21 03:14:00 -08003569 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003570 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00003571 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003572 send_stream_ = send_stream;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003573 receive_streams_ = receive_streams;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003574 }
3575
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003576 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003577 Clock* clock = Clock::GetRealTimeClock();
3578 int64_t now = clock->TimeInMilliseconds();
3579 int64_t stop_time = now + test::CallTest::kLongTimeoutMs;
3580 bool receive_ok = false;
3581 bool send_ok = false;
3582
3583 while (now < stop_time) {
3584 if (!receive_ok)
3585 receive_ok = CheckReceiveStats();
3586 if (!send_ok)
3587 send_ok = CheckSendStats();
3588
3589 if (receive_ok && send_ok)
3590 return;
3591
3592 int64_t time_until_timout_ = stop_time - now;
3593 if (time_until_timout_ > 0)
Peter Boström5811a392015-12-10 13:02:50 +01003594 check_stats_event_.Wait(time_until_timout_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003595 now = clock->TimeInMilliseconds();
3596 }
3597
3598 ADD_FAILURE() << "Timed out waiting for filled stats.";
3599 for (std::map<std::string, bool>::const_iterator it =
3600 receive_stats_filled_.begin();
eladalon413ee9a2017-08-22 04:02:52 -07003601 it != receive_stats_filled_.end(); ++it) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003602 if (!it->second) {
3603 ADD_FAILURE() << "Missing receive stats: " << it->first;
3604 }
3605 }
3606
3607 for (std::map<std::string, bool>::const_iterator it =
3608 send_stats_filled_.begin();
eladalon413ee9a2017-08-22 04:02:52 -07003609 it != send_stats_filled_.end(); ++it) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003610 if (!it->second) {
3611 ADD_FAILURE() << "Missing send stats: " << it->first;
3612 }
3613 }
3614 }
3615
Peter Boströmc6e16e32016-02-05 14:15:53 +01003616 test::DelayedEncoder encoder_;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003617 std::vector<VideoReceiveStream*> receive_streams_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003618 std::map<std::string, bool> receive_stats_filled_;
3619
3620 VideoSendStream* send_stream_;
3621 std::map<std::string, bool> send_stats_filled_;
3622
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003623 std::vector<uint32_t> expected_receive_ssrcs_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003624 std::set<uint32_t> expected_send_ssrcs_;
3625 std::string expected_cname_;
3626
Peter Boström5811a392015-12-10 13:02:50 +01003627 rtc::Event check_stats_event_;
tommi2e82f382016-06-21 00:26:43 -07003628 ReceiveStreamRenderer receive_stream_renderer_;
stefanf116bd02015-10-27 08:29:42 -07003629 } test;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003630
stefane74eef12016-01-08 06:47:13 -08003631 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003632}
3633
ilnik75204c52017-09-04 03:35:40 -07003634TEST_F(EndToEndTest, TimingFramesAreReported) {
ilnik2edc6842017-07-06 03:06:50 -07003635 static const int kExtensionId = 5;
3636
3637 class StatsObserver : public test::EndToEndTest {
3638 public:
3639 StatsObserver() : EndToEndTest(kLongTimeoutMs) {}
3640
3641 private:
ilnik2edc6842017-07-06 03:06:50 -07003642 void ModifyVideoConfigs(
3643 VideoSendStream::Config* send_config,
3644 std::vector<VideoReceiveStream::Config>* receive_configs,
3645 VideoEncoderConfig* encoder_config) override {
3646 send_config->rtp.extensions.clear();
3647 send_config->rtp.extensions.push_back(
3648 RtpExtension(RtpExtension::kVideoTimingUri, kExtensionId));
3649 for (size_t i = 0; i < receive_configs->size(); ++i) {
3650 (*receive_configs)[i].rtp.extensions.clear();
3651 (*receive_configs)[i].rtp.extensions.push_back(
3652 RtpExtension(RtpExtension::kVideoTimingUri, kExtensionId));
3653 }
3654 }
3655
3656 void OnVideoStreamsCreated(
3657 VideoSendStream* send_stream,
3658 const std::vector<VideoReceiveStream*>& receive_streams) override {
3659 receive_streams_ = receive_streams;
3660 }
3661
3662 void PerformTest() override {
3663 // No frames reported initially.
3664 for (size_t i = 0; i < receive_streams_.size(); ++i) {
ilnik75204c52017-09-04 03:35:40 -07003665 EXPECT_FALSE(receive_streams_[i]->GetStats().timing_frame_info);
ilnik2edc6842017-07-06 03:06:50 -07003666 }
3667 // Wait for at least one timing frame to be sent with 100ms grace period.
3668 SleepMs(kDefaultTimingFramesDelayMs + 100);
3669 // Check that timing frames are reported for each stream.
3670 for (size_t i = 0; i < receive_streams_.size(); ++i) {
ilnik75204c52017-09-04 03:35:40 -07003671 EXPECT_TRUE(receive_streams_[i]->GetStats().timing_frame_info);
ilnik2edc6842017-07-06 03:06:50 -07003672 }
3673 }
3674
3675 std::vector<VideoReceiveStream*> receive_streams_;
3676 } test;
3677
3678 RunBaseTest(&test);
3679}
3680
sprang1a646ee2016-12-01 06:34:11 -08003681class RtcpXrObserver : public test::EndToEndTest {
3682 public:
sprang44b3ef62017-01-13 07:30:25 -08003683 RtcpXrObserver(bool enable_rrtr, bool enable_target_bitrate)
sprang1a646ee2016-12-01 06:34:11 -08003684 : EndToEndTest(test::CallTest::kDefaultTimeoutMs),
3685 enable_rrtr_(enable_rrtr),
sprang44b3ef62017-01-13 07:30:25 -08003686 enable_target_bitrate_(enable_target_bitrate),
sprang1a646ee2016-12-01 06:34:11 -08003687 sent_rtcp_sr_(0),
3688 sent_rtcp_rr_(0),
3689 sent_rtcp_rrtr_(0),
3690 sent_rtcp_target_bitrate_(false),
3691 sent_rtcp_dlrr_(0) {}
3692
3693 private:
3694 // Receive stream should send RR packets (and RRTR packets if enabled).
3695 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
3696 rtc::CritScope lock(&crit_);
3697 test::RtcpPacketParser parser;
3698 EXPECT_TRUE(parser.Parse(packet, length));
3699
3700 sent_rtcp_rr_ += parser.receiver_report()->num_packets();
3701 EXPECT_EQ(0, parser.sender_report()->num_packets());
3702 EXPECT_GE(1, parser.xr()->num_packets());
3703 if (parser.xr()->num_packets() > 0) {
3704 if (parser.xr()->rrtr())
3705 ++sent_rtcp_rrtr_;
3706 EXPECT_FALSE(parser.xr()->dlrr());
3707 }
3708
3709 return SEND_PACKET;
3710 }
3711 // Send stream should send SR packets (and DLRR packets if enabled).
3712 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
3713 rtc::CritScope lock(&crit_);
3714 test::RtcpPacketParser parser;
3715 EXPECT_TRUE(parser.Parse(packet, length));
3716
3717 sent_rtcp_sr_ += parser.sender_report()->num_packets();
3718 EXPECT_LE(parser.xr()->num_packets(), 1);
3719 if (parser.xr()->num_packets() > 0) {
3720 EXPECT_FALSE(parser.xr()->rrtr());
3721 if (parser.xr()->dlrr())
3722 ++sent_rtcp_dlrr_;
3723 if (parser.xr()->target_bitrate())
3724 sent_rtcp_target_bitrate_ = true;
3725 }
3726
3727 if (sent_rtcp_sr_ > kNumRtcpReportPacketsToObserve &&
3728 sent_rtcp_rr_ > kNumRtcpReportPacketsToObserve &&
sprang44b3ef62017-01-13 07:30:25 -08003729 (sent_rtcp_target_bitrate_ || !enable_target_bitrate_)) {
sprang1a646ee2016-12-01 06:34:11 -08003730 if (enable_rrtr_) {
3731 EXPECT_GT(sent_rtcp_rrtr_, 0);
3732 EXPECT_GT(sent_rtcp_dlrr_, 0);
3733 } else {
3734 EXPECT_EQ(sent_rtcp_rrtr_, 0);
3735 EXPECT_EQ(sent_rtcp_dlrr_, 0);
3736 }
sprang44b3ef62017-01-13 07:30:25 -08003737 EXPECT_EQ(enable_target_bitrate_, sent_rtcp_target_bitrate_);
sprang1a646ee2016-12-01 06:34:11 -08003738 observation_complete_.Set();
3739 }
3740 return SEND_PACKET;
3741 }
3742
3743 void ModifyVideoConfigs(
3744 VideoSendStream::Config* send_config,
3745 std::vector<VideoReceiveStream::Config>* receive_configs,
3746 VideoEncoderConfig* encoder_config) override {
sprang44b3ef62017-01-13 07:30:25 -08003747 if (enable_target_bitrate_) {
3748 // TargetBitrate only signaled for screensharing.
3749 encoder_config->content_type = VideoEncoderConfig::ContentType::kScreen;
3750 }
sprang1a646ee2016-12-01 06:34:11 -08003751 (*receive_configs)[0].rtp.rtcp_mode = RtcpMode::kReducedSize;
3752 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report =
3753 enable_rrtr_;
3754 }
3755
3756 void PerformTest() override {
3757 EXPECT_TRUE(Wait())
3758 << "Timed out while waiting for RTCP SR/RR packets to be sent.";
3759 }
3760
3761 static const int kNumRtcpReportPacketsToObserve = 5;
3762
3763 rtc::CriticalSection crit_;
sprang44b3ef62017-01-13 07:30:25 -08003764 const bool enable_rrtr_;
3765 const bool enable_target_bitrate_;
sprang1a646ee2016-12-01 06:34:11 -08003766 int sent_rtcp_sr_;
3767 int sent_rtcp_rr_ GUARDED_BY(&crit_);
3768 int sent_rtcp_rrtr_ GUARDED_BY(&crit_);
3769 bool sent_rtcp_target_bitrate_ GUARDED_BY(&crit_);
3770 int sent_rtcp_dlrr_;
3771};
3772
philipel277a8b52017-03-16 05:19:49 -07003773TEST_F(EndToEndTest, TestExtendedReportsWithRrtrWithoutTargetBitrate) {
sprang44b3ef62017-01-13 07:30:25 -08003774 RtcpXrObserver test(true, false);
sprang1a646ee2016-12-01 06:34:11 -08003775 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003776}
3777
philipel277a8b52017-03-16 05:19:49 -07003778TEST_F(EndToEndTest, TestExtendedReportsWithoutRrtrWithoutTargetBitrate) {
sprang44b3ef62017-01-13 07:30:25 -08003779 RtcpXrObserver test(false, false);
3780 RunBaseTest(&test);
3781}
3782
philipel277a8b52017-03-16 05:19:49 -07003783TEST_F(EndToEndTest, TestExtendedReportsWithRrtrWithTargetBitrate) {
sprang44b3ef62017-01-13 07:30:25 -08003784 RtcpXrObserver test(true, true);
3785 RunBaseTest(&test);
3786}
3787
philipel277a8b52017-03-16 05:19:49 -07003788TEST_F(EndToEndTest, TestExtendedReportsWithoutRrtrWithTargetBitrate) {
sprang44b3ef62017-01-13 07:30:25 -08003789 RtcpXrObserver test(false, true);
sprang1a646ee2016-12-01 06:34:11 -08003790 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003791}
3792
philipel277a8b52017-03-16 05:19:49 -07003793TEST_F(EndToEndTest, TestReceivedRtpPacketStats) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003794 static const size_t kNumRtpPacketsToSend = 5;
3795 class ReceivedRtpStatsObserver : public test::EndToEndTest {
3796 public:
3797 ReceivedRtpStatsObserver()
3798 : EndToEndTest(kDefaultTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00003799 receive_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003800 sent_rtp_(0) {}
3801
3802 private:
stefanff483612015-12-21 03:14:00 -08003803 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003804 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00003805 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003806 receive_stream_ = receive_streams[0];
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003807 }
3808
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003809 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003810 if (sent_rtp_ >= kNumRtpPacketsToSend) {
3811 VideoReceiveStream::Stats stats = receive_stream_->GetStats();
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00003812 if (kNumRtpPacketsToSend == stats.rtp_stats.transmitted.packets) {
Peter Boström5811a392015-12-10 13:02:50 +01003813 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003814 }
3815 return DROP_PACKET;
3816 }
3817 ++sent_rtp_;
3818 return SEND_PACKET;
3819 }
3820
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003821 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003822 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003823 << "Timed out while verifying number of received RTP packets.";
3824 }
3825
3826 VideoReceiveStream* receive_stream_;
3827 uint32_t sent_rtp_;
3828 } test;
3829
stefane74eef12016-01-08 06:47:13 -08003830 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003831}
3832
philipel277a8b52017-03-16 05:19:49 -07003833TEST_F(EndToEndTest, SendsSetSsrc) {
philipel266f0a42016-11-28 08:49:07 -08003834 TestSendsSetSsrcs(1, false);
3835}
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003836
philipel277a8b52017-03-16 05:19:49 -07003837TEST_F(EndToEndTest, SendsSetSimulcastSsrcs) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003838 TestSendsSetSsrcs(kNumSsrcs, false);
3839}
3840
philipel277a8b52017-03-16 05:19:49 -07003841TEST_F(EndToEndTest, CanSwitchToUseAllSsrcs) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003842 TestSendsSetSsrcs(kNumSsrcs, true);
3843}
3844
philipel277a8b52017-03-16 05:19:49 -07003845TEST_F(EndToEndTest, DISABLED_RedundantPayloadsTransmittedOnAllSsrcs) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003846 class ObserveRedundantPayloads: public test::EndToEndTest {
3847 public:
3848 ObserveRedundantPayloads()
3849 : EndToEndTest(kDefaultTimeoutMs), ssrcs_to_observe_(kNumSsrcs) {
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00003850 for (size_t i = 0; i < kNumSsrcs; ++i) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003851 registered_rtx_ssrc_[kSendRtxSsrcs[i]] = true;
3852 }
3853 }
3854
3855 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003856 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003857 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00003858 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003859
3860 if (!registered_rtx_ssrc_[header.ssrc])
3861 return SEND_PACKET;
3862
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00003863 EXPECT_LE(header.headerLength + header.paddingLength, length);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003864 const bool packet_is_redundant_payload =
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00003865 header.headerLength + header.paddingLength < length;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003866
3867 if (!packet_is_redundant_payload)
3868 return SEND_PACKET;
3869
3870 if (!observed_redundant_retransmission_[header.ssrc]) {
3871 observed_redundant_retransmission_[header.ssrc] = true;
3872 if (--ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01003873 observation_complete_.Set();
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003874 }
3875
3876 return SEND_PACKET;
3877 }
3878
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003879 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003880
perkjfa10b552016-10-02 23:45:26 -07003881 // This test use other VideoStream settings than the the default settings
3882 // implemented in DefaultVideoStreamFactory. Therefore this test implement
3883 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
3884 // in ModifyVideoConfigs.
3885 class VideoStreamFactory
3886 : public VideoEncoderConfig::VideoStreamFactoryInterface {
3887 public:
3888 VideoStreamFactory() {}
3889
3890 private:
3891 std::vector<VideoStream> CreateEncoderStreams(
3892 int width,
3893 int height,
3894 const VideoEncoderConfig& encoder_config) override {
3895 std::vector<VideoStream> streams =
3896 test::CreateVideoStreams(width, height, encoder_config);
3897 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
3898 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
3899 streams[i].min_bitrate_bps = 10000;
3900 streams[i].target_bitrate_bps = 15000;
3901 streams[i].max_bitrate_bps = 20000;
3902 }
3903 return streams;
3904 }
3905 };
3906
stefanff483612015-12-21 03:14:00 -08003907 void ModifyVideoConfigs(
3908 VideoSendStream::Config* send_config,
3909 std::vector<VideoReceiveStream::Config>* receive_configs,
3910 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003911 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
perkjfa10b552016-10-02 23:45:26 -07003912 encoder_config->video_stream_factory =
3913 new rtc::RefCountedObject<VideoStreamFactory>();
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003914 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003915
3916 for (size_t i = 0; i < kNumSsrcs; ++i)
3917 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.orgad3b5a52014-10-24 09:23:21 +00003918
3919 // Significantly higher than max bitrates for all video streams -> forcing
3920 // padding to trigger redundant padding on all RTX SSRCs.
3921 encoder_config->min_transmit_bitrate_bps = 100000;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003922 }
3923
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003924 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003925 EXPECT_TRUE(Wait())
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003926 << "Timed out while waiting for redundant payloads on all SSRCs.";
3927 }
3928
3929 private:
3930 size_t ssrcs_to_observe_;
3931 std::map<uint32_t, bool> observed_redundant_retransmission_;
3932 std::map<uint32_t, bool> registered_rtx_ssrc_;
3933 } test;
3934
stefane74eef12016-01-08 06:47:13 -08003935 RunBaseTest(&test);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003936}
3937
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003938void EndToEndTest::TestRtpStatePreservation(bool use_rtx,
3939 bool provoke_rtcpsr_before_rtp) {
brandtr5e171752017-05-23 03:32:16 -07003940 // This test uses other VideoStream settings than the the default settings
3941 // implemented in DefaultVideoStreamFactory. Therefore this test implements
perkjfa10b552016-10-02 23:45:26 -07003942 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
3943 // in ModifyVideoConfigs.
3944 class VideoStreamFactory
3945 : public VideoEncoderConfig::VideoStreamFactoryInterface {
3946 public:
3947 VideoStreamFactory() {}
3948
3949 private:
3950 std::vector<VideoStream> CreateEncoderStreams(
3951 int width,
3952 int height,
3953 const VideoEncoderConfig& encoder_config) override {
3954 std::vector<VideoStream> streams =
3955 test::CreateVideoStreams(width, height, encoder_config);
3956
3957 if (encoder_config.number_of_streams > 1) {
3958 // Lower bitrates so that all streams send initially.
kwibergaf476c72016-11-28 15:21:39 -08003959 RTC_DCHECK_EQ(3, encoder_config.number_of_streams);
perkjfa10b552016-10-02 23:45:26 -07003960 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
3961 streams[i].min_bitrate_bps = 10000;
3962 streams[i].target_bitrate_bps = 15000;
3963 streams[i].max_bitrate_bps = 20000;
3964 }
3965 } else {
3966 // Use the same total bitrates when sending a single stream to avoid
3967 // lowering
3968 // the bitrate estimate and requiring a subsequent rampup.
3969 streams[0].min_bitrate_bps = 3 * 10000;
3970 streams[0].target_bitrate_bps = 3 * 15000;
3971 streams[0].max_bitrate_bps = 3 * 20000;
3972 }
3973 return streams;
3974 }
3975 };
3976
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003977 class RtpSequenceObserver : public test::RtpRtcpObserver {
3978 public:
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00003979 explicit RtpSequenceObserver(bool use_rtx)
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003980 : test::RtpRtcpObserver(kDefaultTimeoutMs),
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003981 ssrcs_to_observe_(kNumSsrcs) {
3982 for (size_t i = 0; i < kNumSsrcs; ++i) {
danilchap32cd2c42016-08-01 06:58:34 -07003983 ssrc_is_rtx_[kVideoSendSsrcs[i]] = false;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003984 if (use_rtx)
danilchap32cd2c42016-08-01 06:58:34 -07003985 ssrc_is_rtx_[kSendRtxSsrcs[i]] = true;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003986 }
3987 }
3988
3989 void ResetExpectedSsrcs(size_t num_expected_ssrcs) {
Peter Boströmf2f82832015-05-01 13:00:41 +02003990 rtc::CritScope lock(&crit_);
danilchap34877ee2016-02-01 08:25:04 -08003991 ssrc_observed_.clear();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003992 ssrcs_to_observe_ = num_expected_ssrcs;
3993 }
3994
3995 private:
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003996 void ValidateTimestampGap(uint32_t ssrc,
3997 uint32_t timestamp,
3998 bool only_padding)
3999 EXCLUSIVE_LOCKS_REQUIRED(crit_) {
4000 static const int32_t kMaxTimestampGap = kDefaultTimeoutMs * 90;
4001 auto timestamp_it = last_observed_timestamp_.find(ssrc);
4002 if (timestamp_it == last_observed_timestamp_.end()) {
4003 EXPECT_FALSE(only_padding);
4004 last_observed_timestamp_[ssrc] = timestamp;
4005 } else {
4006 // Verify timestamps are reasonably close.
4007 uint32_t latest_observed = timestamp_it->second;
4008 // Wraparound handling is unnecessary here as long as an int variable
4009 // is used to store the result.
4010 int32_t timestamp_gap = timestamp - latest_observed;
4011 EXPECT_LE(std::abs(timestamp_gap), kMaxTimestampGap)
4012 << "Gap in timestamps (" << latest_observed << " -> " << timestamp
4013 << ") too large for SSRC: " << ssrc << ".";
4014 timestamp_it->second = timestamp;
4015 }
4016 }
4017
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00004018 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004019 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00004020 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004021 const uint32_t ssrc = header.ssrc;
danilchap5c35cf92016-02-03 14:14:49 -08004022 const int64_t sequence_number =
4023 seq_numbers_unwrapper_.Unwrap(header.sequenceNumber);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004024 const uint32_t timestamp = header.timestamp;
danilchap34877ee2016-02-01 08:25:04 -08004025 const bool only_padding =
4026 header.headerLength + header.paddingLength == length;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004027
danilchap32cd2c42016-08-01 06:58:34 -07004028 EXPECT_TRUE(ssrc_is_rtx_.find(ssrc) != ssrc_is_rtx_.end())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004029 << "Received SSRC that wasn't configured: " << ssrc;
4030
danilchap5c35cf92016-02-03 14:14:49 -08004031 static const int64_t kMaxSequenceNumberGap = 100;
4032 std::list<int64_t>* seq_numbers = &last_observed_seq_numbers_[ssrc];
4033 if (seq_numbers->empty()) {
4034 seq_numbers->push_back(sequence_number);
4035 } else {
4036 // We shouldn't get replays of previous sequence numbers.
4037 for (int64_t observed : *seq_numbers) {
4038 EXPECT_NE(observed, sequence_number)
4039 << "Received sequence number " << sequence_number
4040 << " for SSRC " << ssrc << " 2nd time.";
4041 }
4042 // Verify sequence numbers are reasonably close.
4043 int64_t latest_observed = seq_numbers->back();
4044 int64_t sequence_number_gap = sequence_number - latest_observed;
4045 EXPECT_LE(std::abs(sequence_number_gap), kMaxSequenceNumberGap)
4046 << "Gap in sequence numbers (" << latest_observed << " -> "
4047 << sequence_number << ") too large for SSRC: " << ssrc << ".";
4048 seq_numbers->push_back(sequence_number);
4049 if (seq_numbers->size() >= kMaxSequenceNumberGap) {
4050 seq_numbers->pop_front();
4051 }
4052 }
4053
danilchap32cd2c42016-08-01 06:58:34 -07004054 if (!ssrc_is_rtx_[ssrc]) {
4055 rtc::CritScope lock(&crit_);
4056 ValidateTimestampGap(ssrc, timestamp, only_padding);
Danil Chapovalov70ffead2016-07-20 15:26:59 +02004057
danilchap32cd2c42016-08-01 06:58:34 -07004058 // Wait for media packets on all ssrcs.
4059 if (!ssrc_observed_[ssrc] && !only_padding) {
4060 ssrc_observed_[ssrc] = true;
4061 if (--ssrcs_to_observe_ == 0)
4062 observation_complete_.Set();
4063 }
danilchap34877ee2016-02-01 08:25:04 -08004064 }
4065
danilchapf4b9c772016-01-28 06:14:24 -08004066 return SEND_PACKET;
4067 }
4068
Danil Chapovalov70ffead2016-07-20 15:26:59 +02004069 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
4070 test::RtcpPacketParser rtcp_parser;
4071 rtcp_parser.Parse(packet, length);
4072 if (rtcp_parser.sender_report()->num_packets() > 0) {
Danil Chapovalovba6f7be2016-09-02 18:29:10 +02004073 uint32_t ssrc = rtcp_parser.sender_report()->sender_ssrc();
4074 uint32_t rtcp_timestamp = rtcp_parser.sender_report()->rtp_timestamp();
Danil Chapovalov70ffead2016-07-20 15:26:59 +02004075
4076 rtc::CritScope lock(&crit_);
4077 ValidateTimestampGap(ssrc, rtcp_timestamp, false);
4078 }
4079 return SEND_PACKET;
4080 }
4081
danilchap5c35cf92016-02-03 14:14:49 -08004082 SequenceNumberUnwrapper seq_numbers_unwrapper_;
4083 std::map<uint32_t, std::list<int64_t>> last_observed_seq_numbers_;
danilchap34877ee2016-02-01 08:25:04 -08004084 std::map<uint32_t, uint32_t> last_observed_timestamp_;
danilchap32cd2c42016-08-01 06:58:34 -07004085 std::map<uint32_t, bool> ssrc_is_rtx_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004086
Peter Boströmf2f82832015-05-01 13:00:41 +02004087 rtc::CriticalSection crit_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004088 size_t ssrcs_to_observe_ GUARDED_BY(crit_);
danilchap34877ee2016-02-01 08:25:04 -08004089 std::map<uint32_t, bool> ssrc_observed_ GUARDED_BY(crit_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004090 } observer(use_rtx);
4091
eladalon413ee9a2017-08-22 04:02:52 -07004092 std::unique_ptr<test::PacketTransport> send_transport;
4093 std::unique_ptr<test::PacketTransport> receive_transport;
4094
philipel4fb651d2017-04-10 03:54:05 -07004095 Call::Config config(event_log_.get());
eladalon413ee9a2017-08-22 04:02:52 -07004096 VideoEncoderConfig one_stream;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004097
eladalon413ee9a2017-08-22 04:02:52 -07004098 task_queue_.SendTask([this, &observer, &send_transport, &receive_transport,
4099 &config, &one_stream, use_rtx]() {
4100 CreateCalls(config, config);
stefanf116bd02015-10-27 08:29:42 -07004101
eladalon413ee9a2017-08-22 04:02:52 -07004102 send_transport = rtc::MakeUnique<test::PacketTransport>(
4103 &task_queue_, sender_call_.get(), &observer,
4104 test::PacketTransport::kSender, payload_type_map_,
4105 FakeNetworkPipe::Config());
4106 receive_transport = rtc::MakeUnique<test::PacketTransport>(
4107 &task_queue_, nullptr, &observer, test::PacketTransport::kReceiver,
4108 payload_type_map_, FakeNetworkPipe::Config());
4109 send_transport->SetReceiver(receiver_call_->Receiver());
4110 receive_transport->SetReceiver(sender_call_->Receiver());
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004111
eladalon413ee9a2017-08-22 04:02:52 -07004112 CreateSendConfig(kNumSsrcs, 0, 0, send_transport.get());
4113
4114 if (use_rtx) {
4115 for (size_t i = 0; i < kNumSsrcs; ++i) {
4116 video_send_config_.rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
4117 }
4118 video_send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004119 }
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004120
eladalon413ee9a2017-08-22 04:02:52 -07004121 video_encoder_config_.video_stream_factory =
4122 new rtc::RefCountedObject<VideoStreamFactory>();
4123 // Use the same total bitrates when sending a single stream to avoid
4124 // lowering the bitrate estimate and requiring a subsequent rampup.
4125 one_stream = video_encoder_config_.Copy();
4126 // one_stream.streams.resize(1);
4127 one_stream.number_of_streams = 1;
4128 CreateMatchingReceiveConfigs(receive_transport.get());
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004129
eladalon413ee9a2017-08-22 04:02:52 -07004130 CreateVideoStreams();
4131 CreateFrameGeneratorCapturer(30, 1280, 720);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004132
eladalon413ee9a2017-08-22 04:02:52 -07004133 Start();
4134 });
4135
Peter Boström5811a392015-12-10 13:02:50 +01004136 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004137 << "Timed out waiting for all SSRCs to send packets.";
4138
4139 // Test stream resetting more than once to make sure that the state doesn't
4140 // get set once (this could be due to using std::map::insert for instance).
4141 for (size_t i = 0; i < 3; ++i) {
eladalon413ee9a2017-08-22 04:02:52 -07004142 task_queue_.SendTask([&]() {
4143 frame_generator_capturer_->Stop();
4144 sender_call_->DestroyVideoSendStream(video_send_stream_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004145
eladalon413ee9a2017-08-22 04:02:52 -07004146 // Re-create VideoSendStream with only one stream.
4147 video_send_stream_ = sender_call_->CreateVideoSendStream(
4148 video_send_config_.Copy(), one_stream.Copy());
4149 video_send_stream_->Start();
4150 if (provoke_rtcpsr_before_rtp) {
4151 // Rapid Resync Request forces sending RTCP Sender Report back.
4152 // Using this request speeds up this test because then there is no need
4153 // to wait for a second for periodic Sender Report.
4154 rtcp::RapidResyncRequest force_send_sr_back_request;
4155 rtc::Buffer packet = force_send_sr_back_request.Build();
4156 static_cast<webrtc::test::DirectTransport*>(receive_transport.get())
4157 ->SendRtcp(packet.data(), packet.size());
4158 }
4159 CreateFrameGeneratorCapturer(30, 1280, 720);
4160 frame_generator_capturer_->Start();
4161 });
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004162
4163 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01004164 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004165
4166 // Reconfigure back to use all streams.
eladalon413ee9a2017-08-22 04:02:52 -07004167 task_queue_.SendTask([this]() {
4168 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_.Copy());
4169 });
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004170 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01004171 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004172 << "Timed out waiting for all SSRCs to send packets.";
4173
4174 // Reconfigure down to one stream.
eladalon413ee9a2017-08-22 04:02:52 -07004175 task_queue_.SendTask([this, &one_stream]() {
4176 video_send_stream_->ReconfigureVideoEncoder(one_stream.Copy());
4177 });
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004178 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01004179 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004180
4181 // Reconfigure back to use all streams.
eladalon413ee9a2017-08-22 04:02:52 -07004182 task_queue_.SendTask([this]() {
4183 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_.Copy());
4184 });
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004185 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01004186 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004187 << "Timed out waiting for all SSRCs to send packets.";
4188 }
4189
eladalon413ee9a2017-08-22 04:02:52 -07004190 task_queue_.SendTask([this, &send_transport, &receive_transport]() {
4191 Stop();
4192 DestroyStreams();
4193 send_transport.reset();
4194 receive_transport.reset();
4195 DestroyCalls();
4196 });
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004197}
4198
philipel277a8b52017-03-16 05:19:49 -07004199TEST_F(EndToEndTest, RestartingSendStreamPreservesRtpState) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02004200 TestRtpStatePreservation(false, false);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004201}
4202
philipel277a8b52017-03-16 05:19:49 -07004203TEST_F(EndToEndTest, RestartingSendStreamPreservesRtpStatesWithRtx) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02004204 TestRtpStatePreservation(true, false);
4205}
4206
philipel277a8b52017-03-16 05:19:49 -07004207TEST_F(EndToEndTest, RestartingSendStreamKeepsRtpAndRtcpTimestampsSynced) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02004208 TestRtpStatePreservation(true, true);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00004209}
4210
brandtreb806792017-05-31 07:46:56 -07004211// This test is flaky on linux_memcheck. Disable on all linux bots until
4212// flakyness has been fixed.
4213// https://bugs.chromium.org/p/webrtc/issues/detail?id=7737
4214#if defined(WEBRTC_LINUX)
4215#define MAYBE_TestFlexfecRtpStatePreservation \
4216 DISABLED_TestFlexfecRtpStatePreservation
4217#else
4218#define MAYBE_TestFlexfecRtpStatePreservation TestFlexfecRtpStatePreservation
4219#endif
4220TEST_F(EndToEndTest, MAYBE_TestFlexfecRtpStatePreservation) {
brandtr48d21a22017-05-30 02:32:12 -07004221 class RtpSequenceObserver : public test::RtpRtcpObserver {
4222 public:
4223 RtpSequenceObserver()
4224 : test::RtpRtcpObserver(kDefaultTimeoutMs),
4225 num_flexfec_packets_sent_(0) {}
4226
4227 void ResetPacketCount() {
4228 rtc::CritScope lock(&crit_);
4229 num_flexfec_packets_sent_ = 0;
4230 }
4231
4232 private:
4233 Action OnSendRtp(const uint8_t* packet, size_t length) override {
4234 rtc::CritScope lock(&crit_);
4235
4236 RTPHeader header;
4237 EXPECT_TRUE(parser_->Parse(packet, length, &header));
4238 const uint16_t sequence_number = header.sequenceNumber;
4239 const uint32_t timestamp = header.timestamp;
4240 const uint32_t ssrc = header.ssrc;
4241
4242 if (ssrc == kVideoSendSsrcs[0] || ssrc == kSendRtxSsrcs[0]) {
4243 return SEND_PACKET;
4244 }
4245 EXPECT_EQ(kFlexfecSendSsrc, ssrc) << "Unknown SSRC sent.";
4246
4247 ++num_flexfec_packets_sent_;
4248
4249 // If this is the first packet, we have nothing to compare to.
4250 if (!last_observed_sequence_number_) {
4251 last_observed_sequence_number_.emplace(sequence_number);
4252 last_observed_timestamp_.emplace(timestamp);
4253
4254 return SEND_PACKET;
4255 }
4256
4257 // Verify continuity and monotonicity of RTP sequence numbers.
4258 EXPECT_EQ(static_cast<uint16_t>(*last_observed_sequence_number_ + 1),
4259 sequence_number);
4260 last_observed_sequence_number_.emplace(sequence_number);
4261
4262 // Timestamps should be non-decreasing...
4263 const bool timestamp_is_same_or_newer =
4264 timestamp == *last_observed_timestamp_ ||
4265 IsNewerTimestamp(timestamp, *last_observed_timestamp_);
4266 EXPECT_TRUE(timestamp_is_same_or_newer);
4267 // ...but reasonably close in time.
4268 const int k10SecondsInRtpTimestampBase = 10 * kVideoPayloadTypeFrequency;
4269 EXPECT_TRUE(IsNewerTimestamp(
4270 *last_observed_timestamp_ + k10SecondsInRtpTimestampBase, timestamp));
4271 last_observed_timestamp_.emplace(timestamp);
4272
4273 // Pass test when enough packets have been let through.
4274 if (num_flexfec_packets_sent_ >= 10) {
4275 observation_complete_.Set();
4276 }
4277
4278 return SEND_PACKET;
4279 }
4280
4281 rtc::Optional<uint16_t> last_observed_sequence_number_ GUARDED_BY(crit_);
4282 rtc::Optional<uint32_t> last_observed_timestamp_ GUARDED_BY(crit_);
4283 size_t num_flexfec_packets_sent_ GUARDED_BY(crit_);
4284 rtc::CriticalSection crit_;
4285 } observer;
4286
eladalon05b07bb2017-08-24 07:40:16 -07004287 static constexpr int kFrameMaxWidth = 320;
4288 static constexpr int kFrameMaxHeight = 180;
4289 static constexpr int kFrameRate = 15;
eladalon413ee9a2017-08-22 04:02:52 -07004290
brandtr48d21a22017-05-30 02:32:12 -07004291 Call::Config config(event_log_.get());
brandtr48d21a22017-05-30 02:32:12 -07004292
eladalon413ee9a2017-08-22 04:02:52 -07004293 std::unique_ptr<test::PacketTransport> send_transport;
4294 std::unique_ptr<test::PacketTransport> receive_transport;
4295 std::unique_ptr<VideoEncoder> encoder;
brandtr48d21a22017-05-30 02:32:12 -07004296
eladalon413ee9a2017-08-22 04:02:52 -07004297 task_queue_.SendTask([&]() {
4298 CreateCalls(config, config);
brandtr48d21a22017-05-30 02:32:12 -07004299
eladalon413ee9a2017-08-22 04:02:52 -07004300 FakeNetworkPipe::Config lossy_delayed_link;
4301 lossy_delayed_link.loss_percent = 2;
4302 lossy_delayed_link.queue_delay_ms = 50;
brandtr48d21a22017-05-30 02:32:12 -07004303
eladalon413ee9a2017-08-22 04:02:52 -07004304 send_transport = rtc::MakeUnique<test::PacketTransport>(
4305 &task_queue_, sender_call_.get(), &observer,
4306 test::PacketTransport::kSender, payload_type_map_, lossy_delayed_link);
4307 send_transport->SetReceiver(receiver_call_->Receiver());
brandtr48d21a22017-05-30 02:32:12 -07004308
eladalon413ee9a2017-08-22 04:02:52 -07004309 FakeNetworkPipe::Config flawless_link;
4310 receive_transport = rtc::MakeUnique<test::PacketTransport>(
4311 &task_queue_, nullptr, &observer, test::PacketTransport::kReceiver,
4312 payload_type_map_, flawless_link);
4313 receive_transport->SetReceiver(sender_call_->Receiver());
brandtr48d21a22017-05-30 02:32:12 -07004314
eladalon413ee9a2017-08-22 04:02:52 -07004315 // For reduced flakyness, we use a real VP8 encoder together with NACK
4316 // and RTX.
4317 const int kNumVideoStreams = 1;
4318 const int kNumFlexfecStreams = 1;
4319 CreateSendConfig(kNumVideoStreams, 0, kNumFlexfecStreams,
4320 send_transport.get());
4321 encoder = rtc::WrapUnique(VP8Encoder::Create());
4322 video_send_config_.encoder_settings.encoder = encoder.get();
4323 video_send_config_.encoder_settings.payload_name = "VP8";
4324 video_send_config_.encoder_settings.payload_type = kVideoSendPayloadType;
4325 video_send_config_.rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
4326 video_send_config_.rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
4327 video_send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
brandtr48d21a22017-05-30 02:32:12 -07004328
eladalon413ee9a2017-08-22 04:02:52 -07004329 CreateMatchingReceiveConfigs(receive_transport.get());
4330 video_receive_configs_[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
4331 video_receive_configs_[0].rtp.rtx_ssrc = kSendRtxSsrcs[0];
nisse26e3abb2017-08-25 04:44:25 -07004332 video_receive_configs_[0]
4333 .rtp.rtx_associated_payload_types[kSendRtxPayloadType] =
4334 kVideoSendPayloadType;
brandtr48d21a22017-05-30 02:32:12 -07004335
eladalon413ee9a2017-08-22 04:02:52 -07004336 // The matching FlexFEC receive config is not created by
4337 // CreateMatchingReceiveConfigs since this is not a test::BaseTest.
4338 // Set up the receive config manually instead.
4339 FlexfecReceiveStream::Config flexfec_receive_config(
4340 receive_transport.get());
4341 flexfec_receive_config.payload_type =
4342 video_send_config_.rtp.flexfec.payload_type;
4343 flexfec_receive_config.remote_ssrc = video_send_config_.rtp.flexfec.ssrc;
4344 flexfec_receive_config.protected_media_ssrcs =
4345 video_send_config_.rtp.flexfec.protected_media_ssrcs;
4346 flexfec_receive_config.local_ssrc = kReceiverLocalVideoSsrc;
4347 flexfec_receive_config.transport_cc = true;
4348 flexfec_receive_config.rtp_header_extensions.emplace_back(
4349 RtpExtension::kTransportSequenceNumberUri,
4350 test::kTransportSequenceNumberExtensionId);
4351 flexfec_receive_configs_.push_back(flexfec_receive_config);
4352
4353 CreateFlexfecStreams();
4354 CreateVideoStreams();
4355
4356 // RTCP might be disabled if the network is "down".
4357 sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
4358 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
4359
4360 CreateFrameGeneratorCapturer(kFrameRate, kFrameMaxWidth, kFrameMaxHeight);
4361
4362 Start();
4363 });
brandtr48d21a22017-05-30 02:32:12 -07004364
4365 // Initial test.
brandtr48d21a22017-05-30 02:32:12 -07004366 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for packets.";
4367
eladalon413ee9a2017-08-22 04:02:52 -07004368 task_queue_.SendTask([this, &observer]() {
4369 // Ensure monotonicity when the VideoSendStream is restarted.
4370 Stop();
4371 observer.ResetPacketCount();
4372 Start();
4373 });
4374
brandtr48d21a22017-05-30 02:32:12 -07004375 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for packets.";
4376
eladalon05b07bb2017-08-24 07:40:16 -07004377 task_queue_.SendTask([this, &observer]() {
eladalon413ee9a2017-08-22 04:02:52 -07004378 // Ensure monotonicity when the VideoSendStream is recreated.
4379 frame_generator_capturer_->Stop();
4380 sender_call_->DestroyVideoSendStream(video_send_stream_);
4381 observer.ResetPacketCount();
4382 video_send_stream_ = sender_call_->CreateVideoSendStream(
4383 video_send_config_.Copy(), video_encoder_config_.Copy());
4384 video_send_stream_->Start();
4385 CreateFrameGeneratorCapturer(kFrameRate, kFrameMaxWidth, kFrameMaxHeight);
4386 frame_generator_capturer_->Start();
4387 });
4388
brandtr48d21a22017-05-30 02:32:12 -07004389 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for packets.";
4390
4391 // Cleanup.
eladalon413ee9a2017-08-22 04:02:52 -07004392 task_queue_.SendTask([this, &send_transport, &receive_transport]() {
4393 Stop();
4394 DestroyStreams();
4395 send_transport.reset();
4396 receive_transport.reset();
4397 DestroyCalls();
4398 });
brandtr48d21a22017-05-30 02:32:12 -07004399}
4400
philipel277a8b52017-03-16 05:19:49 -07004401TEST_F(EndToEndTest, RespectsNetworkState) {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004402 // TODO(pbos): Remove accepted downtime packets etc. when signaling network
4403 // down blocks until no more packets will be sent.
4404
4405 // Pacer will send from its packet list and then send required padding before
4406 // checking paused_ again. This should be enough for one round of pacing,
4407 // otherwise increase.
4408 static const int kNumAcceptedDowntimeRtp = 5;
4409 // A single RTCP may be in the pipeline.
4410 static const int kNumAcceptedDowntimeRtcp = 1;
4411 class NetworkStateTest : public test::EndToEndTest, public test::FakeEncoder {
4412 public:
eladalon413ee9a2017-08-22 04:02:52 -07004413 explicit NetworkStateTest(
4414 test::SingleThreadedTaskQueueForTesting* task_queue)
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004415 : EndToEndTest(kDefaultTimeoutMs),
4416 FakeEncoder(Clock::GetRealTimeClock()),
eladalon413ee9a2017-08-22 04:02:52 -07004417 task_queue_(task_queue),
Peter Boström5811a392015-12-10 13:02:50 +01004418 encoded_frames_(false, false),
4419 packet_event_(false, false),
sprang867fb522015-08-03 04:38:41 -07004420 sender_call_(nullptr),
4421 receiver_call_(nullptr),
Jelena Marusiccd670222015-07-16 09:30:09 +02004422 sender_state_(kNetworkUp),
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004423 sender_rtp_(0),
stefan9e117c5e12017-08-16 08:16:25 -07004424 sender_padding_(0),
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004425 sender_rtcp_(0),
4426 receiver_rtcp_(0),
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004427 down_frames_(0) {}
4428
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00004429 Action OnSendRtp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02004430 rtc::CritScope lock(&test_crit_);
stefan9e117c5e12017-08-16 08:16:25 -07004431 RTPHeader header;
4432 EXPECT_TRUE(parser_->Parse(packet, length, &header));
4433 if (length == header.headerLength + header.paddingLength)
4434 ++sender_padding_;
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004435 ++sender_rtp_;
Peter Boström5811a392015-12-10 13:02:50 +01004436 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004437 return SEND_PACKET;
4438 }
4439
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00004440 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02004441 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004442 ++sender_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01004443 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004444 return SEND_PACKET;
4445 }
4446
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00004447 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004448 ADD_FAILURE() << "Unexpected receiver RTP, should not be sending.";
4449 return SEND_PACKET;
4450 }
4451
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00004452 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02004453 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004454 ++receiver_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01004455 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004456 return SEND_PACKET;
4457 }
4458
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00004459 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004460 sender_call_ = sender_call;
4461 receiver_call_ = receiver_call;
4462 }
4463
stefanff483612015-12-21 03:14:00 -08004464 void ModifyVideoConfigs(
4465 VideoSendStream::Config* send_config,
4466 std::vector<VideoReceiveStream::Config>* receive_configs,
4467 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004468 send_config->encoder_settings.encoder = this;
4469 }
4470
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00004471 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01004472 EXPECT_TRUE(encoded_frames_.Wait(kDefaultTimeoutMs))
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004473 << "No frames received by the encoder.";
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004474
eladalon413ee9a2017-08-22 04:02:52 -07004475 task_queue_->SendTask([this]() {
4476 // Wait for packets from both sender/receiver.
4477 WaitForPacketsOrSilence(false, false);
skvlad7a43d252016-03-22 15:32:27 -07004478
eladalon413ee9a2017-08-22 04:02:52 -07004479 // Sender-side network down for audio; there should be no effect on
4480 // video
4481 sender_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkDown);
4482 WaitForPacketsOrSilence(false, false);
skvlad7a43d252016-03-22 15:32:27 -07004483
eladalon413ee9a2017-08-22 04:02:52 -07004484 // Receiver-side network down for audio; no change expected
4485 receiver_call_->SignalChannelNetworkState(MediaType::AUDIO,
4486 kNetworkDown);
4487 WaitForPacketsOrSilence(false, false);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004488
eladalon413ee9a2017-08-22 04:02:52 -07004489 // Sender-side network down.
4490 sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkDown);
4491 {
4492 rtc::CritScope lock(&test_crit_);
4493 // After network goes down we shouldn't be encoding more frames.
4494 sender_state_ = kNetworkDown;
4495 }
4496 // Wait for receiver-packets and no sender packets.
4497 WaitForPacketsOrSilence(true, false);
skvlad7a43d252016-03-22 15:32:27 -07004498
eladalon413ee9a2017-08-22 04:02:52 -07004499 // Receiver-side network down.
4500 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO,
4501 kNetworkDown);
4502 WaitForPacketsOrSilence(true, true);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004503
eladalon413ee9a2017-08-22 04:02:52 -07004504 // Network up for audio for both sides; video is still not expected to
4505 // start
4506 sender_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkUp);
4507 receiver_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkUp);
4508 WaitForPacketsOrSilence(true, true);
skvlad7a43d252016-03-22 15:32:27 -07004509
eladalon413ee9a2017-08-22 04:02:52 -07004510 // Network back up again for both.
4511 {
4512 rtc::CritScope lock(&test_crit_);
4513 // It's OK to encode frames again, as we're about to bring up the
4514 // network.
4515 sender_state_ = kNetworkUp;
4516 }
4517 sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
4518 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
4519 WaitForPacketsOrSilence(false, false);
4520
4521 // TODO(skvlad): add tests to verify that the audio streams are stopped
4522 // when the network goes down for audio once the workaround in
4523 // paced_sender.cc is removed.
4524 });
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004525 }
4526
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07004527 int32_t Encode(const VideoFrame& input_image,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00004528 const CodecSpecificInfo* codec_specific_info,
pbos22993e12015-10-19 02:39:06 -07004529 const std::vector<FrameType>* frame_types) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004530 {
Peter Boströmf2f82832015-05-01 13:00:41 +02004531 rtc::CritScope lock(&test_crit_);
Jelena Marusiccd670222015-07-16 09:30:09 +02004532 if (sender_state_ == kNetworkDown) {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004533 ++down_frames_;
4534 EXPECT_LE(down_frames_, 1)
4535 << "Encoding more than one frame while network is down.";
4536 if (down_frames_ > 1)
Peter Boström5811a392015-12-10 13:02:50 +01004537 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004538 } else {
Peter Boström5811a392015-12-10 13:02:50 +01004539 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004540 }
4541 }
4542 return test::FakeEncoder::Encode(
4543 input_image, codec_specific_info, frame_types);
4544 }
4545
4546 private:
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004547 void WaitForPacketsOrSilence(bool sender_down, bool receiver_down) {
4548 int64_t initial_time_ms = clock_->TimeInMilliseconds();
4549 int initial_sender_rtp;
4550 int initial_sender_rtcp;
4551 int initial_receiver_rtcp;
4552 {
Peter Boströmf2f82832015-05-01 13:00:41 +02004553 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004554 initial_sender_rtp = sender_rtp_;
4555 initial_sender_rtcp = sender_rtcp_;
4556 initial_receiver_rtcp = receiver_rtcp_;
4557 }
4558 bool sender_done = false;
4559 bool receiver_done = false;
mflodmand1590b22015-12-09 07:07:59 -08004560 while (!sender_done || !receiver_done) {
Peter Boström5811a392015-12-10 13:02:50 +01004561 packet_event_.Wait(kSilenceTimeoutMs);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004562 int64_t time_now_ms = clock_->TimeInMilliseconds();
Peter Boströmf2f82832015-05-01 13:00:41 +02004563 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004564 if (sender_down) {
stefan9e117c5e12017-08-16 08:16:25 -07004565 ASSERT_LE(sender_rtp_ - initial_sender_rtp - sender_padding_,
4566 kNumAcceptedDowntimeRtp)
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004567 << "RTP sent during sender-side downtime.";
4568 ASSERT_LE(sender_rtcp_ - initial_sender_rtcp,
4569 kNumAcceptedDowntimeRtcp)
4570 << "RTCP sent during sender-side downtime.";
4571 if (time_now_ms - initial_time_ms >=
4572 static_cast<int64_t>(kSilenceTimeoutMs)) {
4573 sender_done = true;
4574 }
4575 } else {
skvlad7a43d252016-03-22 15:32:27 -07004576 if (sender_rtp_ > initial_sender_rtp + kNumAcceptedDowntimeRtp)
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004577 sender_done = true;
4578 }
4579 if (receiver_down) {
4580 ASSERT_LE(receiver_rtcp_ - initial_receiver_rtcp,
4581 kNumAcceptedDowntimeRtcp)
4582 << "RTCP sent during receiver-side downtime.";
4583 if (time_now_ms - initial_time_ms >=
4584 static_cast<int64_t>(kSilenceTimeoutMs)) {
4585 receiver_done = true;
4586 }
4587 } else {
skvlad7a43d252016-03-22 15:32:27 -07004588 if (receiver_rtcp_ > initial_receiver_rtcp + kNumAcceptedDowntimeRtcp)
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004589 receiver_done = true;
4590 }
4591 }
4592 }
4593
eladalon413ee9a2017-08-22 04:02:52 -07004594 test::SingleThreadedTaskQueueForTesting* const task_queue_;
Peter Boströmf2f82832015-05-01 13:00:41 +02004595 rtc::CriticalSection test_crit_;
Peter Boström5811a392015-12-10 13:02:50 +01004596 rtc::Event encoded_frames_;
4597 rtc::Event packet_event_;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004598 Call* sender_call_;
4599 Call* receiver_call_;
Jelena Marusiccd670222015-07-16 09:30:09 +02004600 NetworkState sender_state_ GUARDED_BY(test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004601 int sender_rtp_ GUARDED_BY(test_crit_);
stefan9e117c5e12017-08-16 08:16:25 -07004602 int sender_padding_ GUARDED_BY(test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00004603 int sender_rtcp_ GUARDED_BY(test_crit_);
4604 int receiver_rtcp_ GUARDED_BY(test_crit_);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004605 int down_frames_ GUARDED_BY(test_crit_);
eladalon413ee9a2017-08-22 04:02:52 -07004606 } test(&task_queue_);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004607
stefane74eef12016-01-08 06:47:13 -08004608 RunBaseTest(&test);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004609}
4610
philipel277a8b52017-03-16 05:19:49 -07004611TEST_F(EndToEndTest, CallReportsRttForSender) {
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00004612 static const int kSendDelayMs = 30;
4613 static const int kReceiveDelayMs = 70;
solenberg4fbae2b2015-08-28 04:07:10 -07004614
eladalon413ee9a2017-08-22 04:02:52 -07004615 std::unique_ptr<test::DirectTransport> sender_transport;
4616 std::unique_ptr<test::DirectTransport> receiver_transport;
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00004617
eladalon413ee9a2017-08-22 04:02:52 -07004618 task_queue_.SendTask([this, &sender_transport, &receiver_transport]() {
4619 FakeNetworkPipe::Config config;
4620 config.queue_delay_ms = kSendDelayMs;
4621 CreateCalls(Call::Config(event_log_.get()), Call::Config(event_log_.get()));
4622 sender_transport = rtc::MakeUnique<test::DirectTransport>(
4623 &task_queue_, config, sender_call_.get(), payload_type_map_);
4624 config.queue_delay_ms = kReceiveDelayMs;
4625 receiver_transport = rtc::MakeUnique<test::DirectTransport>(
4626 &task_queue_, config, receiver_call_.get(), payload_type_map_);
4627 sender_transport->SetReceiver(receiver_call_->Receiver());
4628 receiver_transport->SetReceiver(sender_call_->Receiver());
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00004629
eladalon413ee9a2017-08-22 04:02:52 -07004630 CreateSendConfig(1, 0, 0, sender_transport.get());
4631 CreateMatchingReceiveConfigs(receiver_transport.get());
4632
4633 CreateVideoStreams();
4634 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
4635 kDefaultHeight);
4636 Start();
4637 });
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00004638
4639 int64_t start_time_ms = clock_->TimeInMilliseconds();
4640 while (true) {
4641 Call::Stats stats = sender_call_->GetStats();
4642 ASSERT_GE(start_time_ms + kDefaultTimeoutMs,
4643 clock_->TimeInMilliseconds())
4644 << "No RTT stats before timeout!";
4645 if (stats.rtt_ms != -1) {
Danil Chapovalov10e8f8e2016-09-07 15:05:29 +02004646 // To avoid failures caused by rounding or minor ntp clock adjustments,
4647 // relax expectation by 1ms.
4648 constexpr int kAllowedErrorMs = 1;
4649 EXPECT_GE(stats.rtt_ms, kSendDelayMs + kReceiveDelayMs - kAllowedErrorMs);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00004650 break;
4651 }
4652 SleepMs(10);
4653 }
4654
eladalon413ee9a2017-08-22 04:02:52 -07004655 task_queue_.SendTask([this, &sender_transport, &receiver_transport]() {
4656 Stop();
4657 DestroyStreams();
4658 sender_transport.reset();
4659 receiver_transport.reset();
4660 DestroyCalls();
4661 });
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00004662}
4663
skvlad7a43d252016-03-22 15:32:27 -07004664void EndToEndTest::VerifyNewVideoSendStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -08004665 MediaType network_to_bring_up,
skvlad7a43d252016-03-22 15:32:27 -07004666 VideoEncoder* encoder,
4667 Transport* transport) {
eladalon413ee9a2017-08-22 04:02:52 -07004668 task_queue_.SendTask([this, network_to_bring_up, encoder, transport]() {
4669 CreateSenderCall(Call::Config(event_log_.get()));
4670 sender_call_->SignalChannelNetworkState(network_to_bring_up, kNetworkUp);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004671
eladalon413ee9a2017-08-22 04:02:52 -07004672 CreateSendConfig(1, 0, 0, transport);
4673 video_send_config_.encoder_settings.encoder = encoder;
4674 CreateVideoStreams();
4675 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
4676 kDefaultHeight);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004677
eladalon413ee9a2017-08-22 04:02:52 -07004678 Start();
4679 });
4680
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004681 SleepMs(kSilenceTimeoutMs);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004682
eladalon413ee9a2017-08-22 04:02:52 -07004683 task_queue_.SendTask([this]() {
4684 Stop();
4685 DestroyStreams();
4686 DestroyCalls();
4687 });
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004688}
4689
skvlad7a43d252016-03-22 15:32:27 -07004690void EndToEndTest::VerifyNewVideoReceiveStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -08004691 MediaType network_to_bring_up,
skvlad7a43d252016-03-22 15:32:27 -07004692 Transport* transport) {
eladalon413ee9a2017-08-22 04:02:52 -07004693 std::unique_ptr<test::DirectTransport> sender_transport;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004694
eladalon413ee9a2017-08-22 04:02:52 -07004695 task_queue_.SendTask([this, &sender_transport, network_to_bring_up,
4696 transport]() {
4697 Call::Config config(event_log_.get());
4698 CreateCalls(config, config);
4699 receiver_call_->SignalChannelNetworkState(network_to_bring_up, kNetworkUp);
4700 sender_transport = rtc::MakeUnique<test::DirectTransport>(
4701 &task_queue_, sender_call_.get(), payload_type_map_);
4702 sender_transport->SetReceiver(receiver_call_->Receiver());
4703 CreateSendConfig(1, 0, 0, sender_transport.get());
4704 CreateMatchingReceiveConfigs(transport);
4705 CreateVideoStreams();
4706 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
4707 kDefaultHeight);
4708 Start();
4709 });
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004710
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004711 SleepMs(kSilenceTimeoutMs);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004712
eladalon413ee9a2017-08-22 04:02:52 -07004713 task_queue_.SendTask([this, &sender_transport]() {
4714 Stop();
4715 DestroyStreams();
4716 sender_transport.reset();
4717 DestroyCalls();
4718 });
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00004719}
pbos@webrtc.org09cc6862014-11-04 13:48:15 +00004720
philipel277a8b52017-03-16 05:19:49 -07004721TEST_F(EndToEndTest, NewVideoSendStreamsRespectVideoNetworkDown) {
skvlad7a43d252016-03-22 15:32:27 -07004722 class UnusedEncoder : public test::FakeEncoder {
4723 public:
4724 UnusedEncoder() : FakeEncoder(Clock::GetRealTimeClock()) {}
perkjfea93092016-05-14 00:58:48 -07004725
4726 int32_t InitEncode(const VideoCodec* config,
4727 int32_t number_of_cores,
4728 size_t max_payload_size) override {
4729 EXPECT_GT(config->startBitrate, 0u);
4730 return 0;
4731 }
skvlad7a43d252016-03-22 15:32:27 -07004732 int32_t Encode(const VideoFrame& input_image,
4733 const CodecSpecificInfo* codec_specific_info,
4734 const std::vector<FrameType>* frame_types) override {
4735 ADD_FAILURE() << "Unexpected frame encode.";
4736 return test::FakeEncoder::Encode(input_image, codec_specific_info,
4737 frame_types);
4738 }
4739 };
4740
4741 UnusedEncoder unused_encoder;
4742 UnusedTransport unused_transport;
4743 VerifyNewVideoSendStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -08004744 MediaType::AUDIO, &unused_encoder, &unused_transport);
skvlad7a43d252016-03-22 15:32:27 -07004745}
4746
philipel277a8b52017-03-16 05:19:49 -07004747TEST_F(EndToEndTest, NewVideoSendStreamsIgnoreAudioNetworkDown) {
skvlad7a43d252016-03-22 15:32:27 -07004748 class RequiredEncoder : public test::FakeEncoder {
4749 public:
4750 RequiredEncoder()
4751 : FakeEncoder(Clock::GetRealTimeClock()), encoded_frame_(false) {}
4752 ~RequiredEncoder() {
4753 if (!encoded_frame_) {
4754 ADD_FAILURE() << "Didn't encode an expected frame";
4755 }
4756 }
4757 int32_t Encode(const VideoFrame& input_image,
4758 const CodecSpecificInfo* codec_specific_info,
4759 const std::vector<FrameType>* frame_types) override {
4760 encoded_frame_ = true;
4761 return test::FakeEncoder::Encode(input_image, codec_specific_info,
4762 frame_types);
4763 }
4764
4765 private:
4766 bool encoded_frame_;
4767 };
4768
4769 RequiredTransport required_transport(true /*rtp*/, false /*rtcp*/);
4770 RequiredEncoder required_encoder;
4771 VerifyNewVideoSendStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -08004772 MediaType::VIDEO, &required_encoder, &required_transport);
skvlad7a43d252016-03-22 15:32:27 -07004773}
4774
philipel277a8b52017-03-16 05:19:49 -07004775TEST_F(EndToEndTest, NewVideoReceiveStreamsRespectVideoNetworkDown) {
skvlad7a43d252016-03-22 15:32:27 -07004776 UnusedTransport transport;
Sergey Ulanove2b15012016-11-22 16:08:30 -08004777 VerifyNewVideoReceiveStreamsRespectNetworkState(MediaType::AUDIO, &transport);
skvlad7a43d252016-03-22 15:32:27 -07004778}
4779
philipel277a8b52017-03-16 05:19:49 -07004780TEST_F(EndToEndTest, NewVideoReceiveStreamsIgnoreAudioNetworkDown) {
skvlad7a43d252016-03-22 15:32:27 -07004781 RequiredTransport transport(false /*rtp*/, true /*rtcp*/);
Sergey Ulanove2b15012016-11-22 16:08:30 -08004782 VerifyNewVideoReceiveStreamsRespectNetworkState(MediaType::VIDEO, &transport);
skvlad7a43d252016-03-22 15:32:27 -07004783}
4784
Peter Boströmd7da1202015-06-05 14:09:38 +02004785void VerifyEmptyNackConfig(const NackConfig& config) {
4786 EXPECT_EQ(0, config.rtp_history_ms)
4787 << "Enabling NACK requires rtcp-fb: nack negotiation.";
4788}
4789
brandtrb5f2c3f2016-10-04 23:28:39 -07004790void VerifyEmptyUlpfecConfig(const UlpfecConfig& config) {
Peter Boströmd7da1202015-06-05 14:09:38 +02004791 EXPECT_EQ(-1, config.ulpfec_payload_type)
brandtr535830e2016-10-31 03:45:58 -07004792 << "Enabling ULPFEC requires rtpmap: ulpfec negotiation.";
Peter Boströmd7da1202015-06-05 14:09:38 +02004793 EXPECT_EQ(-1, config.red_payload_type)
brandtr535830e2016-10-31 03:45:58 -07004794 << "Enabling ULPFEC requires rtpmap: red negotiation.";
Peter Boströmd7da1202015-06-05 14:09:38 +02004795 EXPECT_EQ(-1, config.red_rtx_payload_type)
brandtr535830e2016-10-31 03:45:58 -07004796 << "Enabling RTX in ULPFEC requires rtpmap: rtx negotiation.";
Peter Boströmd7da1202015-06-05 14:09:38 +02004797}
4798
brandtr3d200bd2017-01-16 06:59:19 -08004799void VerifyEmptyFlexfecConfig(
4800 const VideoSendStream::Config::Rtp::Flexfec& config) {
4801 EXPECT_EQ(-1, config.payload_type)
brandtr1e3dfbf2016-11-16 22:45:19 -08004802 << "Enabling FlexFEC requires rtpmap: flexfec negotiation.";
brandtr3d200bd2017-01-16 06:59:19 -08004803 EXPECT_EQ(0U, config.ssrc)
brandtr1cfbd602016-12-08 04:17:53 -08004804 << "Enabling FlexFEC requires ssrc-group: FEC-FR negotiation.";
brandtr1e3dfbf2016-11-16 22:45:19 -08004805 EXPECT_TRUE(config.protected_media_ssrcs.empty())
4806 << "Enabling FlexFEC requires ssrc-group: FEC-FR negotiation.";
4807}
4808
philipel277a8b52017-03-16 05:19:49 -07004809TEST_F(EndToEndTest, VerifyDefaultSendConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07004810 VideoSendStream::Config default_send_config(nullptr);
Peter Boströmd7da1202015-06-05 14:09:38 +02004811 EXPECT_EQ(0, default_send_config.rtp.nack.rtp_history_ms)
4812 << "Enabling NACK require rtcp-fb: nack negotiation.";
4813 EXPECT_TRUE(default_send_config.rtp.rtx.ssrcs.empty())
4814 << "Enabling RTX requires rtpmap: rtx negotiation.";
4815 EXPECT_TRUE(default_send_config.rtp.extensions.empty())
4816 << "Enabling RTP extensions require negotiation.";
4817
4818 VerifyEmptyNackConfig(default_send_config.rtp.nack);
brandtrb5f2c3f2016-10-04 23:28:39 -07004819 VerifyEmptyUlpfecConfig(default_send_config.rtp.ulpfec);
brandtr1e3dfbf2016-11-16 22:45:19 -08004820 VerifyEmptyFlexfecConfig(default_send_config.rtp.flexfec);
Peter Boströmd7da1202015-06-05 14:09:38 +02004821}
4822
philipel277a8b52017-03-16 05:19:49 -07004823TEST_F(EndToEndTest, VerifyDefaultVideoReceiveConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07004824 VideoReceiveStream::Config default_receive_config(nullptr);
pbosda903ea2015-10-02 02:36:56 -07004825 EXPECT_EQ(RtcpMode::kCompound, default_receive_config.rtp.rtcp_mode)
Peter Boströmd7da1202015-06-05 14:09:38 +02004826 << "Reduced-size RTCP require rtcp-rsize to be negotiated.";
4827 EXPECT_FALSE(default_receive_config.rtp.remb)
4828 << "REMB require rtcp-fb: goog-remb to be negotiated.";
4829 EXPECT_FALSE(
4830 default_receive_config.rtp.rtcp_xr.receiver_reference_time_report)
4831 << "RTCP XR settings require rtcp-xr to be negotiated.";
brandtr14742122017-01-27 04:53:07 -08004832 EXPECT_EQ(0U, default_receive_config.rtp.rtx_ssrc)
4833 << "Enabling RTX requires ssrc-group: FID negotiation";
nisse26e3abb2017-08-25 04:44:25 -07004834 EXPECT_TRUE(default_receive_config.rtp.rtx_associated_payload_types.empty())
Peter Boströmd7da1202015-06-05 14:09:38 +02004835 << "Enabling RTX requires rtpmap: rtx negotiation.";
4836 EXPECT_TRUE(default_receive_config.rtp.extensions.empty())
4837 << "Enabling RTP extensions require negotiation.";
4838
4839 VerifyEmptyNackConfig(default_receive_config.rtp.nack);
brandtrb5f2c3f2016-10-04 23:28:39 -07004840 VerifyEmptyUlpfecConfig(default_receive_config.rtp.ulpfec);
Peter Boströmd7da1202015-06-05 14:09:38 +02004841}
4842
philipel277a8b52017-03-16 05:19:49 -07004843TEST_F(EndToEndTest, VerifyDefaultFlexfecReceiveConfigParameters) {
brandtr8313a6f2017-01-13 07:41:19 -08004844 test::NullTransport rtcp_send_transport;
4845 FlexfecReceiveStream::Config default_receive_config(&rtcp_send_transport);
brandtr1cfbd602016-12-08 04:17:53 -08004846 EXPECT_EQ(-1, default_receive_config.payload_type)
4847 << "Enabling FlexFEC requires rtpmap: flexfec negotiation.";
4848 EXPECT_EQ(0U, default_receive_config.remote_ssrc)
4849 << "Enabling FlexFEC requires ssrc-group: FEC-FR negotiation.";
4850 EXPECT_TRUE(default_receive_config.protected_media_ssrcs.empty())
4851 << "Enabling FlexFEC requires ssrc-group: FEC-FR negotiation.";
brandtr1e3dfbf2016-11-16 22:45:19 -08004852}
4853
philipel277a8b52017-03-16 05:19:49 -07004854TEST_F(EndToEndTest, TransportSeqNumOnAudioAndVideo) {
danilchap4336d732017-03-03 06:21:54 -08004855 static constexpr int kExtensionId = 8;
4856 static constexpr size_t kMinPacketsToWaitFor = 50;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004857 class TransportSequenceNumberTest : public test::EndToEndTest {
4858 public:
4859 TransportSequenceNumberTest()
4860 : EndToEndTest(kDefaultTimeoutMs),
4861 video_observed_(false),
4862 audio_observed_(false) {
4863 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
4864 kExtensionId);
4865 }
4866
4867 size_t GetNumVideoStreams() const override { return 1; }
4868 size_t GetNumAudioStreams() const override { return 1; }
4869
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004870 void ModifyAudioConfigs(
4871 AudioSendStream::Config* send_config,
4872 std::vector<AudioReceiveStream::Config>* receive_configs) override {
4873 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07004874 send_config->rtp.extensions.push_back(RtpExtension(
4875 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004876 (*receive_configs)[0].rtp.extensions.clear();
4877 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
4878 }
4879
4880 Action OnSendRtp(const uint8_t* packet, size_t length) override {
4881 RTPHeader header;
4882 EXPECT_TRUE(parser_->Parse(packet, length, &header));
4883 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
4884 // Unwrap packet id and verify uniqueness.
4885 int64_t packet_id =
4886 unwrapper_.Unwrap(header.extension.transportSequenceNumber);
4887 EXPECT_TRUE(received_packet_ids_.insert(packet_id).second);
4888
4889 if (header.ssrc == kVideoSendSsrcs[0])
4890 video_observed_ = true;
4891 if (header.ssrc == kAudioSendSsrc)
4892 audio_observed_ = true;
4893 if (audio_observed_ && video_observed_ &&
danilchap4336d732017-03-03 06:21:54 -08004894 received_packet_ids_.size() >= kMinPacketsToWaitFor) {
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004895 size_t packet_id_range =
4896 *received_packet_ids_.rbegin() - *received_packet_ids_.begin() + 1;
4897 EXPECT_EQ(received_packet_ids_.size(), packet_id_range);
4898 observation_complete_.Set();
4899 }
4900 return SEND_PACKET;
4901 }
4902
4903 void PerformTest() override {
4904 EXPECT_TRUE(Wait()) << "Timed out while waiting for audio and video "
4905 "packets with transport sequence number.";
4906 }
4907
danilchap4336d732017-03-03 06:21:54 -08004908 void ExpectSuccessful() {
4909 EXPECT_TRUE(video_observed_);
4910 EXPECT_TRUE(audio_observed_);
4911 EXPECT_GE(received_packet_ids_.size(), kMinPacketsToWaitFor);
4912 }
4913
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004914 private:
4915 bool video_observed_;
4916 bool audio_observed_;
4917 SequenceNumberUnwrapper unwrapper_;
4918 std::set<int64_t> received_packet_ids_;
4919 } test;
4920
stefane74eef12016-01-08 06:47:13 -08004921 RunBaseTest(&test);
danilchap4336d732017-03-03 06:21:54 -08004922 // Double check conditions for successful test to produce better error
4923 // message when the test fail.
4924 test.ExpectSuccessful();
Stefan Holmer9fea80f2016-01-07 17:43:18 +01004925}
palmkviste75f2042016-09-28 06:19:48 -07004926
4927class EndToEndLogTest : public EndToEndTest {
4928 void SetUp() { paths_.clear(); }
4929 void TearDown() {
4930 for (const auto& path : paths_) {
4931 rtc::RemoveFile(path);
4932 }
4933 }
4934
4935 public:
4936 int AddFile() {
4937 paths_.push_back(test::TempFilename(test::OutputPath(), "test_file"));
4938 return static_cast<int>(paths_.size()) - 1;
4939 }
4940
4941 rtc::PlatformFile OpenFile(int idx) {
4942 return rtc::OpenPlatformFile(paths_[idx]);
4943 }
4944
4945 void LogSend(bool open) {
4946 if (open) {
4947 video_send_stream_->EnableEncodedFrameRecording(
4948 std::vector<rtc::PlatformFile>(1, OpenFile(AddFile())), 0);
4949 } else {
4950 video_send_stream_->DisableEncodedFrameRecording();
4951 }
4952 }
4953 void LogReceive(bool open) {
4954 if (open) {
4955 video_receive_streams_[0]->EnableEncodedFrameRecording(
4956 OpenFile(AddFile()), 0);
4957 } else {
4958 video_receive_streams_[0]->DisableEncodedFrameRecording();
4959 }
4960 }
4961
4962 std::vector<std::string> paths_;
4963};
4964
philipel277a8b52017-03-16 05:19:49 -07004965TEST_F(EndToEndLogTest, LogsEncodedFramesWhenRequested) {
palmkviste75f2042016-09-28 06:19:48 -07004966 static const int kNumFramesToRecord = 10;
4967 class LogEncodingObserver : public test::EndToEndTest,
4968 public EncodedFrameObserver {
4969 public:
4970 explicit LogEncodingObserver(EndToEndLogTest* fixture)
4971 : EndToEndTest(kDefaultTimeoutMs),
4972 fixture_(fixture),
4973 recorded_frames_(0) {}
4974
4975 void PerformTest() override {
4976 fixture_->LogSend(true);
4977 fixture_->LogReceive(true);
4978 ASSERT_TRUE(Wait()) << "Timed out while waiting for frame logging.";
4979 }
4980
4981 void ModifyVideoConfigs(
4982 VideoSendStream::Config* send_config,
4983 std::vector<VideoReceiveStream::Config>* receive_configs,
4984 VideoEncoderConfig* encoder_config) override {
magjed509e4fe2016-11-18 01:34:11 -08004985 encoder_.reset(VP8Encoder::Create());
palmkviste75f2042016-09-28 06:19:48 -07004986 decoder_.reset(VP8Decoder::Create());
4987
4988 send_config->post_encode_callback = this;
4989 send_config->encoder_settings.payload_name = "VP8";
4990 send_config->encoder_settings.encoder = encoder_.get();
4991
4992 (*receive_configs)[0].decoders.resize(1);
4993 (*receive_configs)[0].decoders[0].payload_type =
4994 send_config->encoder_settings.payload_type;
4995 (*receive_configs)[0].decoders[0].payload_name =
4996 send_config->encoder_settings.payload_name;
4997 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
4998 }
4999
5000 void EncodedFrameCallback(const EncodedFrame& encoded_frame) override {
5001 rtc::CritScope lock(&crit_);
5002 if (recorded_frames_++ > kNumFramesToRecord) {
5003 fixture_->LogSend(false);
5004 fixture_->LogReceive(false);
5005 rtc::File send_file(fixture_->OpenFile(0));
5006 rtc::File receive_file(fixture_->OpenFile(1));
5007 uint8_t out[100];
5008 // If logging has worked correctly neither file should be empty, i.e.
5009 // we should be able to read something from them.
5010 EXPECT_LT(0u, send_file.Read(out, 100));
5011 EXPECT_LT(0u, receive_file.Read(out, 100));
5012 observation_complete_.Set();
5013 }
5014 }
5015
5016 private:
5017 EndToEndLogTest* const fixture_;
5018 std::unique_ptr<VideoEncoder> encoder_;
5019 std::unique_ptr<VideoDecoder> decoder_;
5020 rtc::CriticalSection crit_;
5021 int recorded_frames_ GUARDED_BY(crit_);
5022 } test(this);
5023
5024 RunBaseTest(&test);
5025}
5026
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00005027} // namespace webrtc