blob: 3f22b5229a06861ede93e7d482cf55d4cb4126e1 [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>
13#include <sstream>
14#include <string>
15
16#include "testing/gtest/include/gtest/gtest.h"
17
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +000018#include "webrtc/base/checks.h"
Erik Språng6b8d3552015-09-24 15:06:57 +020019#include "webrtc/base/event.h"
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +000020#include "webrtc/base/scoped_ptr.h"
danilchap5c35cf92016-02-03 14:14:49 -080021#include "webrtc/base/timeutils.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000022#include "webrtc/call.h"
Peter Boström5c389d32015-09-25 13:58:30 +020023#include "webrtc/call/transport_adapter.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000024#include "webrtc/frame_callback.h"
danilchap5c35cf92016-02-03 14:14:49 -080025#include "webrtc/modules/include/module_common_types.h"
stefan32f81542016-01-20 07:13:58 -080026#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h"
sprang861c55e2015-10-16 10:01:21 -070027#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000028#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
hbosbab934b2016-01-27 01:36:03 -080029#include "webrtc/modules/video_coding/codecs/h264/include/h264.h"
marpan@webrtc.org5b883172014-11-01 06:10:48 +000030#include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h"
31#include "webrtc/modules/video_coding/codecs/vp9/include/vp9.h"
Henrik Kjellander2557b862015-11-18 22:00:21 +010032#include "webrtc/modules/video_coding/include/video_coding_defines.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010033#include "webrtc/system_wrappers/include/metrics.h"
34#include "webrtc/system_wrappers/include/sleep.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000035#include "webrtc/test/call_test.h"
36#include "webrtc/test/direct_transport.h"
37#include "webrtc/test/encoder_settings.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000038#include "webrtc/test/fake_decoder.h"
39#include "webrtc/test/fake_encoder.h"
40#include "webrtc/test/frame_generator.h"
41#include "webrtc/test/frame_generator_capturer.h"
Åsa Persson352b2d72015-04-15 18:00:40 +020042#include "webrtc/test/histogram.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000043#include "webrtc/test/null_transport.h"
asapersson@webrtc.org37c05592015-01-28 13:58:27 +000044#include "webrtc/test/rtcp_packet_parser.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000045#include "webrtc/test/rtp_rtcp_observer.h"
46#include "webrtc/test/testsupport/fileutils.h"
47#include "webrtc/test/testsupport/perf_test.h"
pbos@webrtc.orgab990ae2014-09-17 09:02:25 +000048#include "webrtc/video_encoder.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000049
50namespace webrtc {
51
Peter Boström5811a392015-12-10 13:02:50 +010052static const int kSilenceTimeoutMs = 2000;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000053
54class EndToEndTest : public test::CallTest {
55 public:
56 EndToEndTest() {}
57
58 virtual ~EndToEndTest() {
stefanff483612015-12-21 03:14:00 -080059 EXPECT_EQ(nullptr, video_send_stream_);
60 EXPECT_TRUE(video_receive_streams_.empty());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000061 }
62
63 protected:
pbos2d566682015-09-28 09:59:31 -070064 class UnusedTransport : public Transport {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000065 private:
stefan1d8a5062015-10-02 03:39:33 -070066 bool SendRtp(const uint8_t* packet,
67 size_t length,
68 const PacketOptions& options) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000069 ADD_FAILURE() << "Unexpected RTP sent.";
70 return false;
71 }
72
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000073 bool SendRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000074 ADD_FAILURE() << "Unexpected RTCP sent.";
75 return false;
76 }
77 };
78
Peter Boström39593972016-02-15 11:27:15 +010079 void DecodesRetransmittedFrame(bool enable_rtx, bool enable_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000080 void ReceivesPliAndRecovers(int rtp_history_ms);
pbosda903ea2015-10-02 02:36:56 -070081 void RespectsRtcpMode(RtcpMode rtcp_mode);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000082 void TestXrReceiverReferenceTimeReport(bool enable_rrtr);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +000083 void TestSendsSetSsrcs(size_t num_ssrcs, bool send_single_ssrc_first);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +000084 void TestRtpStatePreservation(bool use_rtx);
sprangb4a1ae52015-12-03 08:10:08 -080085 void VerifyHistogramStats(bool use_rtx, bool use_red, bool screenshare);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000086};
87
88TEST_F(EndToEndTest, ReceiverCanBeStartedTwice) {
solenberg4fbae2b2015-08-28 04:07:10 -070089 CreateCalls(Call::Config(), Call::Config());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000090
solenberg4fbae2b2015-08-28 04:07:10 -070091 test::NullTransport transport;
Stefan Holmer9fea80f2016-01-07 17:43:18 +010092 CreateSendConfig(1, 0, &transport);
solenberg4fbae2b2015-08-28 04:07:10 -070093 CreateMatchingReceiveConfigs(&transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000094
Stefan Holmer9fea80f2016-01-07 17:43:18 +010095 CreateVideoStreams();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000096
stefanff483612015-12-21 03:14:00 -080097 video_receive_streams_[0]->Start();
98 video_receive_streams_[0]->Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000099
100 DestroyStreams();
101}
102
103TEST_F(EndToEndTest, ReceiverCanBeStoppedTwice) {
solenberg4fbae2b2015-08-28 04:07:10 -0700104 CreateCalls(Call::Config(), Call::Config());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000105
solenberg4fbae2b2015-08-28 04:07:10 -0700106 test::NullTransport transport;
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100107 CreateSendConfig(1, 0, &transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700108 CreateMatchingReceiveConfigs(&transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000109
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100110 CreateVideoStreams();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000111
stefanff483612015-12-21 03:14:00 -0800112 video_receive_streams_[0]->Stop();
113 video_receive_streams_[0]->Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000114
115 DestroyStreams();
116}
117
118TEST_F(EndToEndTest, RendersSingleDelayedFrame) {
119 static const int kWidth = 320;
120 static const int kHeight = 240;
121 // This constant is chosen to be higher than the timeout in the video_render
122 // module. This makes sure that frames aren't dropped if there are no other
123 // frames in the queue.
124 static const int kDelayRenderCallbackMs = 1000;
125
126 class Renderer : public VideoRenderer {
127 public:
Peter Boström5811a392015-12-10 13:02:50 +0100128 Renderer() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000129
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700130 void RenderFrame(const VideoFrame& video_frame,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000131 int /*time_to_render_ms*/) override {
Peter Boström5811a392015-12-10 13:02:50 +0100132 event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000133 }
134
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000135 bool IsTextureSupported() const override { return false; }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000136
Peter Boström5811a392015-12-10 13:02:50 +0100137 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000138
Peter Boström5811a392015-12-10 13:02:50 +0100139 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000140 } renderer;
141
142 class TestFrameCallback : public I420FrameCallback {
143 public:
Peter Boström5811a392015-12-10 13:02:50 +0100144 TestFrameCallback() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000145
Peter Boström5811a392015-12-10 13:02:50 +0100146 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000147
148 private:
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700149 void FrameCallback(VideoFrame* frame) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000150 SleepMs(kDelayRenderCallbackMs);
Peter Boström5811a392015-12-10 13:02:50 +0100151 event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000152 }
153
Peter Boström5811a392015-12-10 13:02:50 +0100154 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000155 };
156
solenberg4fbae2b2015-08-28 04:07:10 -0700157 CreateCalls(Call::Config(), Call::Config());
158
stefanf116bd02015-10-27 08:29:42 -0700159 test::DirectTransport sender_transport(sender_call_.get());
160 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000161 sender_transport.SetReceiver(receiver_call_->Receiver());
162 receiver_transport.SetReceiver(sender_call_->Receiver());
163
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100164 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700165 CreateMatchingReceiveConfigs(&receiver_transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000166
167 TestFrameCallback pre_render_callback;
stefanff483612015-12-21 03:14:00 -0800168 video_receive_configs_[0].pre_render_callback = &pre_render_callback;
169 video_receive_configs_[0].renderer = &renderer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000170
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100171 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000172 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000173
174 // Create frames that are smaller than the send width/height, this is done to
175 // check that the callbacks are done after processing video.
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000176 rtc::scoped_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +0000177 test::FrameGenerator::CreateChromaGenerator(kWidth, kHeight));
stefanff483612015-12-21 03:14:00 -0800178 video_send_stream_->Input()->IncomingCapturedFrame(
179 *frame_generator->NextFrame());
Peter Boström5811a392015-12-10 13:02:50 +0100180 EXPECT_TRUE(pre_render_callback.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000181 << "Timed out while waiting for pre-render callback.";
Peter Boström5811a392015-12-10 13:02:50 +0100182 EXPECT_TRUE(renderer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000183 << "Timed out while waiting for the frame to render.";
184
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000185 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000186
187 sender_transport.StopSending();
188 receiver_transport.StopSending();
189
190 DestroyStreams();
191}
192
193TEST_F(EndToEndTest, TransmitsFirstFrame) {
194 class Renderer : public VideoRenderer {
195 public:
Peter Boström5811a392015-12-10 13:02:50 +0100196 Renderer() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000197
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700198 void RenderFrame(const VideoFrame& video_frame,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000199 int /*time_to_render_ms*/) override {
Peter Boström5811a392015-12-10 13:02:50 +0100200 event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000201 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000202 bool IsTextureSupported() const override { return false; }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000203
Peter Boström5811a392015-12-10 13:02:50 +0100204 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000205
Peter Boström5811a392015-12-10 13:02:50 +0100206 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000207 } renderer;
208
solenberg4fbae2b2015-08-28 04:07:10 -0700209 CreateCalls(Call::Config(), Call::Config());
210
stefanf116bd02015-10-27 08:29:42 -0700211 test::DirectTransport sender_transport(sender_call_.get());
212 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000213 sender_transport.SetReceiver(receiver_call_->Receiver());
214 receiver_transport.SetReceiver(sender_call_->Receiver());
215
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100216 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700217 CreateMatchingReceiveConfigs(&receiver_transport);
stefanff483612015-12-21 03:14:00 -0800218 video_receive_configs_[0].renderer = &renderer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000219
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100220 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000221 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000222
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000223 rtc::scoped_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +0000224 test::FrameGenerator::CreateChromaGenerator(
stefanff483612015-12-21 03:14:00 -0800225 video_encoder_config_.streams[0].width,
226 video_encoder_config_.streams[0].height));
227 video_send_stream_->Input()->IncomingCapturedFrame(
228 *frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000229
Peter Boström5811a392015-12-10 13:02:50 +0100230 EXPECT_TRUE(renderer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000231 << "Timed out while waiting for the frame to render.";
232
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000233 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000234
235 sender_transport.StopSending();
236 receiver_transport.StopSending();
237
238 DestroyStreams();
239}
240
marpan@webrtc.org5f1e2e42014-11-06 02:02:28 +0000241TEST_F(EndToEndTest, SendsAndReceivesVP9) {
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000242 class VP9Observer : public test::EndToEndTest, public VideoRenderer {
243 public:
244 VP9Observer()
245 : EndToEndTest(2 * kDefaultTimeoutMs),
246 encoder_(VideoEncoder::Create(VideoEncoder::kVp9)),
247 decoder_(VP9Decoder::Create()),
248 frame_counter_(0) {}
249
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000250 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100251 EXPECT_TRUE(Wait())
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000252 << "Timed out while waiting for enough frames to be decoded.";
253 }
254
stefanff483612015-12-21 03:14:00 -0800255 void ModifyVideoConfigs(
256 VideoSendStream::Config* send_config,
257 std::vector<VideoReceiveStream::Config>* receive_configs,
258 VideoEncoderConfig* encoder_config) override {
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000259 send_config->encoder_settings.encoder = encoder_.get();
260 send_config->encoder_settings.payload_name = "VP9";
pbosa7d70542015-07-07 07:35:49 -0700261 send_config->encoder_settings.payload_type = 124;
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000262 encoder_config->streams[0].min_bitrate_bps = 50000;
263 encoder_config->streams[0].target_bitrate_bps =
264 encoder_config->streams[0].max_bitrate_bps = 2000000;
265
266 (*receive_configs)[0].renderer = this;
267 (*receive_configs)[0].decoders.resize(1);
268 (*receive_configs)[0].decoders[0].payload_type =
269 send_config->encoder_settings.payload_type;
270 (*receive_configs)[0].decoders[0].payload_name =
271 send_config->encoder_settings.payload_name;
272 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
273 }
274
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700275 void RenderFrame(const VideoFrame& video_frame,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000276 int time_to_render_ms) override {
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000277 const int kRequiredFrames = 500;
278 if (++frame_counter_ == kRequiredFrames)
Peter Boström5811a392015-12-10 13:02:50 +0100279 observation_complete_.Set();
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000280 }
281
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000282 bool IsTextureSupported() const override { return false; }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000283
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000284 private:
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000285 rtc::scoped_ptr<webrtc::VideoEncoder> encoder_;
286 rtc::scoped_ptr<webrtc::VideoDecoder> decoder_;
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000287 int frame_counter_;
288 } test;
289
stefane74eef12016-01-08 06:47:13 -0800290 RunBaseTest(&test);
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000291}
292
hbosbab934b2016-01-27 01:36:03 -0800293#if defined(WEBRTC_END_TO_END_H264_TESTS)
294
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000295TEST_F(EndToEndTest, SendsAndReceivesH264) {
296 class H264Observer : public test::EndToEndTest, public VideoRenderer {
297 public:
298 H264Observer()
299 : EndToEndTest(2 * kDefaultTimeoutMs),
hbosbab934b2016-01-27 01:36:03 -0800300 encoder_(VideoEncoder::Create(VideoEncoder::kH264)),
301 decoder_(H264Decoder::Create()),
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000302 frame_counter_(0) {}
303
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000304 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100305 EXPECT_TRUE(Wait())
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000306 << "Timed out while waiting for enough frames to be decoded.";
307 }
308
stefanff483612015-12-21 03:14:00 -0800309 void ModifyVideoConfigs(
310 VideoSendStream::Config* send_config,
311 std::vector<VideoReceiveStream::Config>* receive_configs,
312 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org8278c072015-02-23 11:11:49 +0000313 send_config->rtp.nack.rtp_history_ms =
314 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
hbosbab934b2016-01-27 01:36:03 -0800315 send_config->encoder_settings.encoder = encoder_.get();
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000316 send_config->encoder_settings.payload_name = "H264";
hbosbab934b2016-01-27 01:36:03 -0800317 send_config->encoder_settings.payload_type = 126;
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +0000318 encoder_config->streams[0].min_bitrate_bps = 50000;
319 encoder_config->streams[0].target_bitrate_bps =
320 encoder_config->streams[0].max_bitrate_bps = 2000000;
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000321
322 (*receive_configs)[0].renderer = this;
pbos@webrtc.org776e6f22014-10-29 15:28:39 +0000323 (*receive_configs)[0].decoders.resize(1);
324 (*receive_configs)[0].decoders[0].payload_type =
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000325 send_config->encoder_settings.payload_type;
pbos@webrtc.org776e6f22014-10-29 15:28:39 +0000326 (*receive_configs)[0].decoders[0].payload_name =
327 send_config->encoder_settings.payload_name;
hbosbab934b2016-01-27 01:36:03 -0800328 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000329 }
330
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700331 void RenderFrame(const VideoFrame& video_frame,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000332 int time_to_render_ms) override {
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000333 const int kRequiredFrames = 500;
334 if (++frame_counter_ == kRequiredFrames)
Peter Boström5811a392015-12-10 13:02:50 +0100335 observation_complete_.Set();
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000336 }
337
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000338 bool IsTextureSupported() const override { return false; }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000339
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000340 private:
hbosbab934b2016-01-27 01:36:03 -0800341 rtc::scoped_ptr<webrtc::VideoEncoder> encoder_;
342 rtc::scoped_ptr<webrtc::VideoDecoder> decoder_;
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000343 int frame_counter_;
344 } test;
345
stefane74eef12016-01-08 06:47:13 -0800346 RunBaseTest(&test);
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000347}
348
hbosbab934b2016-01-27 01:36:03 -0800349#endif // defined(WEBRTC_END_TO_END_H264_TESTS)
350
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000351TEST_F(EndToEndTest, ReceiverUsesLocalSsrc) {
352 class SyncRtcpObserver : public test::EndToEndTest {
353 public:
354 SyncRtcpObserver() : EndToEndTest(kDefaultTimeoutMs) {}
355
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000356 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000357 RTCPUtility::RTCPParserV2 parser(packet, length, true);
358 EXPECT_TRUE(parser.IsValid());
359 uint32_t ssrc = 0;
360 ssrc |= static_cast<uint32_t>(packet[4]) << 24;
361 ssrc |= static_cast<uint32_t>(packet[5]) << 16;
362 ssrc |= static_cast<uint32_t>(packet[6]) << 8;
363 ssrc |= static_cast<uint32_t>(packet[7]) << 0;
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100364 EXPECT_EQ(kReceiverLocalVideoSsrc, ssrc);
Peter Boström5811a392015-12-10 13:02:50 +0100365 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000366
367 return SEND_PACKET;
368 }
369
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000370 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100371 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000372 << "Timed out while waiting for a receiver RTCP packet to be sent.";
373 }
374 } test;
375
stefane74eef12016-01-08 06:47:13 -0800376 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000377}
378
379TEST_F(EndToEndTest, ReceivesAndRetransmitsNack) {
380 static const int kNumberOfNacksToObserve = 2;
381 static const int kLossBurstSize = 2;
382 static const int kPacketsBetweenLossBursts = 9;
383 class NackObserver : public test::EndToEndTest {
384 public:
385 NackObserver()
386 : EndToEndTest(kLongTimeoutMs),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000387 sent_rtp_packets_(0),
388 packets_left_to_drop_(0),
389 nacks_left_(kNumberOfNacksToObserve) {}
390
391 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000392 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700393 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000394 RTPHeader header;
Peter Boström03671cb2015-12-07 15:22:24 +0100395 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000396
397 // Never drop retransmitted packets.
398 if (dropped_packets_.find(header.sequenceNumber) !=
399 dropped_packets_.end()) {
400 retransmitted_packets_.insert(header.sequenceNumber);
Stefan Holmer586b19b2015-09-18 11:14:31 +0200401 if (nacks_left_ <= 0 &&
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000402 retransmitted_packets_.size() == dropped_packets_.size()) {
Peter Boström5811a392015-12-10 13:02:50 +0100403 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000404 }
405 return SEND_PACKET;
406 }
407
408 ++sent_rtp_packets_;
409
410 // Enough NACKs received, stop dropping packets.
Stefan Holmer586b19b2015-09-18 11:14:31 +0200411 if (nacks_left_ <= 0)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000412 return SEND_PACKET;
413
414 // Check if it's time for a new loss burst.
415 if (sent_rtp_packets_ % kPacketsBetweenLossBursts == 0)
416 packets_left_to_drop_ = kLossBurstSize;
417
Stefan Holmer01b48882015-05-05 10:21:24 +0200418 // Never drop padding packets as those won't be retransmitted.
419 if (packets_left_to_drop_ > 0 && header.paddingLength == 0) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000420 --packets_left_to_drop_;
421 dropped_packets_.insert(header.sequenceNumber);
422 return DROP_PACKET;
423 }
424
425 return SEND_PACKET;
426 }
427
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000428 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700429 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000430 RTCPUtility::RTCPParserV2 parser(packet, length, true);
431 EXPECT_TRUE(parser.IsValid());
432
433 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +0200434 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
435 if (packet_type == RTCPUtility::RTCPPacketTypes::kRtpfbNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000436 --nacks_left_;
437 break;
438 }
439 packet_type = parser.Iterate();
440 }
441 return SEND_PACKET;
442 }
443
stefanff483612015-12-21 03:14:00 -0800444 void ModifyVideoConfigs(
445 VideoSendStream::Config* send_config,
446 std::vector<VideoReceiveStream::Config>* receive_configs,
447 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000448 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000449 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000450 }
451
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000452 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100453 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000454 << "Timed out waiting for packets to be NACKed, retransmitted and "
455 "rendered.";
456 }
457
stefanf116bd02015-10-27 08:29:42 -0700458 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000459 std::set<uint16_t> dropped_packets_;
460 std::set<uint16_t> retransmitted_packets_;
461 uint64_t sent_rtp_packets_;
462 int packets_left_to_drop_;
stefanf116bd02015-10-27 08:29:42 -0700463 int nacks_left_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000464 } test;
465
stefane74eef12016-01-08 06:47:13 -0800466 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000467}
468
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000469TEST_F(EndToEndTest, CanReceiveFec) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000470 class FecRenderObserver : public test::EndToEndTest, public VideoRenderer {
471 public:
472 FecRenderObserver()
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000473 : EndToEndTest(kDefaultTimeoutMs), state_(kFirstPacket) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000474
475 private:
stefanf116bd02015-10-27 08:29:42 -0700476 Action OnSendRtp(const uint8_t* packet, size_t length) override {
477 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000478 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000479 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000480
Stefan Holmer01b48882015-05-05 10:21:24 +0200481 int encapsulated_payload_type = -1;
482 if (header.payloadType == kRedPayloadType) {
483 encapsulated_payload_type =
484 static_cast<int>(packet[header.headerLength]);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100485 if (encapsulated_payload_type != kFakeVideoSendPayloadType)
Stefan Holmer01b48882015-05-05 10:21:24 +0200486 EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
487 } else {
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100488 EXPECT_EQ(kFakeVideoSendPayloadType, header.payloadType);
Stefan Holmer01b48882015-05-05 10:21:24 +0200489 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000490
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000491 if (protected_sequence_numbers_.count(header.sequenceNumber) != 0) {
492 // Retransmitted packet, should not count.
493 protected_sequence_numbers_.erase(header.sequenceNumber);
494 EXPECT_GT(protected_timestamps_.count(header.timestamp), 0u);
495 protected_timestamps_.erase(header.timestamp);
496 return SEND_PACKET;
497 }
498
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000499 switch (state_) {
500 case kFirstPacket:
501 state_ = kDropEveryOtherPacketUntilFec;
502 break;
503 case kDropEveryOtherPacketUntilFec:
504 if (encapsulated_payload_type == kUlpfecPayloadType) {
505 state_ = kDropNextMediaPacket;
506 return SEND_PACKET;
507 }
508 if (header.sequenceNumber % 2 == 0)
509 return DROP_PACKET;
510 break;
511 case kDropNextMediaPacket:
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100512 if (encapsulated_payload_type == kFakeVideoSendPayloadType) {
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000513 protected_sequence_numbers_.insert(header.sequenceNumber);
514 protected_timestamps_.insert(header.timestamp);
515 state_ = kDropEveryOtherPacketUntilFec;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000516 return DROP_PACKET;
517 }
518 break;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000519 }
520
521 return SEND_PACKET;
522 }
523
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700524 void RenderFrame(const VideoFrame& video_frame,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000525 int time_to_render_ms) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200526 rtc::CritScope lock(&crit_);
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000527 // Rendering frame with timestamp of packet that was dropped -> FEC
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000528 // protection worked.
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000529 if (protected_timestamps_.count(video_frame.timestamp()) != 0)
Peter Boström5811a392015-12-10 13:02:50 +0100530 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000531 }
532
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000533 bool IsTextureSupported() const override { return false; }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000534
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000535 enum {
536 kFirstPacket,
537 kDropEveryOtherPacketUntilFec,
538 kDropNextMediaPacket,
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000539 } state_;
540
stefanff483612015-12-21 03:14:00 -0800541 void ModifyVideoConfigs(
542 VideoSendStream::Config* send_config,
543 std::vector<VideoReceiveStream::Config>* receive_configs,
544 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000545 // TODO(pbos): Run this test with combined NACK/FEC enabled as well.
546 // int rtp_history_ms = 1000;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000547 // (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000548 // send_config->rtp.nack.rtp_history_ms = rtp_history_ms;
549 send_config->rtp.fec.red_payload_type = kRedPayloadType;
550 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
551
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000552 (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
553 (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
554 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000555 }
556
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000557 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100558 EXPECT_TRUE(Wait())
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000559 << "Timed out waiting for dropped frames frames to be rendered.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000560 }
561
stefanf116bd02015-10-27 08:29:42 -0700562 rtc::CriticalSection crit_;
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000563 std::set<uint32_t> protected_sequence_numbers_ GUARDED_BY(crit_);
564 std::set<uint32_t> protected_timestamps_ GUARDED_BY(crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000565 } test;
566
stefane74eef12016-01-08 06:47:13 -0800567 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000568}
569
Henrik Kjellanderdb313b62015-04-02 08:45:41 +0200570// Flacky on all platforms. See webrtc:4328.
571TEST_F(EndToEndTest, DISABLED_ReceivedFecPacketsNotNacked) {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000572 class FecNackObserver : public test::EndToEndTest {
573 public:
mflodmand1590b22015-12-09 07:07:59 -0800574 FecNackObserver()
stefanf116bd02015-10-27 08:29:42 -0700575 : EndToEndTest(kDefaultTimeoutMs),
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000576 state_(kFirstPacket),
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000577 fec_sequence_number_(0),
578 has_last_sequence_number_(false),
579 last_sequence_number_(0) {}
580
581 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000582 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -0800583 rtc::CritScope lock_(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000584 RTPHeader header;
585 EXPECT_TRUE(parser_->Parse(packet, length, &header));
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000586
Stefan Holmer01b48882015-05-05 10:21:24 +0200587 int encapsulated_payload_type = -1;
588 if (header.payloadType == kRedPayloadType) {
589 encapsulated_payload_type =
590 static_cast<int>(packet[header.headerLength]);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100591 if (encapsulated_payload_type != kFakeVideoSendPayloadType)
Stefan Holmer01b48882015-05-05 10:21:24 +0200592 EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
593 } else {
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100594 EXPECT_EQ(kFakeVideoSendPayloadType, header.payloadType);
Stefan Holmer01b48882015-05-05 10:21:24 +0200595 }
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000596
597 if (has_last_sequence_number_ &&
598 !IsNewerSequenceNumber(header.sequenceNumber,
599 last_sequence_number_)) {
600 // Drop retransmitted packets.
601 return DROP_PACKET;
602 }
603 last_sequence_number_ = header.sequenceNumber;
604 has_last_sequence_number_ = true;
605
606 bool fec_packet = encapsulated_payload_type == kUlpfecPayloadType;
607 switch (state_) {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000608 case kFirstPacket:
609 state_ = kDropEveryOtherPacketUntilFec;
610 break;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000611 case kDropEveryOtherPacketUntilFec:
612 if (fec_packet) {
613 state_ = kDropAllMediaPacketsUntilFec;
614 } else if (header.sequenceNumber % 2 == 0) {
615 return DROP_PACKET;
616 }
617 break;
618 case kDropAllMediaPacketsUntilFec:
619 if (!fec_packet)
620 return DROP_PACKET;
621 fec_sequence_number_ = header.sequenceNumber;
622 state_ = kVerifyFecPacketNotInNackList;
623 break;
624 case kVerifyFecPacketNotInNackList:
625 // Continue to drop packets. Make sure no frame can be decoded.
626 if (fec_packet || header.sequenceNumber % 2 == 0)
627 return DROP_PACKET;
628 break;
629 }
630 return SEND_PACKET;
631 }
632
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000633 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -0800634 rtc::CritScope lock_(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000635 if (state_ == kVerifyFecPacketNotInNackList) {
636 test::RtcpPacketParser rtcp_parser;
637 rtcp_parser.Parse(packet, length);
638 std::vector<uint16_t> nacks = rtcp_parser.nack_item()->last_nack_list();
639 if (!nacks.empty() &&
640 IsNewerSequenceNumber(nacks.back(), fec_sequence_number_)) {
641 EXPECT_TRUE(std::find(
642 nacks.begin(), nacks.end(), fec_sequence_number_) == nacks.end());
Peter Boström5811a392015-12-10 13:02:50 +0100643 observation_complete_.Set();
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000644 }
645 }
646 return SEND_PACKET;
647 }
648
stefane74eef12016-01-08 06:47:13 -0800649 test::PacketTransport* CreateSendTransport(Call* sender_call) override {
650 // At low RTT (< kLowRttNackMs) -> NACK only, no FEC.
651 // Configure some network delay.
652 const int kNetworkDelayMs = 50;
653 FakeNetworkPipe::Config config;
654 config.queue_delay_ms = kNetworkDelayMs;
655 return new test::PacketTransport(sender_call, this,
656 test::PacketTransport::kSender, config);
657 }
658
Stefan Holmere5904162015-03-26 11:11:06 +0100659 // TODO(holmer): Investigate why we don't send FEC packets when the bitrate
660 // is 10 kbps.
661 Call::Config GetSenderCallConfig() override {
solenberg4fbae2b2015-08-28 04:07:10 -0700662 Call::Config config;
Stefan Holmere5904162015-03-26 11:11:06 +0100663 const int kMinBitrateBps = 30000;
664 config.bitrate_config.min_bitrate_bps = kMinBitrateBps;
665 return config;
666 }
667
stefanff483612015-12-21 03:14:00 -0800668 void ModifyVideoConfigs(
669 VideoSendStream::Config* send_config,
670 std::vector<VideoReceiveStream::Config>* receive_configs,
671 VideoEncoderConfig* encoder_config) override {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000672 // Configure hybrid NACK/FEC.
673 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
674 send_config->rtp.fec.red_payload_type = kRedPayloadType;
675 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
676 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
677 (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
678 (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
679 }
680
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000681 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100682 EXPECT_TRUE(Wait())
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000683 << "Timed out while waiting for FEC packets to be received.";
684 }
685
686 enum {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000687 kFirstPacket,
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000688 kDropEveryOtherPacketUntilFec,
689 kDropAllMediaPacketsUntilFec,
690 kVerifyFecPacketNotInNackList,
691 } state_;
692
stefan608213e2015-11-01 14:56:10 -0800693 rtc::CriticalSection crit_;
694 uint16_t fec_sequence_number_ GUARDED_BY(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000695 bool has_last_sequence_number_;
696 uint16_t last_sequence_number_;
stefanf116bd02015-10-27 08:29:42 -0700697 } test;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000698
stefane74eef12016-01-08 06:47:13 -0800699 RunBaseTest(&test);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000700}
701
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000702// This test drops second RTP packet with a marker bit set, makes sure it's
703// retransmitted and renders. Retransmission SSRCs are also checked.
Peter Boström39593972016-02-15 11:27:15 +0100704void EndToEndTest::DecodesRetransmittedFrame(bool enable_rtx, bool enable_red) {
Peter Boström67680c12016-02-17 11:10:04 +0100705 static const int kDroppedFrameNumber = 10;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000706 class RetransmissionObserver : public test::EndToEndTest,
707 public I420FrameCallback {
708 public:
Peter Boström39593972016-02-15 11:27:15 +0100709 RetransmissionObserver(bool enable_rtx, bool enable_red)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000710 : EndToEndTest(kDefaultTimeoutMs),
Peter Boström39593972016-02-15 11:27:15 +0100711 payload_type_(GetPayloadType(false, enable_red)),
712 retransmission_ssrc_(enable_rtx ? kSendRtxSsrcs[0]
713 : kVideoSendSsrcs[0]),
714 retransmission_payload_type_(GetPayloadType(enable_rtx, enable_red)),
715 encoder_(VideoEncoder::Create(VideoEncoder::EncoderType::kVp8)),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000716 marker_bits_observed_(0),
717 retransmitted_timestamp_(0),
718 frame_retransmitted_(false) {}
719
720 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000721 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700722 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000723 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000724 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000725
Peter Boström67680c12016-02-17 11:10:04 +0100726 // Ignore padding-only packets over RTX.
727 if (header.payloadType != payload_type_) {
728 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
729 if (length == header.headerLength + header.paddingLength)
730 return SEND_PACKET;
Stefan Holmer586b19b2015-09-18 11:14:31 +0200731 }
Peter Boström67680c12016-02-17 11:10:04 +0100732
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000733 if (header.timestamp == retransmitted_timestamp_) {
734 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
735 EXPECT_EQ(retransmission_payload_type_, header.payloadType);
736 frame_retransmitted_ = true;
737 return SEND_PACKET;
738 }
739
Stefan Holmer10880012016-02-03 13:29:59 +0100740 EXPECT_EQ(kVideoSendSsrcs[0], header.ssrc)
741 << "Payload type " << static_cast<int>(header.payloadType)
742 << " not expected.";
Shao Changbine62202f2015-04-21 20:24:50 +0800743 EXPECT_EQ(payload_type_, header.payloadType);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000744
Stefan Holmer586b19b2015-09-18 11:14:31 +0200745 // Found the final packet of the frame to inflict loss to, drop this and
746 // expect a retransmission.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000747 if (header.markerBit && ++marker_bits_observed_ == kDroppedFrameNumber) {
748 retransmitted_timestamp_ = header.timestamp;
749 return DROP_PACKET;
750 }
751
752 return SEND_PACKET;
753 }
754
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700755 void FrameCallback(VideoFrame* frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200756 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000757 if (frame->timestamp() == retransmitted_timestamp_) {
758 EXPECT_TRUE(frame_retransmitted_);
Peter Boström5811a392015-12-10 13:02:50 +0100759 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000760 }
761 }
762
stefanff483612015-12-21 03:14:00 -0800763 void ModifyVideoConfigs(
764 VideoSendStream::Config* send_config,
765 std::vector<VideoReceiveStream::Config>* receive_configs,
766 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000767 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000768 (*receive_configs)[0].pre_render_callback = this;
769 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
Shao Changbine62202f2015-04-21 20:24:50 +0800770
771 if (payload_type_ == kRedPayloadType) {
772 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
773 send_config->rtp.fec.red_payload_type = kRedPayloadType;
Stefan Holmer10880012016-02-03 13:29:59 +0100774 if (retransmission_ssrc_ == kSendRtxSsrcs[0])
775 send_config->rtp.fec.red_rtx_payload_type = kRtxRedPayloadType;
776 (*receive_configs)[0].rtp.fec.ulpfec_payload_type =
777 send_config->rtp.fec.ulpfec_payload_type;
778 (*receive_configs)[0].rtp.fec.red_payload_type =
779 send_config->rtp.fec.red_payload_type;
780 (*receive_configs)[0].rtp.fec.red_rtx_payload_type =
781 send_config->rtp.fec.red_rtx_payload_type;
Shao Changbine62202f2015-04-21 20:24:50 +0800782 }
783
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000784 if (retransmission_ssrc_ == kSendRtxSsrcs[0]) {
785 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000786 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
Stefan Holmer10880012016-02-03 13:29:59 +0100787 (*receive_configs)[0].rtp.rtx[payload_type_].ssrc = kSendRtxSsrcs[0];
788 (*receive_configs)[0].rtp.rtx[payload_type_].payload_type =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000789 kSendRtxPayloadType;
790 }
Peter Boström39593972016-02-15 11:27:15 +0100791 // Configure encoding and decoding with VP8, since generic packetization
792 // doesn't support FEC with NACK.
793 RTC_DCHECK_EQ(1u, (*receive_configs)[0].decoders.size());
794 send_config->encoder_settings.encoder = encoder_.get();
795 send_config->encoder_settings.payload_name = "VP8";
796 (*receive_configs)[0].decoders[0].payload_name = "VP8";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000797 }
798
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000799 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100800 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000801 << "Timed out while waiting for retransmission to render.";
802 }
803
Shao Changbine62202f2015-04-21 20:24:50 +0800804 int GetPayloadType(bool use_rtx, bool use_red) {
Stefan Holmer10880012016-02-03 13:29:59 +0100805 if (use_red) {
806 if (use_rtx)
807 return kRtxRedPayloadType;
808 return kRedPayloadType;
809 }
810 if (use_rtx)
811 return kSendRtxPayloadType;
812 return kFakeVideoSendPayloadType;
Shao Changbine62202f2015-04-21 20:24:50 +0800813 }
814
stefanf116bd02015-10-27 08:29:42 -0700815 rtc::CriticalSection crit_;
Shao Changbine62202f2015-04-21 20:24:50 +0800816 const int payload_type_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000817 const uint32_t retransmission_ssrc_;
818 const int retransmission_payload_type_;
Peter Boström39593972016-02-15 11:27:15 +0100819 rtc::scoped_ptr<VideoEncoder> encoder_;
820 const std::string payload_name_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000821 int marker_bits_observed_;
stefanf116bd02015-10-27 08:29:42 -0700822 uint32_t retransmitted_timestamp_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000823 bool frame_retransmitted_;
Peter Boström39593972016-02-15 11:27:15 +0100824 } test(enable_rtx, enable_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000825
stefane74eef12016-01-08 06:47:13 -0800826 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000827}
828
829TEST_F(EndToEndTest, DecodesRetransmittedFrame) {
Shao Changbine62202f2015-04-21 20:24:50 +0800830 DecodesRetransmittedFrame(false, false);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000831}
832
833TEST_F(EndToEndTest, DecodesRetransmittedFrameOverRtx) {
Shao Changbine62202f2015-04-21 20:24:50 +0800834 DecodesRetransmittedFrame(true, false);
835}
836
837TEST_F(EndToEndTest, DecodesRetransmittedFrameByRed) {
838 DecodesRetransmittedFrame(false, true);
839}
840
841TEST_F(EndToEndTest, DecodesRetransmittedFrameByRedOverRtx) {
842 DecodesRetransmittedFrame(true, true);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000843}
844
andresp@webrtc.org02686112014-09-19 08:24:19 +0000845TEST_F(EndToEndTest, UsesFrameCallbacks) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000846 static const int kWidth = 320;
847 static const int kHeight = 240;
848
849 class Renderer : public VideoRenderer {
850 public:
Peter Boström5811a392015-12-10 13:02:50 +0100851 Renderer() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000852
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700853 void RenderFrame(const VideoFrame& video_frame,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000854 int /*time_to_render_ms*/) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000855 EXPECT_EQ(0, *video_frame.buffer(kYPlane))
856 << "Rendered frame should have zero luma which is applied by the "
857 "pre-render callback.";
Peter Boström5811a392015-12-10 13:02:50 +0100858 event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000859 }
860
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000861 bool IsTextureSupported() const override { return false; }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000862
Peter Boström5811a392015-12-10 13:02:50 +0100863 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
864 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000865 } renderer;
866
867 class TestFrameCallback : public I420FrameCallback {
868 public:
869 TestFrameCallback(int expected_luma_byte, int next_luma_byte)
Peter Boström5811a392015-12-10 13:02:50 +0100870 : event_(false, false),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000871 expected_luma_byte_(expected_luma_byte),
872 next_luma_byte_(next_luma_byte) {}
873
Peter Boström5811a392015-12-10 13:02:50 +0100874 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000875
876 private:
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700877 virtual void FrameCallback(VideoFrame* frame) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000878 EXPECT_EQ(kWidth, frame->width())
879 << "Width not as expected, callback done before resize?";
880 EXPECT_EQ(kHeight, frame->height())
881 << "Height not as expected, callback done before resize?";
882
883 // Previous luma specified, observed luma should be fairly close.
884 if (expected_luma_byte_ != -1) {
885 EXPECT_NEAR(expected_luma_byte_, *frame->buffer(kYPlane), 10);
886 }
887
888 memset(frame->buffer(kYPlane),
889 next_luma_byte_,
890 frame->allocated_size(kYPlane));
891
Peter Boström5811a392015-12-10 13:02:50 +0100892 event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000893 }
894
Peter Boström5811a392015-12-10 13:02:50 +0100895 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000896 int expected_luma_byte_;
897 int next_luma_byte_;
898 };
899
900 TestFrameCallback pre_encode_callback(-1, 255); // Changes luma to 255.
901 TestFrameCallback pre_render_callback(255, 0); // Changes luma from 255 to 0.
902
solenberg4fbae2b2015-08-28 04:07:10 -0700903 CreateCalls(Call::Config(), Call::Config());
904
stefanf116bd02015-10-27 08:29:42 -0700905 test::DirectTransport sender_transport(sender_call_.get());
906 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000907 sender_transport.SetReceiver(receiver_call_->Receiver());
908 receiver_transport.SetReceiver(sender_call_->Receiver());
909
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100910 CreateSendConfig(1, 0, &sender_transport);
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000911 rtc::scoped_ptr<VideoEncoder> encoder(
pbos@webrtc.orgab990ae2014-09-17 09:02:25 +0000912 VideoEncoder::Create(VideoEncoder::kVp8));
stefanff483612015-12-21 03:14:00 -0800913 video_send_config_.encoder_settings.encoder = encoder.get();
914 video_send_config_.encoder_settings.payload_name = "VP8";
915 ASSERT_EQ(1u, video_encoder_config_.streams.size()) << "Test setup error.";
916 video_encoder_config_.streams[0].width = kWidth;
917 video_encoder_config_.streams[0].height = kHeight;
918 video_send_config_.pre_encode_callback = &pre_encode_callback;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000919
solenberg4fbae2b2015-08-28 04:07:10 -0700920 CreateMatchingReceiveConfigs(&receiver_transport);
stefanff483612015-12-21 03:14:00 -0800921 video_receive_configs_[0].pre_render_callback = &pre_render_callback;
922 video_receive_configs_[0].renderer = &renderer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000923
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100924 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000925 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000926
927 // Create frames that are smaller than the send width/height, this is done to
928 // check that the callbacks are done after processing video.
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000929 rtc::scoped_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +0000930 test::FrameGenerator::CreateChromaGenerator(kWidth / 2, kHeight / 2));
stefanff483612015-12-21 03:14:00 -0800931 video_send_stream_->Input()->IncomingCapturedFrame(
932 *frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000933
Peter Boström5811a392015-12-10 13:02:50 +0100934 EXPECT_TRUE(pre_encode_callback.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000935 << "Timed out while waiting for pre-encode callback.";
Peter Boström5811a392015-12-10 13:02:50 +0100936 EXPECT_TRUE(pre_render_callback.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000937 << "Timed out while waiting for pre-render callback.";
Peter Boström5811a392015-12-10 13:02:50 +0100938 EXPECT_TRUE(renderer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000939 << "Timed out while waiting for the frame to render.";
940
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000941 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000942
943 sender_transport.StopSending();
944 receiver_transport.StopSending();
945
946 DestroyStreams();
947}
948
949void EndToEndTest::ReceivesPliAndRecovers(int rtp_history_ms) {
950 static const int kPacketsToDrop = 1;
951
952 class PliObserver : public test::EndToEndTest, public VideoRenderer {
953 public:
954 explicit PliObserver(int rtp_history_ms)
955 : EndToEndTest(kLongTimeoutMs),
956 rtp_history_ms_(rtp_history_ms),
957 nack_enabled_(rtp_history_ms > 0),
958 highest_dropped_timestamp_(0),
959 frames_to_drop_(0),
960 received_pli_(false) {}
961
962 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000963 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700964 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000965 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000966 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000967
968 // Drop all retransmitted packets to force a PLI.
969 if (header.timestamp <= highest_dropped_timestamp_)
970 return DROP_PACKET;
971
972 if (frames_to_drop_ > 0) {
973 highest_dropped_timestamp_ = header.timestamp;
974 --frames_to_drop_;
975 return DROP_PACKET;
976 }
977
978 return SEND_PACKET;
979 }
980
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000981 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700982 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000983 RTCPUtility::RTCPParserV2 parser(packet, length, true);
984 EXPECT_TRUE(parser.IsValid());
985
986 for (RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +0200987 packet_type != RTCPUtility::RTCPPacketTypes::kInvalid;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000988 packet_type = parser.Iterate()) {
989 if (!nack_enabled_)
Erik Språng242e22b2015-05-11 10:17:43 +0200990 EXPECT_NE(packet_type, RTCPUtility::RTCPPacketTypes::kRtpfbNack);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000991
Erik Språng242e22b2015-05-11 10:17:43 +0200992 if (packet_type == RTCPUtility::RTCPPacketTypes::kPsfbPli) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000993 received_pli_ = true;
994 break;
995 }
996 }
997 return SEND_PACKET;
998 }
999
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001000 void RenderFrame(const VideoFrame& video_frame,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001001 int time_to_render_ms) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02001002 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001003 if (received_pli_ &&
1004 video_frame.timestamp() > highest_dropped_timestamp_) {
Peter Boström5811a392015-12-10 13:02:50 +01001005 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001006 }
1007 if (!received_pli_)
1008 frames_to_drop_ = kPacketsToDrop;
1009 }
1010
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001011 bool IsTextureSupported() const override { return false; }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00001012
stefanff483612015-12-21 03:14:00 -08001013 void ModifyVideoConfigs(
1014 VideoSendStream::Config* send_config,
1015 std::vector<VideoReceiveStream::Config>* receive_configs,
1016 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001017 send_config->rtp.nack.rtp_history_ms = rtp_history_ms_;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001018 (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms_;
1019 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001020 }
1021
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001022 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001023 EXPECT_TRUE(Wait()) << "Timed out waiting for PLI to be "
1024 "received and a frame to be "
1025 "rendered afterwards.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001026 }
1027
stefanf116bd02015-10-27 08:29:42 -07001028 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001029 int rtp_history_ms_;
1030 bool nack_enabled_;
stefanf116bd02015-10-27 08:29:42 -07001031 uint32_t highest_dropped_timestamp_ GUARDED_BY(&crit_);
1032 int frames_to_drop_ GUARDED_BY(&crit_);
1033 bool received_pli_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001034 } test(rtp_history_ms);
1035
stefane74eef12016-01-08 06:47:13 -08001036 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001037}
1038
1039TEST_F(EndToEndTest, ReceivesPliAndRecoversWithNack) {
1040 ReceivesPliAndRecovers(1000);
1041}
1042
jbauchdb81ffd2015-11-23 03:59:02 -08001043TEST_F(EndToEndTest, ReceivesPliAndRecoversWithoutNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001044 ReceivesPliAndRecovers(0);
1045}
1046
1047TEST_F(EndToEndTest, UnknownRtpPacketGivesUnknownSsrcReturnCode) {
1048 class PacketInputObserver : public PacketReceiver {
1049 public:
1050 explicit PacketInputObserver(PacketReceiver* receiver)
Peter Boström5811a392015-12-10 13:02:50 +01001051 : receiver_(receiver), delivered_packet_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001052
Peter Boström5811a392015-12-10 13:02:50 +01001053 bool Wait() { return delivered_packet_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001054
1055 private:
stefan68786d22015-09-08 05:36:15 -07001056 DeliveryStatus DeliverPacket(MediaType media_type,
1057 const uint8_t* packet,
1058 size_t length,
1059 const PacketTime& packet_time) override {
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001060 if (RtpHeaderParser::IsRtcp(packet, length)) {
stefan68786d22015-09-08 05:36:15 -07001061 return receiver_->DeliverPacket(media_type, packet, length,
1062 packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001063 } else {
1064 DeliveryStatus delivery_status =
stefan68786d22015-09-08 05:36:15 -07001065 receiver_->DeliverPacket(media_type, packet, length, packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001066 EXPECT_EQ(DELIVERY_UNKNOWN_SSRC, delivery_status);
Peter Boström5811a392015-12-10 13:02:50 +01001067 delivered_packet_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001068 return delivery_status;
1069 }
1070 }
1071
1072 PacketReceiver* receiver_;
Peter Boström5811a392015-12-10 13:02:50 +01001073 rtc::Event delivered_packet_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001074 };
1075
solenberg4fbae2b2015-08-28 04:07:10 -07001076 CreateCalls(Call::Config(), Call::Config());
1077
stefanf116bd02015-10-27 08:29:42 -07001078 test::DirectTransport send_transport(sender_call_.get());
1079 test::DirectTransport receive_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001080 PacketInputObserver input_observer(receiver_call_->Receiver());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001081 send_transport.SetReceiver(&input_observer);
1082 receive_transport.SetReceiver(sender_call_->Receiver());
1083
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001084 CreateSendConfig(1, 0, &send_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07001085 CreateMatchingReceiveConfigs(&receive_transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001086
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001087 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001088 CreateFrameGeneratorCapturer();
1089 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001090
stefanff483612015-12-21 03:14:00 -08001091 receiver_call_->DestroyVideoReceiveStream(video_receive_streams_[0]);
1092 video_receive_streams_.clear();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001093
1094 // Wait() waits for a received packet.
Peter Boström5811a392015-12-10 13:02:50 +01001095 EXPECT_TRUE(input_observer.Wait());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001096
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001097 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001098
1099 DestroyStreams();
1100
1101 send_transport.StopSending();
1102 receive_transport.StopSending();
1103}
1104
pbosda903ea2015-10-02 02:36:56 -07001105void EndToEndTest::RespectsRtcpMode(RtcpMode rtcp_mode) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001106 static const int kNumCompoundRtcpPacketsToObserve = 10;
1107 class RtcpModeObserver : public test::EndToEndTest {
1108 public:
pbosda903ea2015-10-02 02:36:56 -07001109 explicit RtcpModeObserver(RtcpMode rtcp_mode)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001110 : EndToEndTest(kDefaultTimeoutMs),
1111 rtcp_mode_(rtcp_mode),
1112 sent_rtp_(0),
1113 sent_rtcp_(0) {}
1114
1115 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001116 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001117 if (++sent_rtp_ % 3 == 0)
1118 return DROP_PACKET;
1119
1120 return SEND_PACKET;
1121 }
1122
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001123 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001124 ++sent_rtcp_;
1125 RTCPUtility::RTCPParserV2 parser(packet, length, true);
1126 EXPECT_TRUE(parser.IsValid());
1127
1128 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
1129 bool has_report_block = false;
Erik Språng242e22b2015-05-11 10:17:43 +02001130 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
1131 EXPECT_NE(RTCPUtility::RTCPPacketTypes::kSr, packet_type);
1132 if (packet_type == RTCPUtility::RTCPPacketTypes::kRr) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001133 has_report_block = true;
1134 break;
1135 }
1136 packet_type = parser.Iterate();
1137 }
1138
1139 switch (rtcp_mode_) {
pbosda903ea2015-10-02 02:36:56 -07001140 case RtcpMode::kCompound:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001141 if (!has_report_block) {
1142 ADD_FAILURE() << "Received RTCP packet without receiver report for "
pbosda903ea2015-10-02 02:36:56 -07001143 "RtcpMode::kCompound.";
Peter Boström5811a392015-12-10 13:02:50 +01001144 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001145 }
1146
1147 if (sent_rtcp_ >= kNumCompoundRtcpPacketsToObserve)
Peter Boström5811a392015-12-10 13:02:50 +01001148 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001149
1150 break;
pbosda903ea2015-10-02 02:36:56 -07001151 case RtcpMode::kReducedSize:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001152 if (!has_report_block)
Peter Boström5811a392015-12-10 13:02:50 +01001153 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001154 break;
pbosda903ea2015-10-02 02:36:56 -07001155 case RtcpMode::kOff:
1156 RTC_NOTREACHED();
1157 break;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001158 }
1159
1160 return SEND_PACKET;
1161 }
1162
stefanff483612015-12-21 03:14:00 -08001163 void ModifyVideoConfigs(
1164 VideoSendStream::Config* send_config,
1165 std::vector<VideoReceiveStream::Config>* receive_configs,
1166 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001167 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001168 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
1169 (*receive_configs)[0].rtp.rtcp_mode = rtcp_mode_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001170 }
1171
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001172 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001173 EXPECT_TRUE(Wait())
pbosda903ea2015-10-02 02:36:56 -07001174 << (rtcp_mode_ == RtcpMode::kCompound
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001175 ? "Timed out before observing enough compound packets."
1176 : "Timed out before receiving a non-compound RTCP packet.");
1177 }
1178
pbosda903ea2015-10-02 02:36:56 -07001179 RtcpMode rtcp_mode_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001180 int sent_rtp_;
1181 int sent_rtcp_;
1182 } test(rtcp_mode);
1183
stefane74eef12016-01-08 06:47:13 -08001184 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001185}
1186
1187TEST_F(EndToEndTest, UsesRtcpCompoundMode) {
pbosda903ea2015-10-02 02:36:56 -07001188 RespectsRtcpMode(RtcpMode::kCompound);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001189}
1190
1191TEST_F(EndToEndTest, UsesRtcpReducedSizeMode) {
pbosda903ea2015-10-02 02:36:56 -07001192 RespectsRtcpMode(RtcpMode::kReducedSize);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001193}
1194
1195// Test sets up a Call multiple senders with different resolutions and SSRCs.
1196// Another is set up to receive all three of these with different renderers.
sprang867fb522015-08-03 04:38:41 -07001197class MultiStreamTest {
1198 public:
1199 static const size_t kNumStreams = 3;
1200 struct CodecSettings {
1201 uint32_t ssrc;
1202 int width;
1203 int height;
1204 } codec_settings[kNumStreams];
1205
1206 MultiStreamTest() {
1207 // TODO(sprang): Cleanup when msvc supports explicit initializers for array.
1208 codec_settings[0] = {1, 640, 480};
1209 codec_settings[1] = {2, 320, 240};
1210 codec_settings[2] = {3, 240, 160};
1211 }
1212
1213 virtual ~MultiStreamTest() {}
1214
1215 void RunTest() {
solenberg4fbae2b2015-08-28 04:07:10 -07001216 rtc::scoped_ptr<Call> sender_call(Call::Create(Call::Config()));
1217 rtc::scoped_ptr<Call> receiver_call(Call::Create(Call::Config()));
stefanf116bd02015-10-27 08:29:42 -07001218 rtc::scoped_ptr<test::DirectTransport> sender_transport(
1219 CreateSendTransport(sender_call.get()));
1220 rtc::scoped_ptr<test::DirectTransport> receiver_transport(
1221 CreateReceiveTransport(receiver_call.get()));
sprang867fb522015-08-03 04:38:41 -07001222 sender_transport->SetReceiver(receiver_call->Receiver());
1223 receiver_transport->SetReceiver(sender_call->Receiver());
1224
1225 rtc::scoped_ptr<VideoEncoder> encoders[kNumStreams];
1226 for (size_t i = 0; i < kNumStreams; ++i)
1227 encoders[i].reset(VideoEncoder::Create(VideoEncoder::kVp8));
1228
1229 VideoSendStream* send_streams[kNumStreams];
1230 VideoReceiveStream* receive_streams[kNumStreams];
1231
1232 test::FrameGeneratorCapturer* frame_generators[kNumStreams];
1233 ScopedVector<VideoDecoder> allocated_decoders;
1234 for (size_t i = 0; i < kNumStreams; ++i) {
1235 uint32_t ssrc = codec_settings[i].ssrc;
1236 int width = codec_settings[i].width;
1237 int height = codec_settings[i].height;
1238
solenberg4fbae2b2015-08-28 04:07:10 -07001239 VideoSendStream::Config send_config(sender_transport.get());
sprang867fb522015-08-03 04:38:41 -07001240 send_config.rtp.ssrcs.push_back(ssrc);
1241 send_config.encoder_settings.encoder = encoders[i].get();
1242 send_config.encoder_settings.payload_name = "VP8";
1243 send_config.encoder_settings.payload_type = 124;
1244 VideoEncoderConfig encoder_config;
1245 encoder_config.streams = test::CreateVideoStreams(1);
1246 VideoStream* stream = &encoder_config.streams[0];
1247 stream->width = width;
1248 stream->height = height;
1249 stream->max_framerate = 5;
1250 stream->min_bitrate_bps = stream->target_bitrate_bps =
1251 stream->max_bitrate_bps = 100000;
1252
1253 UpdateSendConfig(i, &send_config, &encoder_config, &frame_generators[i]);
1254
1255 send_streams[i] =
1256 sender_call->CreateVideoSendStream(send_config, encoder_config);
1257 send_streams[i]->Start();
1258
solenberg4fbae2b2015-08-28 04:07:10 -07001259 VideoReceiveStream::Config receive_config(receiver_transport.get());
sprang867fb522015-08-03 04:38:41 -07001260 receive_config.rtp.remote_ssrc = ssrc;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001261 receive_config.rtp.local_ssrc = test::CallTest::kReceiverLocalVideoSsrc;
sprang867fb522015-08-03 04:38:41 -07001262 VideoReceiveStream::Decoder decoder =
1263 test::CreateMatchingDecoder(send_config.encoder_settings);
1264 allocated_decoders.push_back(decoder.decoder);
1265 receive_config.decoders.push_back(decoder);
1266
1267 UpdateReceiveConfig(i, &receive_config);
1268
1269 receive_streams[i] =
1270 receiver_call->CreateVideoReceiveStream(receive_config);
1271 receive_streams[i]->Start();
1272
1273 frame_generators[i] = test::FrameGeneratorCapturer::Create(
1274 send_streams[i]->Input(), width, height, 30,
1275 Clock::GetRealTimeClock());
1276 frame_generators[i]->Start();
1277 }
1278
1279 Wait();
1280
1281 for (size_t i = 0; i < kNumStreams; ++i) {
1282 frame_generators[i]->Stop();
1283 sender_call->DestroyVideoSendStream(send_streams[i]);
1284 receiver_call->DestroyVideoReceiveStream(receive_streams[i]);
1285 delete frame_generators[i];
1286 }
1287
1288 sender_transport->StopSending();
1289 receiver_transport->StopSending();
1290 }
1291
1292 protected:
1293 virtual void Wait() = 0;
1294 // Note: frame_generator is a point-to-pointer, since the actual instance
1295 // hasn't been created at the time of this call. Only when packets/frames
1296 // start flowing should this be dereferenced.
1297 virtual void UpdateSendConfig(
1298 size_t stream_index,
1299 VideoSendStream::Config* send_config,
1300 VideoEncoderConfig* encoder_config,
1301 test::FrameGeneratorCapturer** frame_generator) {}
1302 virtual void UpdateReceiveConfig(size_t stream_index,
1303 VideoReceiveStream::Config* receive_config) {
1304 }
stefanf116bd02015-10-27 08:29:42 -07001305 virtual test::DirectTransport* CreateSendTransport(Call* sender_call) {
1306 return new test::DirectTransport(sender_call);
sprang867fb522015-08-03 04:38:41 -07001307 }
stefanf116bd02015-10-27 08:29:42 -07001308 virtual test::DirectTransport* CreateReceiveTransport(Call* receiver_call) {
1309 return new test::DirectTransport(receiver_call);
sprang867fb522015-08-03 04:38:41 -07001310 }
1311};
1312
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001313// Each renderer verifies that it receives the expected resolution, and as soon
1314// as every renderer has received a frame, the test finishes.
andresp@webrtc.org02686112014-09-19 08:24:19 +00001315TEST_F(EndToEndTest, SendsAndReceivesMultipleStreams) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001316 class VideoOutputObserver : public VideoRenderer {
1317 public:
sprang867fb522015-08-03 04:38:41 -07001318 VideoOutputObserver(const MultiStreamTest::CodecSettings& settings,
1319 uint32_t ssrc,
1320 test::FrameGeneratorCapturer** frame_generator)
1321 : settings_(settings),
1322 ssrc_(ssrc),
1323 frame_generator_(frame_generator),
Peter Boström5811a392015-12-10 13:02:50 +01001324 done_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001325
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001326 void RenderFrame(const VideoFrame& video_frame,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001327 int time_to_render_ms) override {
sprang867fb522015-08-03 04:38:41 -07001328 EXPECT_EQ(settings_.width, video_frame.width());
1329 EXPECT_EQ(settings_.height, video_frame.height());
1330 (*frame_generator_)->Stop();
Peter Boström5811a392015-12-10 13:02:50 +01001331 done_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001332 }
1333
sprang867fb522015-08-03 04:38:41 -07001334 uint32_t Ssrc() { return ssrc_; }
1335
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001336 bool IsTextureSupported() const override { return false; }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00001337
Peter Boström5811a392015-12-10 13:02:50 +01001338 bool Wait() { return done_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001339
1340 private:
sprang867fb522015-08-03 04:38:41 -07001341 const MultiStreamTest::CodecSettings& settings_;
1342 const uint32_t ssrc_;
1343 test::FrameGeneratorCapturer** const frame_generator_;
Peter Boström5811a392015-12-10 13:02:50 +01001344 rtc::Event done_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001345 };
1346
sprang867fb522015-08-03 04:38:41 -07001347 class Tester : public MultiStreamTest {
1348 public:
1349 Tester() {}
1350 virtual ~Tester() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001351
sprang867fb522015-08-03 04:38:41 -07001352 protected:
1353 void Wait() override {
1354 for (const auto& observer : observers_) {
Peter Boström5811a392015-12-10 13:02:50 +01001355 EXPECT_TRUE(observer->Wait()) << "Time out waiting for from on ssrc "
1356 << observer->Ssrc();
sprang867fb522015-08-03 04:38:41 -07001357 }
1358 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001359
sprang867fb522015-08-03 04:38:41 -07001360 void UpdateSendConfig(
1361 size_t stream_index,
1362 VideoSendStream::Config* send_config,
1363 VideoEncoderConfig* encoder_config,
1364 test::FrameGeneratorCapturer** frame_generator) override {
1365 observers_[stream_index].reset(new VideoOutputObserver(
1366 codec_settings[stream_index], send_config->rtp.ssrcs.front(),
1367 frame_generator));
1368 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001369
sprang867fb522015-08-03 04:38:41 -07001370 void UpdateReceiveConfig(
1371 size_t stream_index,
1372 VideoReceiveStream::Config* receive_config) override {
1373 receive_config->renderer = observers_[stream_index].get();
1374 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001375
sprang867fb522015-08-03 04:38:41 -07001376 private:
1377 rtc::scoped_ptr<VideoOutputObserver> observers_[kNumStreams];
1378 } tester;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001379
sprang867fb522015-08-03 04:38:41 -07001380 tester.RunTest();
1381}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001382
sprang867fb522015-08-03 04:38:41 -07001383TEST_F(EndToEndTest, AssignsTransportSequenceNumbers) {
sprang867fb522015-08-03 04:38:41 -07001384 static const int kExtensionId = 5;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001385
sprang867fb522015-08-03 04:38:41 -07001386 class RtpExtensionHeaderObserver : public test::DirectTransport {
1387 public:
stefanf116bd02015-10-27 08:29:42 -07001388 RtpExtensionHeaderObserver(Call* sender_call,
1389 const uint32_t& first_media_ssrc,
sprang861c55e2015-10-16 10:01:21 -07001390 const std::map<uint32_t, uint32_t>& ssrc_map)
stefanf116bd02015-10-27 08:29:42 -07001391 : DirectTransport(sender_call),
Peter Boström5811a392015-12-10 13:02:50 +01001392 done_(false, false),
sprang867fb522015-08-03 04:38:41 -07001393 parser_(RtpHeaderParser::Create()),
sprang861c55e2015-10-16 10:01:21 -07001394 first_media_ssrc_(first_media_ssrc),
1395 rtx_to_media_ssrcs_(ssrc_map),
sprang867fb522015-08-03 04:38:41 -07001396 padding_observed_(false),
sprang861c55e2015-10-16 10:01:21 -07001397 rtx_padding_observed_(false),
1398 retransmit_observed_(false),
1399 started_(false) {
sprang867fb522015-08-03 04:38:41 -07001400 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
1401 kExtensionId);
1402 }
1403 virtual ~RtpExtensionHeaderObserver() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001404
stefan1d8a5062015-10-02 03:39:33 -07001405 bool SendRtp(const uint8_t* data,
1406 size_t length,
1407 const PacketOptions& options) override {
sprang861c55e2015-10-16 10:01:21 -07001408 {
1409 rtc::CritScope cs(&lock_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001410
Erik Språng8d629712015-08-04 16:24:03 +02001411 if (IsDone())
sprang861c55e2015-10-16 10:01:21 -07001412 return false;
1413
1414 if (started_) {
1415 RTPHeader header;
1416 EXPECT_TRUE(parser_->Parse(data, length, &header));
1417 bool drop_packet = false;
1418
1419 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
1420 EXPECT_EQ(options.packet_id,
1421 header.extension.transportSequenceNumber);
1422 if (!streams_observed_.empty()) {
1423 // Unwrap packet id and verify uniqueness.
1424 int64_t packet_id = unwrapper_.Unwrap(options.packet_id);
1425 EXPECT_TRUE(received_packed_ids_.insert(packet_id).second);
1426 }
1427
1428 // Drop (up to) every 17th packet, so we get retransmits.
1429 // Only drop media, and not on the first stream (otherwise it will be
1430 // hard to distinguish from padding, which is always sent on the first
1431 // stream).
1432 if (header.payloadType != kSendRtxPayloadType &&
1433 header.ssrc != first_media_ssrc_ &&
1434 header.extension.transportSequenceNumber % 17 == 0) {
1435 dropped_seq_[header.ssrc].insert(header.sequenceNumber);
1436 drop_packet = true;
1437 }
1438
1439 size_t payload_length =
1440 length - (header.headerLength + header.paddingLength);
1441 if (payload_length == 0) {
1442 padding_observed_ = true;
1443 } else if (header.payloadType == kSendRtxPayloadType) {
1444 uint16_t original_sequence_number =
1445 ByteReader<uint16_t>::ReadBigEndian(&data[header.headerLength]);
1446 uint32_t original_ssrc =
1447 rtx_to_media_ssrcs_.find(header.ssrc)->second;
1448 std::set<uint16_t>* seq_no_map = &dropped_seq_[original_ssrc];
1449 auto it = seq_no_map->find(original_sequence_number);
1450 if (it != seq_no_map->end()) {
1451 retransmit_observed_ = true;
1452 seq_no_map->erase(it);
1453 } else {
1454 rtx_padding_observed_ = true;
1455 }
1456 } else {
1457 streams_observed_.insert(header.ssrc);
1458 }
1459
1460 if (IsDone())
Peter Boström5811a392015-12-10 13:02:50 +01001461 done_.Set();
sprang861c55e2015-10-16 10:01:21 -07001462
1463 if (drop_packet)
1464 return true;
1465 }
sprang867fb522015-08-03 04:38:41 -07001466 }
sprang861c55e2015-10-16 10:01:21 -07001467
stefan1d8a5062015-10-02 03:39:33 -07001468 return test::DirectTransport::SendRtp(data, length, options);
sprang867fb522015-08-03 04:38:41 -07001469 }
1470
Erik Språng8d629712015-08-04 16:24:03 +02001471 bool IsDone() {
sprang861c55e2015-10-16 10:01:21 -07001472 bool observed_types_ok =
1473 streams_observed_.size() == MultiStreamTest::kNumStreams &&
1474 padding_observed_ && retransmit_observed_ && rtx_padding_observed_;
1475 if (!observed_types_ok)
1476 return false;
1477 // We should not have any gaps in the sequence number range.
1478 size_t seqno_range =
1479 *received_packed_ids_.rbegin() - *received_packed_ids_.begin() + 1;
1480 return seqno_range == received_packed_ids_.size();
Erik Språng8d629712015-08-04 16:24:03 +02001481 }
1482
Peter Boström5811a392015-12-10 13:02:50 +01001483 bool Wait() {
sprang861c55e2015-10-16 10:01:21 -07001484 {
1485 // Can't be sure until this point that rtx_to_media_ssrcs_ etc have
1486 // been initialized and are OK to read.
1487 rtc::CritScope cs(&lock_);
1488 started_ = true;
1489 }
Peter Boström5811a392015-12-10 13:02:50 +01001490 return done_.Wait(kDefaultTimeoutMs);
sprang861c55e2015-10-16 10:01:21 -07001491 }
sprang867fb522015-08-03 04:38:41 -07001492
sprang861c55e2015-10-16 10:01:21 -07001493 rtc::CriticalSection lock_;
Peter Boström5811a392015-12-10 13:02:50 +01001494 rtc::Event done_;
sprang867fb522015-08-03 04:38:41 -07001495 rtc::scoped_ptr<RtpHeaderParser> parser_;
sprang861c55e2015-10-16 10:01:21 -07001496 SequenceNumberUnwrapper unwrapper_;
1497 std::set<int64_t> received_packed_ids_;
sprang867fb522015-08-03 04:38:41 -07001498 std::set<uint32_t> streams_observed_;
sprang861c55e2015-10-16 10:01:21 -07001499 std::map<uint32_t, std::set<uint16_t>> dropped_seq_;
1500 const uint32_t& first_media_ssrc_;
1501 const std::map<uint32_t, uint32_t>& rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001502 bool padding_observed_;
1503 bool rtx_padding_observed_;
sprang861c55e2015-10-16 10:01:21 -07001504 bool retransmit_observed_;
1505 bool started_;
sprang867fb522015-08-03 04:38:41 -07001506 };
1507
1508 class TransportSequenceNumberTester : public MultiStreamTest {
1509 public:
sprang861c55e2015-10-16 10:01:21 -07001510 TransportSequenceNumberTester()
1511 : first_media_ssrc_(0), observer_(nullptr) {}
sprang867fb522015-08-03 04:38:41 -07001512 virtual ~TransportSequenceNumberTester() {}
1513
1514 protected:
1515 void Wait() override {
henrikg91d6ede2015-09-17 00:24:34 -07001516 RTC_DCHECK(observer_ != nullptr);
Peter Boström5811a392015-12-10 13:02:50 +01001517 EXPECT_TRUE(observer_->Wait());
sprang867fb522015-08-03 04:38:41 -07001518 }
1519
1520 void UpdateSendConfig(
1521 size_t stream_index,
1522 VideoSendStream::Config* send_config,
1523 VideoEncoderConfig* encoder_config,
1524 test::FrameGeneratorCapturer** frame_generator) override {
1525 send_config->rtp.extensions.clear();
1526 send_config->rtp.extensions.push_back(
1527 RtpExtension(RtpExtension::kTransportSequenceNumber, kExtensionId));
1528
1529 // Force some padding to be sent.
1530 const int kPaddingBitrateBps = 50000;
1531 int total_target_bitrate = 0;
1532 for (const VideoStream& stream : encoder_config->streams)
1533 total_target_bitrate += stream.target_bitrate_bps;
1534 encoder_config->min_transmit_bitrate_bps =
1535 total_target_bitrate + kPaddingBitrateBps;
1536
1537 // Configure RTX for redundant payload padding.
1538 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang861c55e2015-10-16 10:01:21 -07001539 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[stream_index]);
sprang867fb522015-08-03 04:38:41 -07001540 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
sprang861c55e2015-10-16 10:01:21 -07001541 rtx_to_media_ssrcs_[kSendRtxSsrcs[stream_index]] =
1542 send_config->rtp.ssrcs[0];
1543
1544 if (stream_index == 0)
1545 first_media_ssrc_ = send_config->rtp.ssrcs[0];
sprang867fb522015-08-03 04:38:41 -07001546 }
1547
1548 void UpdateReceiveConfig(
1549 size_t stream_index,
1550 VideoReceiveStream::Config* receive_config) override {
sprang861c55e2015-10-16 10:01:21 -07001551 receive_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang867fb522015-08-03 04:38:41 -07001552 receive_config->rtp.extensions.clear();
1553 receive_config->rtp.extensions.push_back(
1554 RtpExtension(RtpExtension::kTransportSequenceNumber, kExtensionId));
1555 }
1556
stefanf116bd02015-10-27 08:29:42 -07001557 test::DirectTransport* CreateSendTransport(Call* sender_call) override {
1558 observer_ = new RtpExtensionHeaderObserver(sender_call, first_media_ssrc_,
sprang861c55e2015-10-16 10:01:21 -07001559 rtx_to_media_ssrcs_);
sprang867fb522015-08-03 04:38:41 -07001560 return observer_;
1561 }
1562
1563 private:
sprang861c55e2015-10-16 10:01:21 -07001564 uint32_t first_media_ssrc_;
1565 std::map<uint32_t, uint32_t> rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001566 RtpExtensionHeaderObserver* observer_;
1567 } tester;
1568
1569 tester.RunTest();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001570}
1571
Stefan Holmer04cb7632016-01-14 20:34:30 +01001572class TransportFeedbackTester : public test::EndToEndTest {
1573 public:
1574 explicit TransportFeedbackTester(bool feedback_enabled,
1575 size_t num_video_streams,
1576 size_t num_audio_streams)
1577 : EndToEndTest(::webrtc::EndToEndTest::kDefaultTimeoutMs),
1578 feedback_enabled_(feedback_enabled),
1579 num_video_streams_(num_video_streams),
1580 num_audio_streams_(num_audio_streams) {
1581 // Only one stream of each supported for now.
1582 EXPECT_LE(num_video_streams, 1u);
1583 EXPECT_LE(num_audio_streams, 1u);
1584 }
1585
1586 protected:
1587 Action OnSendRtcp(const uint8_t* data, size_t length) override {
1588 EXPECT_FALSE(HasTransportFeedback(data, length));
1589 return SEND_PACKET;
1590 }
1591
1592 Action OnReceiveRtcp(const uint8_t* data, size_t length) override {
1593 if (HasTransportFeedback(data, length))
1594 observation_complete_.Set();
1595 return SEND_PACKET;
1596 }
1597
1598 bool HasTransportFeedback(const uint8_t* data, size_t length) const {
1599 RTCPUtility::RTCPParserV2 parser(data, length, true);
1600 EXPECT_TRUE(parser.IsValid());
1601
1602 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
1603 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
1604 if (packet_type == RTCPUtility::RTCPPacketTypes::kTransportFeedback)
1605 return true;
1606 packet_type = parser.Iterate();
1607 }
1608
1609 return false;
1610 }
1611
1612 void PerformTest() override {
1613 const int64_t kDisabledFeedbackTimeoutMs = 5000;
1614 EXPECT_EQ(feedback_enabled_,
1615 observation_complete_.Wait(feedback_enabled_
1616 ? test::CallTest::kDefaultTimeoutMs
1617 : kDisabledFeedbackTimeoutMs));
1618 }
1619
1620 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
1621 receiver_call_ = receiver_call;
1622 }
1623
1624 size_t GetNumVideoStreams() const override { return num_video_streams_; }
1625 size_t GetNumAudioStreams() const override { return num_audio_streams_; }
1626
1627 void ModifyVideoConfigs(
1628 VideoSendStream::Config* send_config,
1629 std::vector<VideoReceiveStream::Config>* receive_configs,
1630 VideoEncoderConfig* encoder_config) override {
1631 send_config->rtp.extensions.clear();
1632 send_config->rtp.extensions.push_back(
1633 RtpExtension(RtpExtension::kTransportSequenceNumber, kExtensionId));
1634 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1635 (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
1636 }
1637
1638 void ModifyAudioConfigs(
1639 AudioSendStream::Config* send_config,
1640 std::vector<AudioReceiveStream::Config>* receive_configs) override {
1641 send_config->rtp.extensions.clear();
1642 send_config->rtp.extensions.push_back(
1643 RtpExtension(RtpExtension::kTransportSequenceNumber, kExtensionId));
1644 (*receive_configs)[0].rtp.extensions.clear();
1645 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1646 (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001647 }
1648
1649 private:
Erik Språng6b8d3552015-09-24 15:06:57 +02001650 static const int kExtensionId = 5;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001651 const bool feedback_enabled_;
1652 const size_t num_video_streams_;
1653 const size_t num_audio_streams_;
1654 Call* receiver_call_;
1655};
Erik Språng6b8d3552015-09-24 15:06:57 +02001656
Stefan Holmer04cb7632016-01-14 20:34:30 +01001657TEST_F(EndToEndTest, VideoReceivesTransportFeedback) {
1658 TransportFeedbackTester test(true, 1, 0);
1659 RunBaseTest(&test);
Erik Språng6b8d3552015-09-24 15:06:57 +02001660}
stefan43edf0f2015-11-20 18:05:48 -08001661
Stefan Holmer04cb7632016-01-14 20:34:30 +01001662TEST_F(EndToEndTest, VideoTransportFeedbackNotConfigured) {
1663 TransportFeedbackTester test(false, 1, 0);
1664 RunBaseTest(&test);
stefan43edf0f2015-11-20 18:05:48 -08001665}
1666
Stefan Holmer04cb7632016-01-14 20:34:30 +01001667TEST_F(EndToEndTest, AudioReceivesTransportFeedback) {
1668 TransportFeedbackTester test(true, 0, 1);
1669 RunBaseTest(&test);
1670}
1671
1672TEST_F(EndToEndTest, AudioTransportFeedbackNotConfigured) {
1673 TransportFeedbackTester test(false, 0, 1);
1674 RunBaseTest(&test);
1675}
1676
1677TEST_F(EndToEndTest, AudioVideoReceivesTransportFeedback) {
1678 TransportFeedbackTester test(true, 1, 1);
1679 RunBaseTest(&test);
stefan43edf0f2015-11-20 18:05:48 -08001680}
1681
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001682TEST_F(EndToEndTest, ObserversEncodedFrames) {
1683 class EncodedFrameTestObserver : public EncodedFrameObserver {
1684 public:
1685 EncodedFrameTestObserver()
Peter Boström5811a392015-12-10 13:02:50 +01001686 : length_(0), frame_type_(kEmptyFrame), called_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001687 virtual ~EncodedFrameTestObserver() {}
1688
1689 virtual void EncodedFrameCallback(const EncodedFrame& encoded_frame) {
1690 frame_type_ = encoded_frame.frame_type_;
1691 length_ = encoded_frame.length_;
1692 buffer_.reset(new uint8_t[length_]);
1693 memcpy(buffer_.get(), encoded_frame.data_, length_);
Peter Boström5811a392015-12-10 13:02:50 +01001694 called_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001695 }
1696
Peter Boström5811a392015-12-10 13:02:50 +01001697 bool Wait() { return called_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001698
1699 void ExpectEqualFrames(const EncodedFrameTestObserver& observer) {
1700 ASSERT_EQ(length_, observer.length_)
1701 << "Observed frames are of different lengths.";
1702 EXPECT_EQ(frame_type_, observer.frame_type_)
1703 << "Observed frames have different frame types.";
1704 EXPECT_EQ(0, memcmp(buffer_.get(), observer.buffer_.get(), length_))
1705 << "Observed encoded frames have different content.";
1706 }
1707
1708 private:
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00001709 rtc::scoped_ptr<uint8_t[]> buffer_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001710 size_t length_;
1711 FrameType frame_type_;
Peter Boström5811a392015-12-10 13:02:50 +01001712 rtc::Event called_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001713 };
1714
1715 EncodedFrameTestObserver post_encode_observer;
1716 EncodedFrameTestObserver pre_decode_observer;
1717
solenberg4fbae2b2015-08-28 04:07:10 -07001718 CreateCalls(Call::Config(), Call::Config());
1719
stefanf116bd02015-10-27 08:29:42 -07001720 test::DirectTransport sender_transport(sender_call_.get());
1721 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001722 sender_transport.SetReceiver(receiver_call_->Receiver());
1723 receiver_transport.SetReceiver(sender_call_->Receiver());
1724
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001725 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07001726 CreateMatchingReceiveConfigs(&receiver_transport);
stefanff483612015-12-21 03:14:00 -08001727 video_send_config_.post_encode_callback = &post_encode_observer;
1728 video_receive_configs_[0].pre_decode_callback = &pre_decode_observer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001729
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001730 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001731 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001732
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00001733 rtc::scoped_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +00001734 test::FrameGenerator::CreateChromaGenerator(
stefanff483612015-12-21 03:14:00 -08001735 video_encoder_config_.streams[0].width,
1736 video_encoder_config_.streams[0].height));
1737 video_send_stream_->Input()->IncomingCapturedFrame(
1738 *frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001739
Peter Boström5811a392015-12-10 13:02:50 +01001740 EXPECT_TRUE(post_encode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001741 << "Timed out while waiting for send-side encoded-frame callback.";
1742
Peter Boström5811a392015-12-10 13:02:50 +01001743 EXPECT_TRUE(pre_decode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001744 << "Timed out while waiting for pre-decode encoded-frame callback.";
1745
1746 post_encode_observer.ExpectEqualFrames(pre_decode_observer);
1747
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001748 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001749
1750 sender_transport.StopSending();
1751 receiver_transport.StopSending();
1752
1753 DestroyStreams();
1754}
1755
1756TEST_F(EndToEndTest, ReceiveStreamSendsRemb) {
1757 class RembObserver : public test::EndToEndTest {
1758 public:
1759 RembObserver() : EndToEndTest(kDefaultTimeoutMs) {}
1760
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001761 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001762 RTCPUtility::RTCPParserV2 parser(packet, length, true);
1763 EXPECT_TRUE(parser.IsValid());
1764
1765 bool received_psfb = false;
1766 bool received_remb = false;
1767 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02001768 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
1769 if (packet_type == RTCPUtility::RTCPPacketTypes::kPsfbRemb) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001770 const RTCPUtility::RTCPPacket& packet = parser.Packet();
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001771 EXPECT_EQ(packet.PSFBAPP.SenderSSRC, kReceiverLocalVideoSsrc);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001772 received_psfb = true;
Erik Språng242e22b2015-05-11 10:17:43 +02001773 } else if (packet_type == RTCPUtility::RTCPPacketTypes::kPsfbRembItem) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001774 const RTCPUtility::RTCPPacket& packet = parser.Packet();
1775 EXPECT_GT(packet.REMBItem.BitRate, 0u);
1776 EXPECT_EQ(packet.REMBItem.NumberOfSSRCs, 1u);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001777 EXPECT_EQ(packet.REMBItem.SSRCs[0], kVideoSendSsrcs[0]);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001778 received_remb = true;
1779 }
1780 packet_type = parser.Iterate();
1781 }
1782 if (received_psfb && received_remb)
Peter Boström5811a392015-12-10 13:02:50 +01001783 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001784 return SEND_PACKET;
1785 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001786 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001787 EXPECT_TRUE(Wait()) << "Timed out while waiting for a "
1788 "receiver RTCP REMB packet to be "
1789 "sent.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001790 }
1791 } test;
1792
stefane74eef12016-01-08 06:47:13 -08001793 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001794}
1795
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001796TEST_F(EndToEndTest, VerifyBandwidthStats) {
stefanf116bd02015-10-27 08:29:42 -07001797 class RtcpObserver : public test::EndToEndTest {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001798 public:
1799 RtcpObserver()
1800 : EndToEndTest(kDefaultTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00001801 sender_call_(nullptr),
1802 receiver_call_(nullptr),
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001803 has_seen_pacer_delay_(false) {}
1804
stefanf116bd02015-10-27 08:29:42 -07001805 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001806 Call::Stats sender_stats = sender_call_->GetStats();
1807 Call::Stats receiver_stats = receiver_call_->GetStats();
1808 if (!has_seen_pacer_delay_)
1809 has_seen_pacer_delay_ = sender_stats.pacer_delay_ms > 0;
1810 if (sender_stats.send_bandwidth_bps > 0 &&
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00001811 receiver_stats.recv_bandwidth_bps > 0 && has_seen_pacer_delay_) {
Peter Boström5811a392015-12-10 13:02:50 +01001812 observation_complete_.Set();
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00001813 }
stefanf116bd02015-10-27 08:29:42 -07001814 return SEND_PACKET;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001815 }
1816
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001817 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001818 sender_call_ = sender_call;
1819 receiver_call_ = receiver_call;
1820 }
1821
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001822 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001823 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
1824 "non-zero bandwidth stats.";
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001825 }
1826
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001827 private:
1828 Call* sender_call_;
1829 Call* receiver_call_;
1830 bool has_seen_pacer_delay_;
1831 } test;
1832
stefane74eef12016-01-08 06:47:13 -08001833 RunBaseTest(&test);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001834}
1835
stefan32f81542016-01-20 07:13:58 -08001836
1837// Verifies that it's possible to limit the send BWE by sending a REMB.
1838// This is verified by allowing the send BWE to ramp-up to >1000 kbps,
1839// then have the test generate a REMB of 500 kbps and verify that the send BWE
1840// is reduced to exactly 500 kbps. Then a REMB of 1000 kbps is generated and the
1841// test verifies that the send BWE ramps back up to exactly 1000 kbps.
1842TEST_F(EndToEndTest, RembWithSendSideBwe) {
1843 class BweObserver : public test::EndToEndTest {
1844 public:
1845 BweObserver()
1846 : EndToEndTest(kDefaultTimeoutMs),
1847 sender_call_(nullptr),
1848 clock_(Clock::GetRealTimeClock()),
1849 sender_ssrc_(0),
1850 remb_bitrate_bps_(1000000),
1851 receive_transport_(nullptr),
1852 event_(false, false),
1853 poller_thread_(&BitrateStatsPollingThread,
1854 this,
1855 "BitrateStatsPollingThread"),
1856 state_(kWaitForFirstRampUp) {}
1857
1858 ~BweObserver() {}
1859
1860 test::PacketTransport* CreateReceiveTransport() {
1861 receive_transport_ = new test::PacketTransport(
1862 nullptr, this, test::PacketTransport::kReceiver,
1863 FakeNetworkPipe::Config());
1864 return receive_transport_;
1865 }
1866
1867 Call::Config GetSenderCallConfig() override {
1868 Call::Config config;
1869 // Set a high start bitrate to reduce the test completion time.
1870 config.bitrate_config.start_bitrate_bps = remb_bitrate_bps_;
1871 return config;
1872 }
1873
1874 void ModifyVideoConfigs(
1875 VideoSendStream::Config* send_config,
1876 std::vector<VideoReceiveStream::Config>* receive_configs,
1877 VideoEncoderConfig* encoder_config) override {
1878 ASSERT_EQ(1u, send_config->rtp.ssrcs.size());
1879 send_config->rtp.extensions.clear();
1880 send_config->rtp.extensions.push_back(
1881 RtpExtension(RtpExtension::kTransportSequenceNumber,
1882 test::kTransportSequenceNumberExtensionId));
1883 sender_ssrc_ = send_config->rtp.ssrcs[0];
1884
1885 encoder_config->streams[0].max_bitrate_bps =
1886 encoder_config->streams[0].target_bitrate_bps = 2000000;
1887
1888 ASSERT_EQ(1u, receive_configs->size());
1889 (*receive_configs)[0].rtp.remb = false;
1890 (*receive_configs)[0].rtp.transport_cc = true;
1891 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1892 RtpRtcp::Configuration config;
1893 config.receiver_only = true;
1894 config.clock = clock_;
1895 config.outgoing_transport = receive_transport_;
1896 rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(config));
1897 rtp_rtcp_->SetRemoteSSRC((*receive_configs)[0].rtp.remote_ssrc);
1898 rtp_rtcp_->SetSSRC((*receive_configs)[0].rtp.local_ssrc);
1899 rtp_rtcp_->SetREMBStatus(true);
1900 rtp_rtcp_->SetSendingStatus(true);
1901 rtp_rtcp_->SetRTCPStatus(RtcpMode::kReducedSize);
1902 }
1903
1904 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
1905 sender_call_ = sender_call;
1906 }
1907
1908 static bool BitrateStatsPollingThread(void* obj) {
1909 return static_cast<BweObserver*>(obj)->PollStats();
1910 }
1911
1912 bool PollStats() {
1913 if (sender_call_) {
1914 Call::Stats stats = sender_call_->GetStats();
1915 switch (state_) {
1916 case kWaitForFirstRampUp:
1917 if (stats.send_bandwidth_bps >= remb_bitrate_bps_) {
1918 state_ = kWaitForRemb;
1919 remb_bitrate_bps_ /= 2;
1920 rtp_rtcp_->SetREMBData(
1921 remb_bitrate_bps_,
1922 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
1923 rtp_rtcp_->SendRTCP(kRtcpRr);
1924 }
1925 break;
1926
1927 case kWaitForRemb:
1928 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
1929 state_ = kWaitForSecondRampUp;
1930 remb_bitrate_bps_ *= 2;
1931 rtp_rtcp_->SetREMBData(
1932 remb_bitrate_bps_,
1933 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
1934 rtp_rtcp_->SendRTCP(kRtcpRr);
1935 }
1936 break;
1937
1938 case kWaitForSecondRampUp:
1939 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
1940 observation_complete_.Set();
1941 }
1942 break;
1943 }
1944 }
1945
1946 return !event_.Wait(1000);
1947 }
1948
1949 void PerformTest() override {
1950 poller_thread_.Start();
1951 EXPECT_TRUE(Wait())
1952 << "Timed out while waiting for bitrate to change according to REMB.";
1953 poller_thread_.Stop();
1954 }
1955
1956 private:
1957 enum TestState { kWaitForFirstRampUp, kWaitForRemb, kWaitForSecondRampUp };
1958
1959 Call* sender_call_;
1960 Clock* const clock_;
1961 uint32_t sender_ssrc_;
1962 int remb_bitrate_bps_;
1963 rtc::scoped_ptr<RtpRtcp> rtp_rtcp_;
1964 test::PacketTransport* receive_transport_;
1965 rtc::Event event_;
1966 rtc::PlatformThread poller_thread_;
1967 TestState state_;
1968 } test;
1969
1970 RunBaseTest(&test);
1971}
1972
Åsa Persson352b2d72015-04-15 18:00:40 +02001973TEST_F(EndToEndTest, VerifyNackStats) {
1974 static const int kPacketNumberToDrop = 200;
1975 class NackObserver : public test::EndToEndTest {
1976 public:
1977 NackObserver()
1978 : EndToEndTest(kLongTimeoutMs),
1979 sent_rtp_packets_(0),
1980 dropped_rtp_packet_(0),
1981 dropped_rtp_packet_requested_(false),
1982 send_stream_(nullptr),
1983 start_runtime_ms_(-1) {}
1984
1985 private:
1986 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08001987 rtc::CritScope lock(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02001988 if (++sent_rtp_packets_ == kPacketNumberToDrop) {
1989 rtc::scoped_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
1990 RTPHeader header;
1991 EXPECT_TRUE(parser->Parse(packet, length, &header));
1992 dropped_rtp_packet_ = header.sequenceNumber;
1993 return DROP_PACKET;
1994 }
1995 VerifyStats();
1996 return SEND_PACKET;
1997 }
1998
1999 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002000 rtc::CritScope lock(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02002001 test::RtcpPacketParser rtcp_parser;
2002 rtcp_parser.Parse(packet, length);
2003 std::vector<uint16_t> nacks = rtcp_parser.nack_item()->last_nack_list();
2004 if (!nacks.empty() && std::find(
2005 nacks.begin(), nacks.end(), dropped_rtp_packet_) != nacks.end()) {
2006 dropped_rtp_packet_requested_ = true;
2007 }
2008 return SEND_PACKET;
2009 }
2010
stefan608213e2015-11-01 14:56:10 -08002011 void VerifyStats() EXCLUSIVE_LOCKS_REQUIRED(&crit_) {
Åsa Persson352b2d72015-04-15 18:00:40 +02002012 if (!dropped_rtp_packet_requested_)
2013 return;
2014 int send_stream_nack_packets = 0;
2015 int receive_stream_nack_packets = 0;
2016 VideoSendStream::Stats stats = send_stream_->GetStats();
2017 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
2018 stats.substreams.begin(); it != stats.substreams.end(); ++it) {
2019 const VideoSendStream::StreamStats& stream_stats = it->second;
2020 send_stream_nack_packets +=
2021 stream_stats.rtcp_packet_type_counts.nack_packets;
2022 }
2023 for (size_t i = 0; i < receive_streams_.size(); ++i) {
2024 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
2025 receive_stream_nack_packets +=
2026 stats.rtcp_packet_type_counts.nack_packets;
2027 }
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002028 if (send_stream_nack_packets >= 1 && receive_stream_nack_packets >= 1) {
Åsa Persson352b2d72015-04-15 18:00:40 +02002029 // NACK packet sent on receive stream and received on sent stream.
2030 if (MinMetricRunTimePassed())
Peter Boström5811a392015-12-10 13:02:50 +01002031 observation_complete_.Set();
Åsa Persson352b2d72015-04-15 18:00:40 +02002032 }
2033 }
2034
2035 bool MinMetricRunTimePassed() {
2036 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
2037 if (start_runtime_ms_ == -1) {
2038 start_runtime_ms_ = now;
2039 return false;
2040 }
2041 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
2042 return elapsed_sec > metrics::kMinRunTimeInSeconds;
2043 }
2044
stefanff483612015-12-21 03:14:00 -08002045 void ModifyVideoConfigs(
2046 VideoSendStream::Config* send_config,
2047 std::vector<VideoReceiveStream::Config>* receive_configs,
2048 VideoEncoderConfig* encoder_config) override {
Åsa Persson352b2d72015-04-15 18:00:40 +02002049 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2050 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2051 }
2052
stefanff483612015-12-21 03:14:00 -08002053 void OnVideoStreamsCreated(
Åsa Persson352b2d72015-04-15 18:00:40 +02002054 VideoSendStream* send_stream,
2055 const std::vector<VideoReceiveStream*>& receive_streams) override {
2056 send_stream_ = send_stream;
2057 receive_streams_ = receive_streams;
2058 }
2059
2060 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002061 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Åsa Persson352b2d72015-04-15 18:00:40 +02002062 }
2063
stefan608213e2015-11-01 14:56:10 -08002064 rtc::CriticalSection crit_;
Åsa Persson352b2d72015-04-15 18:00:40 +02002065 uint64_t sent_rtp_packets_;
stefan608213e2015-11-01 14:56:10 -08002066 uint16_t dropped_rtp_packet_ GUARDED_BY(&crit_);
2067 bool dropped_rtp_packet_requested_ GUARDED_BY(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02002068 std::vector<VideoReceiveStream*> receive_streams_;
2069 VideoSendStream* send_stream_;
2070 int64_t start_runtime_ms_;
2071 } test;
2072
Åsa Persson3c391cb2015-04-27 10:09:49 +02002073 test::ClearHistograms();
stefane74eef12016-01-08 06:47:13 -08002074 RunBaseTest(&test);
Åsa Persson352b2d72015-04-15 18:00:40 +02002075
Åsa Persson3c391cb2015-04-27 10:09:49 +02002076 EXPECT_EQ(1, test::NumHistogramSamples(
Åsa Persson352b2d72015-04-15 18:00:40 +02002077 "WebRTC.Video.UniqueNackRequestsSentInPercent"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002078 EXPECT_EQ(1, test::NumHistogramSamples(
Åsa Persson352b2d72015-04-15 18:00:40 +02002079 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
2080 EXPECT_GT(test::LastHistogramSample(
2081 "WebRTC.Video.NackPacketsSentPerMinute"), 0);
2082 EXPECT_GT(test::LastHistogramSample(
2083 "WebRTC.Video.NackPacketsReceivedPerMinute"), 0);
2084}
2085
sprangb4a1ae52015-12-03 08:10:08 -08002086void EndToEndTest::VerifyHistogramStats(bool use_rtx,
2087 bool use_red,
2088 bool screenshare) {
stefanf116bd02015-10-27 08:29:42 -07002089 class StatsObserver : public test::EndToEndTest {
Åsa Persson3c391cb2015-04-27 10:09:49 +02002090 public:
sprangb4a1ae52015-12-03 08:10:08 -08002091 StatsObserver(bool use_rtx, bool use_red, bool screenshare)
Åsa Persson3c391cb2015-04-27 10:09:49 +02002092 : EndToEndTest(kLongTimeoutMs),
2093 use_rtx_(use_rtx),
2094 use_red_(use_red),
sprangb4a1ae52015-12-03 08:10:08 -08002095 screenshare_(screenshare),
Peter Boström39593972016-02-15 11:27:15 +01002096 // This test uses NACK, so to send FEC we can't use a fake encoder.
2097 vp8_encoder_(
2098 use_red ? VideoEncoder::Create(VideoEncoder::EncoderType::kVp8)
2099 : nullptr),
Åsa Persson3c391cb2015-04-27 10:09:49 +02002100 sender_call_(nullptr),
2101 receiver_call_(nullptr),
2102 start_runtime_ms_(-1) {}
2103
2104 private:
2105 Action OnSendRtp(const uint8_t* packet, size_t length) override {
2106 if (MinMetricRunTimePassed())
Peter Boström5811a392015-12-10 13:02:50 +01002107 observation_complete_.Set();
Åsa Persson3c391cb2015-04-27 10:09:49 +02002108
stefanf116bd02015-10-27 08:29:42 -07002109 return SEND_PACKET;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002110 }
2111
2112 bool MinMetricRunTimePassed() {
2113 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
2114 if (start_runtime_ms_ == -1) {
2115 start_runtime_ms_ = now;
2116 return false;
2117 }
2118 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
2119 return elapsed_sec > metrics::kMinRunTimeInSeconds * 2;
2120 }
2121
stefanff483612015-12-21 03:14:00 -08002122 void ModifyVideoConfigs(
2123 VideoSendStream::Config* send_config,
2124 std::vector<VideoReceiveStream::Config>* receive_configs,
2125 VideoEncoderConfig* encoder_config) override {
Åsa Persson3c391cb2015-04-27 10:09:49 +02002126 // NACK
2127 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2128 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2129 // FEC
2130 if (use_red_) {
2131 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
2132 send_config->rtp.fec.red_payload_type = kRedPayloadType;
Peter Boström39593972016-02-15 11:27:15 +01002133 send_config->encoder_settings.encoder = vp8_encoder_.get();
2134 send_config->encoder_settings.payload_name = "VP8";
2135 (*receive_configs)[0].decoders[0].payload_name = "VP8";
Åsa Persson3c391cb2015-04-27 10:09:49 +02002136 (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
2137 (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
2138 }
2139 // RTX
2140 if (use_rtx_) {
2141 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
2142 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002143 (*receive_configs)[0].rtp.rtx[kFakeVideoSendPayloadType].ssrc =
Åsa Persson3c391cb2015-04-27 10:09:49 +02002144 kSendRtxSsrcs[0];
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002145 (*receive_configs)[0].rtp.rtx[kFakeVideoSendPayloadType].payload_type =
Åsa Persson3c391cb2015-04-27 10:09:49 +02002146 kSendRtxPayloadType;
2147 }
sprangb4a1ae52015-12-03 08:10:08 -08002148 encoder_config->content_type =
2149 screenshare_ ? VideoEncoderConfig::ContentType::kScreen
2150 : VideoEncoderConfig::ContentType::kRealtimeVideo;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002151 }
2152
2153 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2154 sender_call_ = sender_call;
2155 receiver_call_ = receiver_call;
2156 }
2157
Åsa Persson3c391cb2015-04-27 10:09:49 +02002158 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002159 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Åsa Persson3c391cb2015-04-27 10:09:49 +02002160 }
2161
sprangb4a1ae52015-12-03 08:10:08 -08002162 const bool use_rtx_;
2163 const bool use_red_;
2164 const bool screenshare_;
Peter Boström39593972016-02-15 11:27:15 +01002165 const rtc::scoped_ptr<VideoEncoder> vp8_encoder_;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002166 Call* sender_call_;
2167 Call* receiver_call_;
2168 int64_t start_runtime_ms_;
sprangb4a1ae52015-12-03 08:10:08 -08002169 } test(use_rtx, use_red, screenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002170
2171 test::ClearHistograms();
stefane74eef12016-01-08 06:47:13 -08002172 RunBaseTest(&test);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002173
stefan91d92602015-11-11 10:13:02 -08002174 // Delete the call for Call stats to be reported.
stefan18adf0a2015-11-17 06:24:56 -08002175 sender_call_.reset();
stefan91d92602015-11-11 10:13:02 -08002176 receiver_call_.reset();
2177
sprangb4a1ae52015-12-03 08:10:08 -08002178 std::string video_prefix =
2179 screenshare ? "WebRTC.Video.Screenshare." : "WebRTC.Video.";
2180
Åsa Persson3c391cb2015-04-27 10:09:49 +02002181 // Verify that stats have been updated once.
stefan91d92602015-11-11 10:13:02 -08002182 EXPECT_EQ(
2183 1, test::NumHistogramSamples("WebRTC.Call.VideoBitrateReceivedInKbps"));
2184 EXPECT_EQ(1,
2185 test::NumHistogramSamples("WebRTC.Call.RtcpBitrateReceivedInBps"));
2186 EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Call.BitrateReceivedInKbps"));
stefan18adf0a2015-11-17 06:24:56 -08002187 EXPECT_EQ(
2188 1, test::NumHistogramSamples("WebRTC.Call.EstimatedSendBitrateInKbps"));
2189 EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Call.PacerBitrateInKbps"));
stefan91d92602015-11-11 10:13:02 -08002190
Åsa Persson3c391cb2015-04-27 10:09:49 +02002191 EXPECT_EQ(1, test::NumHistogramSamples(
2192 "WebRTC.Video.NackPacketsSentPerMinute"));
2193 EXPECT_EQ(1, test::NumHistogramSamples(
2194 "WebRTC.Video.NackPacketsReceivedPerMinute"));
2195 EXPECT_EQ(1, test::NumHistogramSamples(
2196 "WebRTC.Video.FirPacketsSentPerMinute"));
2197 EXPECT_EQ(1, test::NumHistogramSamples(
2198 "WebRTC.Video.FirPacketsReceivedPerMinute"));
2199 EXPECT_EQ(1, test::NumHistogramSamples(
2200 "WebRTC.Video.PliPacketsSentPerMinute"));
2201 EXPECT_EQ(1, test::NumHistogramSamples(
2202 "WebRTC.Video.PliPacketsReceivedPerMinute"));
2203
sprangb4a1ae52015-12-03 08:10:08 -08002204 EXPECT_EQ(
2205 1, test::NumHistogramSamples(video_prefix + "KeyFramesSentInPermille"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002206 EXPECT_EQ(1, test::NumHistogramSamples(
2207 "WebRTC.Video.KeyFramesReceivedInPermille"));
2208
sprange2d83d62016-02-19 09:03:26 -08002209 EXPECT_EQ(
2210 1, test::NumHistogramSamples(video_prefix + "SentPacketsLostInPercent"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002211 EXPECT_EQ(1, test::NumHistogramSamples(
2212 "WebRTC.Video.ReceivedPacketsLostInPercent"));
2213
sprangb4a1ae52015-12-03 08:10:08 -08002214 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "InputWidthInPixels"));
2215 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "InputHeightInPixels"));
2216 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "SentWidthInPixels"));
2217 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "SentHeightInPixels"));
asaperssond89920b2015-07-22 06:52:00 -07002218 EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.ReceivedWidthInPixels"));
2219 EXPECT_EQ(1,
2220 test::NumHistogramSamples("WebRTC.Video.ReceivedHeightInPixels"));
2221
stefanff483612015-12-21 03:14:00 -08002222 EXPECT_EQ(static_cast<int>(video_encoder_config_.streams[0].width),
sprangb4a1ae52015-12-03 08:10:08 -08002223 test::LastHistogramSample(video_prefix + "InputWidthInPixels"));
stefanff483612015-12-21 03:14:00 -08002224 EXPECT_EQ(static_cast<int>(video_encoder_config_.streams[0].height),
sprangb4a1ae52015-12-03 08:10:08 -08002225 test::LastHistogramSample(video_prefix + "InputHeightInPixels"));
stefanff483612015-12-21 03:14:00 -08002226 EXPECT_EQ(static_cast<int>(video_encoder_config_.streams[0].width),
sprangb4a1ae52015-12-03 08:10:08 -08002227 test::LastHistogramSample(video_prefix + "SentWidthInPixels"));
stefanff483612015-12-21 03:14:00 -08002228 EXPECT_EQ(static_cast<int>(video_encoder_config_.streams[0].height),
sprangb4a1ae52015-12-03 08:10:08 -08002229 test::LastHistogramSample(video_prefix + "SentHeightInPixels"));
stefanff483612015-12-21 03:14:00 -08002230 EXPECT_EQ(static_cast<int>(video_encoder_config_.streams[0].width),
asaperssond89920b2015-07-22 06:52:00 -07002231 test::LastHistogramSample("WebRTC.Video.ReceivedWidthInPixels"));
stefanff483612015-12-21 03:14:00 -08002232 EXPECT_EQ(static_cast<int>(video_encoder_config_.streams[0].height),
asaperssond89920b2015-07-22 06:52:00 -07002233 test::LastHistogramSample("WebRTC.Video.ReceivedHeightInPixels"));
2234
sprangb4a1ae52015-12-03 08:10:08 -08002235 EXPECT_EQ(1,
2236 test::NumHistogramSamples(video_prefix + "InputFramesPerSecond"));
2237 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "SentFramesPerSecond"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002238 EXPECT_EQ(1, test::NumHistogramSamples(
2239 "WebRTC.Video.DecodedFramesPerSecond"));
asaperssond89920b2015-07-22 06:52:00 -07002240 EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.RenderFramesPerSecond"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002241
asapersson6f14be82015-11-16 00:40:49 -08002242 EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.OnewayDelayInMs"));
2243 EXPECT_EQ(
2244 1, test::NumHistogramSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
2245
sprangb4a1ae52015-12-03 08:10:08 -08002246 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "EncodeTimeInMs"));
asapersson6718e972015-07-24 00:20:58 -07002247 EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.DecodeTimeInMs"));
2248
Åsa Persson3c391cb2015-04-27 10:09:49 +02002249 EXPECT_EQ(1, test::NumHistogramSamples(
2250 "WebRTC.Video.BitrateSentInKbps"));
2251 EXPECT_EQ(1, test::NumHistogramSamples(
2252 "WebRTC.Video.BitrateReceivedInKbps"));
2253 EXPECT_EQ(1, test::NumHistogramSamples(
2254 "WebRTC.Video.MediaBitrateSentInKbps"));
2255 EXPECT_EQ(1, test::NumHistogramSamples(
2256 "WebRTC.Video.MediaBitrateReceivedInKbps"));
2257 EXPECT_EQ(1, test::NumHistogramSamples(
2258 "WebRTC.Video.PaddingBitrateSentInKbps"));
2259 EXPECT_EQ(1, test::NumHistogramSamples(
2260 "WebRTC.Video.PaddingBitrateReceivedInKbps"));
2261 EXPECT_EQ(1, test::NumHistogramSamples(
2262 "WebRTC.Video.RetransmittedBitrateSentInKbps"));
2263 EXPECT_EQ(1, test::NumHistogramSamples(
2264 "WebRTC.Video.RetransmittedBitrateReceivedInKbps"));
2265
sprangb4a1ae52015-12-03 08:10:08 -08002266 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "SendSideDelayInMs"));
2267 EXPECT_EQ(1,
2268 test::NumHistogramSamples(video_prefix + "SendSideDelayMaxInMs"));
asapersson6f14be82015-11-16 00:40:49 -08002269
Åsa Persson3c391cb2015-04-27 10:09:49 +02002270 int num_rtx_samples = use_rtx ? 1 : 0;
2271 EXPECT_EQ(num_rtx_samples, test::NumHistogramSamples(
2272 "WebRTC.Video.RtxBitrateSentInKbps"));
2273 EXPECT_EQ(num_rtx_samples, test::NumHistogramSamples(
2274 "WebRTC.Video.RtxBitrateReceivedInKbps"));
2275
2276 int num_red_samples = use_red ? 1 : 0;
2277 EXPECT_EQ(num_red_samples, test::NumHistogramSamples(
2278 "WebRTC.Video.FecBitrateSentInKbps"));
2279 EXPECT_EQ(num_red_samples, test::NumHistogramSamples(
2280 "WebRTC.Video.FecBitrateReceivedInKbps"));
2281 EXPECT_EQ(num_red_samples, test::NumHistogramSamples(
2282 "WebRTC.Video.ReceivedFecPacketsInPercent"));
2283}
2284
2285TEST_F(EndToEndTest, VerifyHistogramStatsWithRtx) {
2286 const bool kEnabledRtx = true;
2287 const bool kEnabledRed = false;
sprangb4a1ae52015-12-03 08:10:08 -08002288 const bool kScreenshare = false;
2289 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002290}
2291
2292TEST_F(EndToEndTest, VerifyHistogramStatsWithRed) {
2293 const bool kEnabledRtx = false;
2294 const bool kEnabledRed = true;
sprangb4a1ae52015-12-03 08:10:08 -08002295 const bool kScreenshare = false;
2296 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
2297}
2298
2299TEST_F(EndToEndTest, VerifyHistogramStatsWithScreenshare) {
2300 const bool kEnabledRtx = false;
2301 const bool kEnabledRed = false;
2302 const bool kScreenshare = true;
2303 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002304}
2305
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002306void EndToEndTest::TestXrReceiverReferenceTimeReport(bool enable_rrtr) {
2307 static const int kNumRtcpReportPacketsToObserve = 5;
2308 class RtcpXrObserver : public test::EndToEndTest {
2309 public:
2310 explicit RtcpXrObserver(bool enable_rrtr)
2311 : EndToEndTest(kDefaultTimeoutMs),
2312 enable_rrtr_(enable_rrtr),
2313 sent_rtcp_sr_(0),
2314 sent_rtcp_rr_(0),
2315 sent_rtcp_rrtr_(0),
2316 sent_rtcp_dlrr_(0) {}
2317
2318 private:
2319 // Receive stream should send RR packets (and RRTR packets if enabled).
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002320 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002321 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002322 RTCPUtility::RTCPParserV2 parser(packet, length, true);
2323 EXPECT_TRUE(parser.IsValid());
2324
2325 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02002326 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
2327 if (packet_type == RTCPUtility::RTCPPacketTypes::kRr) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002328 ++sent_rtcp_rr_;
2329 } else if (packet_type ==
Erik Språng242e22b2015-05-11 10:17:43 +02002330 RTCPUtility::RTCPPacketTypes::kXrReceiverReferenceTime) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002331 ++sent_rtcp_rrtr_;
2332 }
Erik Språng242e22b2015-05-11 10:17:43 +02002333 EXPECT_NE(packet_type, RTCPUtility::RTCPPacketTypes::kSr);
2334 EXPECT_NE(packet_type,
2335 RTCPUtility::RTCPPacketTypes::kXrDlrrReportBlockItem);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002336 packet_type = parser.Iterate();
2337 }
2338 return SEND_PACKET;
2339 }
2340 // Send stream should send SR packets (and DLRR packets if enabled).
2341 virtual Action OnSendRtcp(const uint8_t* packet, size_t length) {
stefan608213e2015-11-01 14:56:10 -08002342 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002343 RTCPUtility::RTCPParserV2 parser(packet, length, true);
2344 EXPECT_TRUE(parser.IsValid());
2345
2346 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02002347 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
2348 if (packet_type == RTCPUtility::RTCPPacketTypes::kSr) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002349 ++sent_rtcp_sr_;
Erik Språng242e22b2015-05-11 10:17:43 +02002350 } else if (packet_type ==
2351 RTCPUtility::RTCPPacketTypes::kXrDlrrReportBlockItem) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002352 ++sent_rtcp_dlrr_;
2353 }
Erik Språng242e22b2015-05-11 10:17:43 +02002354 EXPECT_NE(packet_type,
2355 RTCPUtility::RTCPPacketTypes::kXrReceiverReferenceTime);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002356 packet_type = parser.Iterate();
2357 }
2358 if (sent_rtcp_sr_ > kNumRtcpReportPacketsToObserve &&
2359 sent_rtcp_rr_ > kNumRtcpReportPacketsToObserve) {
2360 if (enable_rrtr_) {
2361 EXPECT_GT(sent_rtcp_rrtr_, 0);
2362 EXPECT_GT(sent_rtcp_dlrr_, 0);
2363 } else {
2364 EXPECT_EQ(0, sent_rtcp_rrtr_);
2365 EXPECT_EQ(0, sent_rtcp_dlrr_);
2366 }
Peter Boström5811a392015-12-10 13:02:50 +01002367 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002368 }
2369 return SEND_PACKET;
2370 }
2371
stefanff483612015-12-21 03:14:00 -08002372 void ModifyVideoConfigs(
2373 VideoSendStream::Config* send_config,
2374 std::vector<VideoReceiveStream::Config>* receive_configs,
2375 VideoEncoderConfig* encoder_config) override {
pbosda903ea2015-10-02 02:36:56 -07002376 (*receive_configs)[0].rtp.rtcp_mode = RtcpMode::kReducedSize;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002377 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report =
2378 enable_rrtr_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002379 }
2380
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002381 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002382 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002383 << "Timed out while waiting for RTCP SR/RR packets to be sent.";
2384 }
2385
stefan608213e2015-11-01 14:56:10 -08002386 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002387 bool enable_rrtr_;
2388 int sent_rtcp_sr_;
stefan608213e2015-11-01 14:56:10 -08002389 int sent_rtcp_rr_ GUARDED_BY(&crit_);
2390 int sent_rtcp_rrtr_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002391 int sent_rtcp_dlrr_;
2392 } test(enable_rrtr);
2393
stefane74eef12016-01-08 06:47:13 -08002394 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002395}
2396
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002397void EndToEndTest::TestSendsSetSsrcs(size_t num_ssrcs,
2398 bool send_single_ssrc_first) {
2399 class SendsSetSsrcs : public test::EndToEndTest {
2400 public:
2401 SendsSetSsrcs(const uint32_t* ssrcs,
2402 size_t num_ssrcs,
2403 bool send_single_ssrc_first)
2404 : EndToEndTest(kDefaultTimeoutMs),
2405 num_ssrcs_(num_ssrcs),
2406 send_single_ssrc_first_(send_single_ssrc_first),
2407 ssrcs_to_observe_(num_ssrcs),
sprang867fb522015-08-03 04:38:41 -07002408 expect_single_ssrc_(send_single_ssrc_first),
2409 send_stream_(nullptr) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002410 for (size_t i = 0; i < num_ssrcs; ++i)
2411 valid_ssrcs_[ssrcs[i]] = true;
2412 }
2413
2414 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002415 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002416 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002417 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002418
2419 EXPECT_TRUE(valid_ssrcs_[header.ssrc])
2420 << "Received unknown SSRC: " << header.ssrc;
2421
2422 if (!valid_ssrcs_[header.ssrc])
Peter Boström5811a392015-12-10 13:02:50 +01002423 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002424
2425 if (!is_observed_[header.ssrc]) {
2426 is_observed_[header.ssrc] = true;
2427 --ssrcs_to_observe_;
2428 if (expect_single_ssrc_) {
2429 expect_single_ssrc_ = false;
Peter Boström5811a392015-12-10 13:02:50 +01002430 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002431 }
2432 }
2433
2434 if (ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01002435 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002436
2437 return SEND_PACKET;
2438 }
2439
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002440 size_t GetNumVideoStreams() const override { return num_ssrcs_; }
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002441
stefanff483612015-12-21 03:14:00 -08002442 void ModifyVideoConfigs(
2443 VideoSendStream::Config* send_config,
2444 std::vector<VideoReceiveStream::Config>* receive_configs,
2445 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002446 if (num_ssrcs_ > 1) {
2447 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002448 for (size_t i = 0; i < encoder_config->streams.size(); ++i) {
2449 encoder_config->streams[i].min_bitrate_bps = 10000;
2450 encoder_config->streams[i].target_bitrate_bps = 15000;
2451 encoder_config->streams[i].max_bitrate_bps = 20000;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002452 }
2453 }
2454
stefanff483612015-12-21 03:14:00 -08002455 video_encoder_config_all_streams_ = *encoder_config;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002456 if (send_single_ssrc_first_)
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002457 encoder_config->streams.resize(1);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002458 }
2459
stefanff483612015-12-21 03:14:00 -08002460 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002461 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002462 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002463 send_stream_ = send_stream;
2464 }
2465
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002466 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002467 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
2468 << (send_single_ssrc_first_ ? "first SSRC."
2469 : "SSRCs.");
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002470
2471 if (send_single_ssrc_first_) {
2472 // Set full simulcast and continue with the rest of the SSRCs.
stefanff483612015-12-21 03:14:00 -08002473 send_stream_->ReconfigureVideoEncoder(
2474 video_encoder_config_all_streams_);
Peter Boström5811a392015-12-10 13:02:50 +01002475 EXPECT_TRUE(Wait()) << "Timed out while waiting on additional SSRCs.";
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002476 }
2477 }
2478
2479 private:
2480 std::map<uint32_t, bool> valid_ssrcs_;
2481 std::map<uint32_t, bool> is_observed_;
2482
2483 const size_t num_ssrcs_;
2484 const bool send_single_ssrc_first_;
2485
2486 size_t ssrcs_to_observe_;
2487 bool expect_single_ssrc_;
2488
2489 VideoSendStream* send_stream_;
stefanff483612015-12-21 03:14:00 -08002490 VideoEncoderConfig video_encoder_config_all_streams_;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002491 } test(kVideoSendSsrcs, num_ssrcs, send_single_ssrc_first);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002492
stefane74eef12016-01-08 06:47:13 -08002493 RunBaseTest(&test);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002494}
2495
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002496TEST_F(EndToEndTest, ReportsSetEncoderRates) {
2497 class EncoderRateStatsTest : public test::EndToEndTest,
2498 public test::FakeEncoder {
2499 public:
2500 EncoderRateStatsTest()
2501 : EndToEndTest(kDefaultTimeoutMs),
sprang867fb522015-08-03 04:38:41 -07002502 FakeEncoder(Clock::GetRealTimeClock()),
2503 send_stream_(nullptr),
2504 bitrate_kbps_(0) {}
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002505
stefanff483612015-12-21 03:14:00 -08002506 void OnVideoStreamsCreated(
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002507 VideoSendStream* send_stream,
2508 const std::vector<VideoReceiveStream*>& receive_streams) override {
2509 send_stream_ = send_stream;
2510 }
2511
stefanff483612015-12-21 03:14:00 -08002512 void ModifyVideoConfigs(
2513 VideoSendStream::Config* send_config,
2514 std::vector<VideoReceiveStream::Config>* receive_configs,
2515 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002516 send_config->encoder_settings.encoder = this;
2517 }
2518
2519 int32_t SetRates(uint32_t new_target_bitrate, uint32_t framerate) override {
2520 // Make sure not to trigger on any default zero bitrates.
2521 if (new_target_bitrate == 0)
2522 return 0;
Peter Boströmf2f82832015-05-01 13:00:41 +02002523 rtc::CritScope lock(&crit_);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002524 bitrate_kbps_ = new_target_bitrate;
Peter Boström5811a392015-12-10 13:02:50 +01002525 observation_complete_.Set();
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002526 return 0;
2527 }
2528
2529 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002530 ASSERT_TRUE(Wait())
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002531 << "Timed out while waiting for encoder SetRates() call.";
2532 // Wait for GetStats to report a corresponding bitrate.
Peter Boström5811a392015-12-10 13:02:50 +01002533 for (int i = 0; i < kDefaultTimeoutMs; ++i) {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002534 VideoSendStream::Stats stats = send_stream_->GetStats();
2535 {
Peter Boströmf2f82832015-05-01 13:00:41 +02002536 rtc::CritScope lock(&crit_);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002537 if ((stats.target_media_bitrate_bps + 500) / 1000 ==
2538 static_cast<int>(bitrate_kbps_)) {
2539 return;
2540 }
2541 }
2542 SleepMs(1);
2543 }
2544 FAIL()
2545 << "Timed out waiting for stats reporting the currently set bitrate.";
2546 }
2547
2548 private:
stefanf116bd02015-10-27 08:29:42 -07002549 rtc::CriticalSection crit_;
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002550 VideoSendStream* send_stream_;
2551 uint32_t bitrate_kbps_ GUARDED_BY(crit_);
2552 } test;
2553
stefane74eef12016-01-08 06:47:13 -08002554 RunBaseTest(&test);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002555}
2556
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002557TEST_F(EndToEndTest, GetStats) {
2558 static const int kStartBitrateBps = 3000000;
Peter Boströmdef398832015-05-27 17:59:11 +02002559 static const int kExpectedRenderDelayMs = 20;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002560 class StatsObserver : public test::EndToEndTest, public I420FrameCallback {
2561 public:
stefanf116bd02015-10-27 08:29:42 -07002562 StatsObserver()
2563 : EndToEndTest(kLongTimeoutMs),
Peter Boströmc6e16e32016-02-05 14:15:53 +01002564 encoder_(Clock::GetRealTimeClock(), 10),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00002565 send_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002566 expected_send_ssrcs_(),
Peter Boström5811a392015-12-10 13:02:50 +01002567 check_stats_event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002568
2569 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002570 Action OnSendRtp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002571 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002572 return SEND_PACKET;
2573 }
2574
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002575 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002576 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002577 return SEND_PACKET;
2578 }
2579
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002580 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002581 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002582 return SEND_PACKET;
2583 }
2584
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002585 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002586 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002587 return SEND_PACKET;
2588 }
2589
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07002590 void FrameCallback(VideoFrame* video_frame) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002591 // Ensure that we have at least 5ms send side delay.
2592 int64_t render_time = video_frame->render_time_ms();
2593 if (render_time > 0)
2594 video_frame->set_render_time_ms(render_time - 5);
2595 }
2596
2597 bool CheckReceiveStats() {
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002598 for (size_t i = 0; i < receive_streams_.size(); ++i) {
2599 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
2600 EXPECT_EQ(expected_receive_ssrcs_[i], stats.ssrc);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002601
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002602 // Make sure all fields have been populated.
2603 // TODO(pbos): Use CompoundKey if/when we ever know that all stats are
2604 // always filled for all receivers.
2605 receive_stats_filled_["IncomingRate"] |=
2606 stats.network_frame_rate != 0 || stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002607
Peter Boströmb7d9a972015-12-18 16:01:11 +01002608 send_stats_filled_["DecoderImplementationName"] |=
2609 stats.decoder_implementation_name ==
2610 test::FakeDecoder::kImplementationName;
Peter Boströmdef398832015-05-27 17:59:11 +02002611 receive_stats_filled_["RenderDelayAsHighAsExpected"] |=
2612 stats.render_delay_ms >= kExpectedRenderDelayMs;
2613
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002614 receive_stats_filled_["FrameCallback"] |= stats.decode_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002615
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002616 receive_stats_filled_["FrameRendered"] |= stats.render_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002617
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002618 receive_stats_filled_["StatisticsUpdated"] |=
2619 stats.rtcp_stats.cumulative_lost != 0 ||
2620 stats.rtcp_stats.extended_max_sequence_number != 0 ||
2621 stats.rtcp_stats.fraction_lost != 0 || stats.rtcp_stats.jitter != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002622
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002623 receive_stats_filled_["DataCountersUpdated"] |=
2624 stats.rtp_stats.transmitted.payload_bytes != 0 ||
2625 stats.rtp_stats.fec.packets != 0 ||
2626 stats.rtp_stats.transmitted.header_bytes != 0 ||
2627 stats.rtp_stats.transmitted.packets != 0 ||
2628 stats.rtp_stats.transmitted.padding_bytes != 0 ||
2629 stats.rtp_stats.retransmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002630
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002631 receive_stats_filled_["CodecStats"] |=
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002632 stats.target_delay_ms != 0 || stats.discarded_packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002633
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002634 receive_stats_filled_["FrameCounts"] |=
2635 stats.frame_counts.key_frames != 0 ||
2636 stats.frame_counts.delta_frames != 0;
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002637
pbosbb36fdf2015-07-09 07:48:14 -07002638 receive_stats_filled_["CName"] |= !stats.c_name.empty();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002639
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002640 receive_stats_filled_["RtcpPacketTypeCount"] |=
2641 stats.rtcp_packet_type_counts.fir_packets != 0 ||
2642 stats.rtcp_packet_type_counts.nack_packets != 0 ||
2643 stats.rtcp_packet_type_counts.pli_packets != 0 ||
2644 stats.rtcp_packet_type_counts.nack_requests != 0 ||
2645 stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbosf42376c2015-08-28 07:35:32 -07002646
2647 assert(stats.current_payload_type == -1 ||
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002648 stats.current_payload_type == kFakeVideoSendPayloadType);
pbosf42376c2015-08-28 07:35:32 -07002649 receive_stats_filled_["IncomingPayloadType"] |=
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002650 stats.current_payload_type == kFakeVideoSendPayloadType;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002651 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002652
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002653 return AllStatsFilled(receive_stats_filled_);
2654 }
2655
2656 bool CheckSendStats() {
henrikg91d6ede2015-09-17 00:24:34 -07002657 RTC_DCHECK(send_stream_ != nullptr);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002658 VideoSendStream::Stats stats = send_stream_->GetStats();
2659
2660 send_stats_filled_["NumStreams"] |=
2661 stats.substreams.size() == expected_send_ssrcs_.size();
2662
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00002663 send_stats_filled_["CpuOveruseMetrics"] |=
Peter Boströme4499152016-02-05 11:13:28 +01002664 stats.avg_encode_time_ms != 0 && stats.encode_usage_percent != 0;
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00002665
Peter Boströmb7d9a972015-12-18 16:01:11 +01002666 send_stats_filled_["EncoderImplementationName"] |=
2667 stats.encoder_implementation_name ==
2668 test::FakeEncoder::kImplementationName;
2669
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002670 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002671 stats.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002672 it != stats.substreams.end(); ++it) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002673 EXPECT_TRUE(expected_send_ssrcs_.find(it->first) !=
2674 expected_send_ssrcs_.end());
2675
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002676 send_stats_filled_[CompoundKey("CapturedFrameRate", it->first)] |=
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002677 stats.input_frame_rate != 0;
2678
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002679 const VideoSendStream::StreamStats& stream_stats = it->second;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002680
2681 send_stats_filled_[CompoundKey("StatisticsUpdated", it->first)] |=
2682 stream_stats.rtcp_stats.cumulative_lost != 0 ||
2683 stream_stats.rtcp_stats.extended_max_sequence_number != 0 ||
2684 stream_stats.rtcp_stats.fraction_lost != 0;
2685
2686 send_stats_filled_[CompoundKey("DataCountersUpdated", it->first)] |=
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00002687 stream_stats.rtp_stats.fec.packets != 0 ||
2688 stream_stats.rtp_stats.transmitted.padding_bytes != 0 ||
2689 stream_stats.rtp_stats.retransmitted.packets != 0 ||
2690 stream_stats.rtp_stats.transmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002691
2692 send_stats_filled_[CompoundKey("BitrateStatisticsObserver",
2693 it->first)] |=
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002694 stream_stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002695
2696 send_stats_filled_[CompoundKey("FrameCountObserver", it->first)] |=
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002697 stream_stats.frame_counts.delta_frames != 0 ||
2698 stream_stats.frame_counts.key_frames != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002699
2700 send_stats_filled_[CompoundKey("OutgoingRate", it->first)] |=
2701 stats.encode_frame_rate != 0;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +00002702
2703 send_stats_filled_[CompoundKey("Delay", it->first)] |=
2704 stream_stats.avg_delay_ms != 0 || stream_stats.max_delay_ms != 0;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002705
2706 // TODO(pbos): Use CompoundKey when the test makes sure that all SSRCs
2707 // report dropped packets.
2708 send_stats_filled_["RtcpPacketTypeCount"] |=
2709 stream_stats.rtcp_packet_type_counts.fir_packets != 0 ||
2710 stream_stats.rtcp_packet_type_counts.nack_packets != 0 ||
2711 stream_stats.rtcp_packet_type_counts.pli_packets != 0 ||
2712 stream_stats.rtcp_packet_type_counts.nack_requests != 0 ||
2713 stream_stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002714 }
2715
2716 return AllStatsFilled(send_stats_filled_);
2717 }
2718
2719 std::string CompoundKey(const char* name, uint32_t ssrc) {
2720 std::ostringstream oss;
2721 oss << name << "_" << ssrc;
2722 return oss.str();
2723 }
2724
2725 bool AllStatsFilled(const std::map<std::string, bool>& stats_map) {
2726 for (std::map<std::string, bool>::const_iterator it = stats_map.begin();
2727 it != stats_map.end();
2728 ++it) {
2729 if (!it->second)
2730 return false;
2731 }
2732 return true;
2733 }
2734
stefane74eef12016-01-08 06:47:13 -08002735 test::PacketTransport* CreateSendTransport(Call* sender_call) override {
2736 FakeNetworkPipe::Config network_config;
2737 network_config.loss_percent = 5;
2738 return new test::PacketTransport(
2739 sender_call, this, test::PacketTransport::kSender, network_config);
2740 }
2741
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002742 Call::Config GetSenderCallConfig() override {
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002743 Call::Config config = EndToEndTest::GetSenderCallConfig();
Stefan Holmere5904162015-03-26 11:11:06 +01002744 config.bitrate_config.start_bitrate_bps = kStartBitrateBps;
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002745 return config;
2746 }
2747
stefanff483612015-12-21 03:14:00 -08002748 void ModifyVideoConfigs(
2749 VideoSendStream::Config* send_config,
2750 std::vector<VideoReceiveStream::Config>* receive_configs,
2751 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002752 send_config->pre_encode_callback = this; // Used to inject delay.
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002753 expected_cname_ = send_config->rtp.c_name = "SomeCName";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002754
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002755 const std::vector<uint32_t>& ssrcs = send_config->rtp.ssrcs;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002756 for (size_t i = 0; i < ssrcs.size(); ++i) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002757 expected_send_ssrcs_.insert(ssrcs[i]);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002758 expected_receive_ssrcs_.push_back(
2759 (*receive_configs)[i].rtp.remote_ssrc);
Peter Boströmdef398832015-05-27 17:59:11 +02002760 (*receive_configs)[i].render_delay_ms = kExpectedRenderDelayMs;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002761 }
Peter Boströmc6e16e32016-02-05 14:15:53 +01002762 // Use a delayed encoder to make sure we see CpuOveruseMetrics stats that
2763 // are non-zero.
2764 send_config->encoder_settings.encoder = &encoder_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002765 }
2766
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002767 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.orgece38902014-11-14 11:52:04 +00002768
stefanff483612015-12-21 03:14:00 -08002769 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002770 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002771 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002772 send_stream_ = send_stream;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002773 receive_streams_ = receive_streams;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002774 }
2775
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002776 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002777 Clock* clock = Clock::GetRealTimeClock();
2778 int64_t now = clock->TimeInMilliseconds();
2779 int64_t stop_time = now + test::CallTest::kLongTimeoutMs;
2780 bool receive_ok = false;
2781 bool send_ok = false;
2782
2783 while (now < stop_time) {
2784 if (!receive_ok)
2785 receive_ok = CheckReceiveStats();
2786 if (!send_ok)
2787 send_ok = CheckSendStats();
2788
2789 if (receive_ok && send_ok)
2790 return;
2791
2792 int64_t time_until_timout_ = stop_time - now;
2793 if (time_until_timout_ > 0)
Peter Boström5811a392015-12-10 13:02:50 +01002794 check_stats_event_.Wait(time_until_timout_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002795 now = clock->TimeInMilliseconds();
2796 }
2797
2798 ADD_FAILURE() << "Timed out waiting for filled stats.";
2799 for (std::map<std::string, bool>::const_iterator it =
2800 receive_stats_filled_.begin();
2801 it != receive_stats_filled_.end();
2802 ++it) {
2803 if (!it->second) {
2804 ADD_FAILURE() << "Missing receive stats: " << it->first;
2805 }
2806 }
2807
2808 for (std::map<std::string, bool>::const_iterator it =
2809 send_stats_filled_.begin();
2810 it != send_stats_filled_.end();
2811 ++it) {
2812 if (!it->second) {
2813 ADD_FAILURE() << "Missing send stats: " << it->first;
2814 }
2815 }
2816 }
2817
Peter Boströmc6e16e32016-02-05 14:15:53 +01002818 test::DelayedEncoder encoder_;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002819 std::vector<VideoReceiveStream*> receive_streams_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002820 std::map<std::string, bool> receive_stats_filled_;
2821
2822 VideoSendStream* send_stream_;
2823 std::map<std::string, bool> send_stats_filled_;
2824
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002825 std::vector<uint32_t> expected_receive_ssrcs_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002826 std::set<uint32_t> expected_send_ssrcs_;
2827 std::string expected_cname_;
2828
Peter Boström5811a392015-12-10 13:02:50 +01002829 rtc::Event check_stats_event_;
stefanf116bd02015-10-27 08:29:42 -07002830 } test;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002831
stefane74eef12016-01-08 06:47:13 -08002832 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002833}
2834
2835TEST_F(EndToEndTest, ReceiverReferenceTimeReportEnabled) {
2836 TestXrReceiverReferenceTimeReport(true);
2837}
2838
2839TEST_F(EndToEndTest, ReceiverReferenceTimeReportDisabled) {
2840 TestXrReceiverReferenceTimeReport(false);
2841}
2842
2843TEST_F(EndToEndTest, TestReceivedRtpPacketStats) {
2844 static const size_t kNumRtpPacketsToSend = 5;
2845 class ReceivedRtpStatsObserver : public test::EndToEndTest {
2846 public:
2847 ReceivedRtpStatsObserver()
2848 : EndToEndTest(kDefaultTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00002849 receive_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002850 sent_rtp_(0) {}
2851
2852 private:
stefanff483612015-12-21 03:14:00 -08002853 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002854 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002855 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002856 receive_stream_ = receive_streams[0];
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002857 }
2858
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002859 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002860 if (sent_rtp_ >= kNumRtpPacketsToSend) {
2861 VideoReceiveStream::Stats stats = receive_stream_->GetStats();
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00002862 if (kNumRtpPacketsToSend == stats.rtp_stats.transmitted.packets) {
Peter Boström5811a392015-12-10 13:02:50 +01002863 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002864 }
2865 return DROP_PACKET;
2866 }
2867 ++sent_rtp_;
2868 return SEND_PACKET;
2869 }
2870
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002871 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002872 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002873 << "Timed out while verifying number of received RTP packets.";
2874 }
2875
2876 VideoReceiveStream* receive_stream_;
2877 uint32_t sent_rtp_;
2878 } test;
2879
stefane74eef12016-01-08 06:47:13 -08002880 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002881}
2882
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002883TEST_F(EndToEndTest, SendsSetSsrc) { TestSendsSetSsrcs(1, false); }
2884
2885TEST_F(EndToEndTest, SendsSetSimulcastSsrcs) {
2886 TestSendsSetSsrcs(kNumSsrcs, false);
2887}
2888
2889TEST_F(EndToEndTest, CanSwitchToUseAllSsrcs) {
2890 TestSendsSetSsrcs(kNumSsrcs, true);
2891}
2892
mflodman@webrtc.orgf9460682014-07-24 16:41:25 +00002893TEST_F(EndToEndTest, DISABLED_RedundantPayloadsTransmittedOnAllSsrcs) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002894 class ObserveRedundantPayloads: public test::EndToEndTest {
2895 public:
2896 ObserveRedundantPayloads()
2897 : EndToEndTest(kDefaultTimeoutMs), ssrcs_to_observe_(kNumSsrcs) {
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00002898 for (size_t i = 0; i < kNumSsrcs; ++i) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002899 registered_rtx_ssrc_[kSendRtxSsrcs[i]] = true;
2900 }
2901 }
2902
2903 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002904 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002905 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002906 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002907
2908 if (!registered_rtx_ssrc_[header.ssrc])
2909 return SEND_PACKET;
2910
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00002911 EXPECT_LE(header.headerLength + header.paddingLength, length);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002912 const bool packet_is_redundant_payload =
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00002913 header.headerLength + header.paddingLength < length;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002914
2915 if (!packet_is_redundant_payload)
2916 return SEND_PACKET;
2917
2918 if (!observed_redundant_retransmission_[header.ssrc]) {
2919 observed_redundant_retransmission_[header.ssrc] = true;
2920 if (--ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01002921 observation_complete_.Set();
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002922 }
2923
2924 return SEND_PACKET;
2925 }
2926
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002927 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002928
stefanff483612015-12-21 03:14:00 -08002929 void ModifyVideoConfigs(
2930 VideoSendStream::Config* send_config,
2931 std::vector<VideoReceiveStream::Config>* receive_configs,
2932 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002933 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002934 for (size_t i = 0; i < encoder_config->streams.size(); ++i) {
2935 encoder_config->streams[i].min_bitrate_bps = 10000;
2936 encoder_config->streams[i].target_bitrate_bps = 15000;
2937 encoder_config->streams[i].max_bitrate_bps = 20000;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002938 }
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002939
2940 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002941
2942 for (size_t i = 0; i < kNumSsrcs; ++i)
2943 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.orgad3b5a52014-10-24 09:23:21 +00002944
2945 // Significantly higher than max bitrates for all video streams -> forcing
2946 // padding to trigger redundant padding on all RTX SSRCs.
2947 encoder_config->min_transmit_bitrate_bps = 100000;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002948 }
2949
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002950 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002951 EXPECT_TRUE(Wait())
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002952 << "Timed out while waiting for redundant payloads on all SSRCs.";
2953 }
2954
2955 private:
2956 size_t ssrcs_to_observe_;
2957 std::map<uint32_t, bool> observed_redundant_retransmission_;
2958 std::map<uint32_t, bool> registered_rtx_ssrc_;
2959 } test;
2960
stefane74eef12016-01-08 06:47:13 -08002961 RunBaseTest(&test);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002962}
2963
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002964void EndToEndTest::TestRtpStatePreservation(bool use_rtx) {
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002965 class RtpSequenceObserver : public test::RtpRtcpObserver {
2966 public:
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00002967 explicit RtpSequenceObserver(bool use_rtx)
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002968 : test::RtpRtcpObserver(kDefaultTimeoutMs),
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002969 ssrcs_to_observe_(kNumSsrcs) {
2970 for (size_t i = 0; i < kNumSsrcs; ++i) {
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002971 configured_ssrcs_[kVideoSendSsrcs[i]] = true;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002972 if (use_rtx)
2973 configured_ssrcs_[kSendRtxSsrcs[i]] = true;
2974 }
2975 }
2976
2977 void ResetExpectedSsrcs(size_t num_expected_ssrcs) {
Peter Boströmf2f82832015-05-01 13:00:41 +02002978 rtc::CritScope lock(&crit_);
danilchap34877ee2016-02-01 08:25:04 -08002979 ssrc_observed_.clear();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002980 ssrcs_to_observe_ = num_expected_ssrcs;
2981 }
2982
2983 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002984 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002985 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002986 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002987 const uint32_t ssrc = header.ssrc;
danilchap5c35cf92016-02-03 14:14:49 -08002988 const int64_t sequence_number =
2989 seq_numbers_unwrapper_.Unwrap(header.sequenceNumber);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002990 const uint32_t timestamp = header.timestamp;
danilchap34877ee2016-02-01 08:25:04 -08002991 const bool only_padding =
2992 header.headerLength + header.paddingLength == length;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002993
2994 EXPECT_TRUE(configured_ssrcs_[ssrc])
2995 << "Received SSRC that wasn't configured: " << ssrc;
2996
danilchap5c35cf92016-02-03 14:14:49 -08002997 static const int64_t kMaxSequenceNumberGap = 100;
2998 std::list<int64_t>* seq_numbers = &last_observed_seq_numbers_[ssrc];
2999 if (seq_numbers->empty()) {
3000 seq_numbers->push_back(sequence_number);
3001 } else {
3002 // We shouldn't get replays of previous sequence numbers.
3003 for (int64_t observed : *seq_numbers) {
3004 EXPECT_NE(observed, sequence_number)
3005 << "Received sequence number " << sequence_number
3006 << " for SSRC " << ssrc << " 2nd time.";
3007 }
3008 // Verify sequence numbers are reasonably close.
3009 int64_t latest_observed = seq_numbers->back();
3010 int64_t sequence_number_gap = sequence_number - latest_observed;
3011 EXPECT_LE(std::abs(sequence_number_gap), kMaxSequenceNumberGap)
3012 << "Gap in sequence numbers (" << latest_observed << " -> "
3013 << sequence_number << ") too large for SSRC: " << ssrc << ".";
3014 seq_numbers->push_back(sequence_number);
3015 if (seq_numbers->size() >= kMaxSequenceNumberGap) {
3016 seq_numbers->pop_front();
3017 }
3018 }
3019
3020 static const int32_t kMaxTimestampGap = kDefaultTimeoutMs * 90;
3021 auto timestamp_it = last_observed_timestamp_.find(ssrc);
3022 if (timestamp_it == last_observed_timestamp_.end()) {
danilchap34877ee2016-02-01 08:25:04 -08003023 last_observed_timestamp_[ssrc] = timestamp;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003024 } else {
danilchap5c35cf92016-02-03 14:14:49 -08003025 // Verify timestamps are reasonably close.
3026 uint32_t latest_observed = timestamp_it->second;
3027 int32_t timestamp_gap = rtc::TimeDiff(timestamp, latest_observed);
3028 EXPECT_LE(std::abs(timestamp_gap), kMaxTimestampGap)
3029 << "Gap in timestamps (" << latest_observed << " -> "
3030 << timestamp << ") too large for SSRC: " << ssrc << ".";
3031 timestamp_it->second = timestamp;
danilchapf4b9c772016-01-28 06:14:24 -08003032 }
danilchap34877ee2016-02-01 08:25:04 -08003033
3034 rtc::CritScope lock(&crit_);
3035 // Wait for media packets on all ssrcs.
3036 if (!ssrc_observed_[ssrc] && !only_padding) {
3037 ssrc_observed_[ssrc] = true;
3038 if (--ssrcs_to_observe_ == 0)
3039 observation_complete_.Set();
3040 }
3041
danilchapf4b9c772016-01-28 06:14:24 -08003042 return SEND_PACKET;
3043 }
3044
danilchap5c35cf92016-02-03 14:14:49 -08003045 SequenceNumberUnwrapper seq_numbers_unwrapper_;
3046 std::map<uint32_t, std::list<int64_t>> last_observed_seq_numbers_;
danilchap34877ee2016-02-01 08:25:04 -08003047 std::map<uint32_t, uint32_t> last_observed_timestamp_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003048 std::map<uint32_t, bool> configured_ssrcs_;
3049
Peter Boströmf2f82832015-05-01 13:00:41 +02003050 rtc::CriticalSection crit_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003051 size_t ssrcs_to_observe_ GUARDED_BY(crit_);
danilchap34877ee2016-02-01 08:25:04 -08003052 std::map<uint32_t, bool> ssrc_observed_ GUARDED_BY(crit_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003053 } observer(use_rtx);
3054
solenberg4fbae2b2015-08-28 04:07:10 -07003055 CreateCalls(Call::Config(), Call::Config());
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003056
stefanf116bd02015-10-27 08:29:42 -07003057 test::PacketTransport send_transport(sender_call_.get(), &observer,
3058 test::PacketTransport::kSender,
3059 FakeNetworkPipe::Config());
3060 test::PacketTransport receive_transport(nullptr, &observer,
3061 test::PacketTransport::kReceiver,
3062 FakeNetworkPipe::Config());
3063 send_transport.SetReceiver(receiver_call_->Receiver());
3064 receive_transport.SetReceiver(sender_call_->Receiver());
3065
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003066 CreateSendConfig(kNumSsrcs, 0, &send_transport);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003067
3068 if (use_rtx) {
3069 for (size_t i = 0; i < kNumSsrcs; ++i) {
stefanff483612015-12-21 03:14:00 -08003070 video_send_config_.rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003071 }
stefanff483612015-12-21 03:14:00 -08003072 video_send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003073 }
3074
3075 // Lower bitrates so that all streams send initially.
stefanff483612015-12-21 03:14:00 -08003076 for (size_t i = 0; i < video_encoder_config_.streams.size(); ++i) {
3077 video_encoder_config_.streams[i].min_bitrate_bps = 10000;
3078 video_encoder_config_.streams[i].target_bitrate_bps = 15000;
3079 video_encoder_config_.streams[i].max_bitrate_bps = 20000;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003080 }
3081
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003082 // Use the same total bitrates when sending a single stream to avoid lowering
3083 // the bitrate estimate and requiring a subsequent rampup.
stefanff483612015-12-21 03:14:00 -08003084 VideoEncoderConfig one_stream = video_encoder_config_;
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003085 one_stream.streams.resize(1);
stefanff483612015-12-21 03:14:00 -08003086 for (size_t i = 1; i < video_encoder_config_.streams.size(); ++i) {
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003087 one_stream.streams.front().min_bitrate_bps +=
stefanff483612015-12-21 03:14:00 -08003088 video_encoder_config_.streams[i].min_bitrate_bps;
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003089 one_stream.streams.front().target_bitrate_bps +=
stefanff483612015-12-21 03:14:00 -08003090 video_encoder_config_.streams[i].target_bitrate_bps;
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003091 one_stream.streams.front().max_bitrate_bps +=
stefanff483612015-12-21 03:14:00 -08003092 video_encoder_config_.streams[i].max_bitrate_bps;
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003093 }
3094
stefanf116bd02015-10-27 08:29:42 -07003095 CreateMatchingReceiveConfigs(&receive_transport);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003096
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003097 CreateVideoStreams();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003098 CreateFrameGeneratorCapturer();
3099
3100 Start();
Peter Boström5811a392015-12-10 13:02:50 +01003101 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003102 << "Timed out waiting for all SSRCs to send packets.";
3103
3104 // Test stream resetting more than once to make sure that the state doesn't
3105 // get set once (this could be due to using std::map::insert for instance).
3106 for (size_t i = 0; i < 3; ++i) {
3107 frame_generator_capturer_->Stop();
stefanff483612015-12-21 03:14:00 -08003108 sender_call_->DestroyVideoSendStream(video_send_stream_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003109
3110 // Re-create VideoSendStream with only one stream.
stefanff483612015-12-21 03:14:00 -08003111 video_send_stream_ =
3112 sender_call_->CreateVideoSendStream(video_send_config_, one_stream);
3113 video_send_stream_->Start();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003114 CreateFrameGeneratorCapturer();
3115 frame_generator_capturer_->Start();
3116
3117 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01003118 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003119
3120 // Reconfigure back to use all streams.
stefanff483612015-12-21 03:14:00 -08003121 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003122 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01003123 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003124 << "Timed out waiting for all SSRCs to send packets.";
3125
3126 // Reconfigure down to one stream.
stefanff483612015-12-21 03:14:00 -08003127 video_send_stream_->ReconfigureVideoEncoder(one_stream);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003128 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01003129 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003130
3131 // Reconfigure back to use all streams.
stefanff483612015-12-21 03:14:00 -08003132 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003133 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01003134 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003135 << "Timed out waiting for all SSRCs to send packets.";
3136 }
3137
stefanf116bd02015-10-27 08:29:42 -07003138 send_transport.StopSending();
3139 receive_transport.StopSending();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003140
3141 Stop();
3142 DestroyStreams();
3143}
3144
Peter Boströmfc968a22016-02-19 16:14:37 +01003145TEST_F(EndToEndTest, RestartingSendStreamPreservesRtpState) {
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003146 TestRtpStatePreservation(false);
3147}
3148
3149TEST_F(EndToEndTest, RestartingSendStreamPreservesRtpStatesWithRtx) {
3150 TestRtpStatePreservation(true);
3151}
3152
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003153TEST_F(EndToEndTest, RespectsNetworkState) {
3154 // TODO(pbos): Remove accepted downtime packets etc. when signaling network
3155 // down blocks until no more packets will be sent.
3156
3157 // Pacer will send from its packet list and then send required padding before
3158 // checking paused_ again. This should be enough for one round of pacing,
3159 // otherwise increase.
3160 static const int kNumAcceptedDowntimeRtp = 5;
3161 // A single RTCP may be in the pipeline.
3162 static const int kNumAcceptedDowntimeRtcp = 1;
3163 class NetworkStateTest : public test::EndToEndTest, public test::FakeEncoder {
3164 public:
3165 NetworkStateTest()
3166 : EndToEndTest(kDefaultTimeoutMs),
3167 FakeEncoder(Clock::GetRealTimeClock()),
Peter Boström5811a392015-12-10 13:02:50 +01003168 encoded_frames_(false, false),
3169 packet_event_(false, false),
sprang867fb522015-08-03 04:38:41 -07003170 sender_call_(nullptr),
3171 receiver_call_(nullptr),
Jelena Marusiccd670222015-07-16 09:30:09 +02003172 sender_state_(kNetworkUp),
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003173 sender_rtp_(0),
3174 sender_rtcp_(0),
3175 receiver_rtcp_(0),
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003176 down_frames_(0) {}
3177
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003178 Action OnSendRtp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003179 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003180 ++sender_rtp_;
Peter Boström5811a392015-12-10 13:02:50 +01003181 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003182 return SEND_PACKET;
3183 }
3184
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003185 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003186 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003187 ++sender_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01003188 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003189 return SEND_PACKET;
3190 }
3191
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003192 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003193 ADD_FAILURE() << "Unexpected receiver RTP, should not be sending.";
3194 return SEND_PACKET;
3195 }
3196
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003197 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003198 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003199 ++receiver_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01003200 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003201 return SEND_PACKET;
3202 }
3203
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003204 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003205 sender_call_ = sender_call;
3206 receiver_call_ = receiver_call;
3207 }
3208
stefanff483612015-12-21 03:14:00 -08003209 void ModifyVideoConfigs(
3210 VideoSendStream::Config* send_config,
3211 std::vector<VideoReceiveStream::Config>* receive_configs,
3212 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003213 send_config->encoder_settings.encoder = this;
3214 }
3215
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003216 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003217 EXPECT_TRUE(encoded_frames_.Wait(kDefaultTimeoutMs))
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003218 << "No frames received by the encoder.";
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003219 // Wait for packets from both sender/receiver.
3220 WaitForPacketsOrSilence(false, false);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003221
3222 // Sender-side network down.
Jelena Marusiccd670222015-07-16 09:30:09 +02003223 sender_call_->SignalNetworkState(kNetworkDown);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003224 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003225 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003226 // After network goes down we shouldn't be encoding more frames.
Jelena Marusiccd670222015-07-16 09:30:09 +02003227 sender_state_ = kNetworkDown;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003228 }
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003229 // Wait for receiver-packets and no sender packets.
3230 WaitForPacketsOrSilence(true, false);
3231
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003232 // Receiver-side network down.
Jelena Marusiccd670222015-07-16 09:30:09 +02003233 receiver_call_->SignalNetworkState(kNetworkDown);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003234 WaitForPacketsOrSilence(true, true);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003235
3236 // Network back up again for both.
3237 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003238 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003239 // It's OK to encode frames again, as we're about to bring up the
3240 // network.
Jelena Marusiccd670222015-07-16 09:30:09 +02003241 sender_state_ = kNetworkUp;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003242 }
Jelena Marusiccd670222015-07-16 09:30:09 +02003243 sender_call_->SignalNetworkState(kNetworkUp);
3244 receiver_call_->SignalNetworkState(kNetworkUp);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003245 WaitForPacketsOrSilence(false, false);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003246 }
3247
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07003248 int32_t Encode(const VideoFrame& input_image,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003249 const CodecSpecificInfo* codec_specific_info,
pbos22993e12015-10-19 02:39:06 -07003250 const std::vector<FrameType>* frame_types) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003251 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003252 rtc::CritScope lock(&test_crit_);
Jelena Marusiccd670222015-07-16 09:30:09 +02003253 if (sender_state_ == kNetworkDown) {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003254 ++down_frames_;
3255 EXPECT_LE(down_frames_, 1)
3256 << "Encoding more than one frame while network is down.";
3257 if (down_frames_ > 1)
Peter Boström5811a392015-12-10 13:02:50 +01003258 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003259 } else {
Peter Boström5811a392015-12-10 13:02:50 +01003260 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003261 }
3262 }
3263 return test::FakeEncoder::Encode(
3264 input_image, codec_specific_info, frame_types);
3265 }
3266
3267 private:
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003268 void WaitForPacketsOrSilence(bool sender_down, bool receiver_down) {
3269 int64_t initial_time_ms = clock_->TimeInMilliseconds();
3270 int initial_sender_rtp;
3271 int initial_sender_rtcp;
3272 int initial_receiver_rtcp;
3273 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003274 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003275 initial_sender_rtp = sender_rtp_;
3276 initial_sender_rtcp = sender_rtcp_;
3277 initial_receiver_rtcp = receiver_rtcp_;
3278 }
3279 bool sender_done = false;
3280 bool receiver_done = false;
mflodmand1590b22015-12-09 07:07:59 -08003281 while (!sender_done || !receiver_done) {
Peter Boström5811a392015-12-10 13:02:50 +01003282 packet_event_.Wait(kSilenceTimeoutMs);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003283 int64_t time_now_ms = clock_->TimeInMilliseconds();
Peter Boströmf2f82832015-05-01 13:00:41 +02003284 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003285 if (sender_down) {
3286 ASSERT_LE(sender_rtp_ - initial_sender_rtp, kNumAcceptedDowntimeRtp)
3287 << "RTP sent during sender-side downtime.";
3288 ASSERT_LE(sender_rtcp_ - initial_sender_rtcp,
3289 kNumAcceptedDowntimeRtcp)
3290 << "RTCP sent during sender-side downtime.";
3291 if (time_now_ms - initial_time_ms >=
3292 static_cast<int64_t>(kSilenceTimeoutMs)) {
3293 sender_done = true;
3294 }
3295 } else {
3296 if (sender_rtp_ > initial_sender_rtp)
3297 sender_done = true;
3298 }
3299 if (receiver_down) {
3300 ASSERT_LE(receiver_rtcp_ - initial_receiver_rtcp,
3301 kNumAcceptedDowntimeRtcp)
3302 << "RTCP sent during receiver-side downtime.";
3303 if (time_now_ms - initial_time_ms >=
3304 static_cast<int64_t>(kSilenceTimeoutMs)) {
3305 receiver_done = true;
3306 }
3307 } else {
3308 if (receiver_rtcp_ > initial_receiver_rtcp)
3309 receiver_done = true;
3310 }
3311 }
3312 }
3313
Peter Boströmf2f82832015-05-01 13:00:41 +02003314 rtc::CriticalSection test_crit_;
Peter Boström5811a392015-12-10 13:02:50 +01003315 rtc::Event encoded_frames_;
3316 rtc::Event packet_event_;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003317 Call* sender_call_;
3318 Call* receiver_call_;
Jelena Marusiccd670222015-07-16 09:30:09 +02003319 NetworkState sender_state_ GUARDED_BY(test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003320 int sender_rtp_ GUARDED_BY(test_crit_);
3321 int sender_rtcp_ GUARDED_BY(test_crit_);
3322 int receiver_rtcp_ GUARDED_BY(test_crit_);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003323 int down_frames_ GUARDED_BY(test_crit_);
3324 } test;
3325
stefane74eef12016-01-08 06:47:13 -08003326 RunBaseTest(&test);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003327}
3328
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003329TEST_F(EndToEndTest, CallReportsRttForSender) {
3330 static const int kSendDelayMs = 30;
3331 static const int kReceiveDelayMs = 70;
3332
solenberg4fbae2b2015-08-28 04:07:10 -07003333 CreateCalls(Call::Config(), Call::Config());
3334
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003335 FakeNetworkPipe::Config config;
3336 config.queue_delay_ms = kSendDelayMs;
stefanf116bd02015-10-27 08:29:42 -07003337 test::DirectTransport sender_transport(config, sender_call_.get());
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003338 config.queue_delay_ms = kReceiveDelayMs;
stefanf116bd02015-10-27 08:29:42 -07003339 test::DirectTransport receiver_transport(config, receiver_call_.get());
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003340 sender_transport.SetReceiver(receiver_call_->Receiver());
3341 receiver_transport.SetReceiver(sender_call_->Receiver());
3342
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003343 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07003344 CreateMatchingReceiveConfigs(&receiver_transport);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003345
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003346 CreateVideoStreams();
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003347 CreateFrameGeneratorCapturer();
3348 Start();
3349
3350 int64_t start_time_ms = clock_->TimeInMilliseconds();
3351 while (true) {
3352 Call::Stats stats = sender_call_->GetStats();
3353 ASSERT_GE(start_time_ms + kDefaultTimeoutMs,
3354 clock_->TimeInMilliseconds())
3355 << "No RTT stats before timeout!";
3356 if (stats.rtt_ms != -1) {
3357 EXPECT_GE(stats.rtt_ms, kSendDelayMs + kReceiveDelayMs);
3358 break;
3359 }
3360 SleepMs(10);
3361 }
3362
3363 Stop();
3364 DestroyStreams();
3365}
3366
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003367TEST_F(EndToEndTest, NewSendStreamsRespectNetworkDown) {
3368 class UnusedEncoder : public test::FakeEncoder {
mflodmand1590b22015-12-09 07:07:59 -08003369 public:
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003370 UnusedEncoder() : FakeEncoder(Clock::GetRealTimeClock()) {}
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07003371 int32_t Encode(const VideoFrame& input_image,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003372 const CodecSpecificInfo* codec_specific_info,
pbos22993e12015-10-19 02:39:06 -07003373 const std::vector<FrameType>* frame_types) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003374 ADD_FAILURE() << "Unexpected frame encode.";
3375 return test::FakeEncoder::Encode(
3376 input_image, codec_specific_info, frame_types);
3377 }
3378 };
3379
solenberg4fbae2b2015-08-28 04:07:10 -07003380 CreateSenderCall(Call::Config());
Jelena Marusiccd670222015-07-16 09:30:09 +02003381 sender_call_->SignalNetworkState(kNetworkDown);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003382
solenberg4fbae2b2015-08-28 04:07:10 -07003383 UnusedTransport transport;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003384 CreateSendConfig(1, 0, &transport);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003385 UnusedEncoder unused_encoder;
stefanff483612015-12-21 03:14:00 -08003386 video_send_config_.encoder_settings.encoder = &unused_encoder;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003387 CreateVideoStreams();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003388 CreateFrameGeneratorCapturer();
3389
3390 Start();
3391 SleepMs(kSilenceTimeoutMs);
3392 Stop();
3393
3394 DestroyStreams();
3395}
3396
3397TEST_F(EndToEndTest, NewReceiveStreamsRespectNetworkDown) {
solenberg4fbae2b2015-08-28 04:07:10 -07003398 CreateCalls(Call::Config(), Call::Config());
Jelena Marusiccd670222015-07-16 09:30:09 +02003399 receiver_call_->SignalNetworkState(kNetworkDown);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003400
stefanf116bd02015-10-27 08:29:42 -07003401 test::DirectTransport sender_transport(sender_call_.get());
solenberg4fbae2b2015-08-28 04:07:10 -07003402 sender_transport.SetReceiver(receiver_call_->Receiver());
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003403 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07003404 UnusedTransport transport;
3405 CreateMatchingReceiveConfigs(&transport);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003406 CreateVideoStreams();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003407 CreateFrameGeneratorCapturer();
3408
3409 Start();
3410 SleepMs(kSilenceTimeoutMs);
3411 Stop();
3412
3413 sender_transport.StopSending();
3414
3415 DestroyStreams();
3416}
pbos@webrtc.org09cc6862014-11-04 13:48:15 +00003417
Peter Boströmd7da1202015-06-05 14:09:38 +02003418void VerifyEmptyNackConfig(const NackConfig& config) {
3419 EXPECT_EQ(0, config.rtp_history_ms)
3420 << "Enabling NACK requires rtcp-fb: nack negotiation.";
3421}
3422
3423void VerifyEmptyFecConfig(const FecConfig& config) {
3424 EXPECT_EQ(-1, config.ulpfec_payload_type)
3425 << "Enabling FEC requires rtpmap: ulpfec negotiation.";
3426 EXPECT_EQ(-1, config.red_payload_type)
3427 << "Enabling FEC requires rtpmap: red negotiation.";
3428 EXPECT_EQ(-1, config.red_rtx_payload_type)
3429 << "Enabling RTX in FEC requires rtpmap: rtx negotiation.";
3430}
3431
3432TEST_F(EndToEndTest, VerifyDefaultSendConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07003433 VideoSendStream::Config default_send_config(nullptr);
Peter Boströmd7da1202015-06-05 14:09:38 +02003434 EXPECT_EQ(0, default_send_config.rtp.nack.rtp_history_ms)
3435 << "Enabling NACK require rtcp-fb: nack negotiation.";
3436 EXPECT_TRUE(default_send_config.rtp.rtx.ssrcs.empty())
3437 << "Enabling RTX requires rtpmap: rtx negotiation.";
3438 EXPECT_TRUE(default_send_config.rtp.extensions.empty())
3439 << "Enabling RTP extensions require negotiation.";
3440
3441 VerifyEmptyNackConfig(default_send_config.rtp.nack);
3442 VerifyEmptyFecConfig(default_send_config.rtp.fec);
3443}
3444
3445TEST_F(EndToEndTest, VerifyDefaultReceiveConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07003446 VideoReceiveStream::Config default_receive_config(nullptr);
pbosda903ea2015-10-02 02:36:56 -07003447 EXPECT_EQ(RtcpMode::kCompound, default_receive_config.rtp.rtcp_mode)
Peter Boströmd7da1202015-06-05 14:09:38 +02003448 << "Reduced-size RTCP require rtcp-rsize to be negotiated.";
3449 EXPECT_FALSE(default_receive_config.rtp.remb)
3450 << "REMB require rtcp-fb: goog-remb to be negotiated.";
3451 EXPECT_FALSE(
3452 default_receive_config.rtp.rtcp_xr.receiver_reference_time_report)
3453 << "RTCP XR settings require rtcp-xr to be negotiated.";
3454 EXPECT_TRUE(default_receive_config.rtp.rtx.empty())
3455 << "Enabling RTX requires rtpmap: rtx negotiation.";
3456 EXPECT_TRUE(default_receive_config.rtp.extensions.empty())
3457 << "Enabling RTP extensions require negotiation.";
3458
3459 VerifyEmptyNackConfig(default_receive_config.rtp.nack);
3460 VerifyEmptyFecConfig(default_receive_config.rtp.fec);
3461}
3462
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003463TEST_F(EndToEndTest, TransportSeqNumOnAudioAndVideo) {
3464 static const int kExtensionId = 8;
3465 class TransportSequenceNumberTest : public test::EndToEndTest {
3466 public:
3467 TransportSequenceNumberTest()
3468 : EndToEndTest(kDefaultTimeoutMs),
3469 video_observed_(false),
3470 audio_observed_(false) {
3471 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
3472 kExtensionId);
3473 }
3474
3475 size_t GetNumVideoStreams() const override { return 1; }
3476 size_t GetNumAudioStreams() const override { return 1; }
3477
3478 void ModifyVideoConfigs(
3479 VideoSendStream::Config* send_config,
3480 std::vector<VideoReceiveStream::Config>* receive_configs,
3481 VideoEncoderConfig* encoder_config) override {
3482 send_config->rtp.extensions.clear();
3483 send_config->rtp.extensions.push_back(
3484 RtpExtension(RtpExtension::kTransportSequenceNumber, kExtensionId));
3485 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
3486 }
3487
3488 void ModifyAudioConfigs(
3489 AudioSendStream::Config* send_config,
3490 std::vector<AudioReceiveStream::Config>* receive_configs) override {
3491 send_config->rtp.extensions.clear();
3492 send_config->rtp.extensions.push_back(
3493 RtpExtension(RtpExtension::kTransportSequenceNumber, kExtensionId));
3494 (*receive_configs)[0].rtp.extensions.clear();
3495 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
3496 }
3497
3498 Action OnSendRtp(const uint8_t* packet, size_t length) override {
3499 RTPHeader header;
3500 EXPECT_TRUE(parser_->Parse(packet, length, &header));
3501 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
3502 // Unwrap packet id and verify uniqueness.
3503 int64_t packet_id =
3504 unwrapper_.Unwrap(header.extension.transportSequenceNumber);
3505 EXPECT_TRUE(received_packet_ids_.insert(packet_id).second);
3506
3507 if (header.ssrc == kVideoSendSsrcs[0])
3508 video_observed_ = true;
3509 if (header.ssrc == kAudioSendSsrc)
3510 audio_observed_ = true;
3511 if (audio_observed_ && video_observed_ &&
3512 received_packet_ids_.size() == 50) {
3513 size_t packet_id_range =
3514 *received_packet_ids_.rbegin() - *received_packet_ids_.begin() + 1;
3515 EXPECT_EQ(received_packet_ids_.size(), packet_id_range);
3516 observation_complete_.Set();
3517 }
3518 return SEND_PACKET;
3519 }
3520
3521 void PerformTest() override {
3522 EXPECT_TRUE(Wait()) << "Timed out while waiting for audio and video "
3523 "packets with transport sequence number.";
3524 }
3525
3526 private:
3527 bool video_observed_;
3528 bool audio_observed_;
3529 SequenceNumberUnwrapper unwrapper_;
3530 std::set<int64_t> received_packet_ids_;
3531 } test;
3532
stefane74eef12016-01-08 06:47:13 -08003533 RunBaseTest(&test);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003534}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003535} // namespace webrtc