blob: 0bf7570d1df5f79129b5be9e5bcdb675b4068bc7 [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>
11#include <map>
12#include <sstream>
13#include <string>
14
15#include "testing/gtest/include/gtest/gtest.h"
16
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +000017#include "webrtc/base/checks.h"
Erik Språng6b8d3552015-09-24 15:06:57 +020018#include "webrtc/base/event.h"
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +000019#include "webrtc/base/scoped_ptr.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000020#include "webrtc/call.h"
Peter Boström5c389d32015-09-25 13:58:30 +020021#include "webrtc/call/transport_adapter.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000022#include "webrtc/frame_callback.h"
stefan32f81542016-01-20 07:13:58 -080023#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h"
sprang861c55e2015-10-16 10:01:21 -070024#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000025#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
marpan@webrtc.org5b883172014-11-01 06:10:48 +000026#include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h"
27#include "webrtc/modules/video_coding/codecs/vp9/include/vp9.h"
Henrik Kjellander2557b862015-11-18 22:00:21 +010028#include "webrtc/modules/video_coding/include/video_coding_defines.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010029#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010030#include "webrtc/system_wrappers/include/metrics.h"
31#include "webrtc/system_wrappers/include/sleep.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000032#include "webrtc/test/call_test.h"
33#include "webrtc/test/direct_transport.h"
34#include "webrtc/test/encoder_settings.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000035#include "webrtc/test/fake_decoder.h"
36#include "webrtc/test/fake_encoder.h"
37#include "webrtc/test/frame_generator.h"
38#include "webrtc/test/frame_generator_capturer.h"
Åsa Persson352b2d72015-04-15 18:00:40 +020039#include "webrtc/test/histogram.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000040#include "webrtc/test/null_transport.h"
asapersson@webrtc.org37c05592015-01-28 13:58:27 +000041#include "webrtc/test/rtcp_packet_parser.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000042#include "webrtc/test/rtp_rtcp_observer.h"
43#include "webrtc/test/testsupport/fileutils.h"
44#include "webrtc/test/testsupport/perf_test.h"
pbos@webrtc.orgab990ae2014-09-17 09:02:25 +000045#include "webrtc/video_encoder.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000046
47namespace webrtc {
48
Peter Boström5811a392015-12-10 13:02:50 +010049static const int kSilenceTimeoutMs = 2000;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000050
51class EndToEndTest : public test::CallTest {
52 public:
53 EndToEndTest() {}
54
55 virtual ~EndToEndTest() {
stefanff483612015-12-21 03:14:00 -080056 EXPECT_EQ(nullptr, video_send_stream_);
57 EXPECT_TRUE(video_receive_streams_.empty());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000058 }
59
60 protected:
pbos2d566682015-09-28 09:59:31 -070061 class UnusedTransport : public Transport {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000062 private:
stefan1d8a5062015-10-02 03:39:33 -070063 bool SendRtp(const uint8_t* packet,
64 size_t length,
65 const PacketOptions& options) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000066 ADD_FAILURE() << "Unexpected RTP sent.";
67 return false;
68 }
69
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000070 bool SendRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000071 ADD_FAILURE() << "Unexpected RTCP sent.";
72 return false;
73 }
74 };
75
Shao Changbine62202f2015-04-21 20:24:50 +080076 void DecodesRetransmittedFrame(bool use_rtx, bool use_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000077 void ReceivesPliAndRecovers(int rtp_history_ms);
pbosda903ea2015-10-02 02:36:56 -070078 void RespectsRtcpMode(RtcpMode rtcp_mode);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000079 void TestXrReceiverReferenceTimeReport(bool enable_rrtr);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +000080 void TestSendsSetSsrcs(size_t num_ssrcs, bool send_single_ssrc_first);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +000081 void TestRtpStatePreservation(bool use_rtx);
sprangb4a1ae52015-12-03 08:10:08 -080082 void VerifyHistogramStats(bool use_rtx, bool use_red, bool screenshare);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000083};
84
85TEST_F(EndToEndTest, ReceiverCanBeStartedTwice) {
solenberg4fbae2b2015-08-28 04:07:10 -070086 CreateCalls(Call::Config(), Call::Config());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000087
solenberg4fbae2b2015-08-28 04:07:10 -070088 test::NullTransport transport;
Stefan Holmer9fea80f2016-01-07 17:43:18 +010089 CreateSendConfig(1, 0, &transport);
solenberg4fbae2b2015-08-28 04:07:10 -070090 CreateMatchingReceiveConfigs(&transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000091
Stefan Holmer9fea80f2016-01-07 17:43:18 +010092 CreateVideoStreams();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000093
stefanff483612015-12-21 03:14:00 -080094 video_receive_streams_[0]->Start();
95 video_receive_streams_[0]->Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000096
97 DestroyStreams();
98}
99
100TEST_F(EndToEndTest, ReceiverCanBeStoppedTwice) {
solenberg4fbae2b2015-08-28 04:07:10 -0700101 CreateCalls(Call::Config(), Call::Config());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000102
solenberg4fbae2b2015-08-28 04:07:10 -0700103 test::NullTransport transport;
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100104 CreateSendConfig(1, 0, &transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700105 CreateMatchingReceiveConfigs(&transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000106
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100107 CreateVideoStreams();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000108
stefanff483612015-12-21 03:14:00 -0800109 video_receive_streams_[0]->Stop();
110 video_receive_streams_[0]->Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000111
112 DestroyStreams();
113}
114
115TEST_F(EndToEndTest, RendersSingleDelayedFrame) {
116 static const int kWidth = 320;
117 static const int kHeight = 240;
118 // This constant is chosen to be higher than the timeout in the video_render
119 // module. This makes sure that frames aren't dropped if there are no other
120 // frames in the queue.
121 static const int kDelayRenderCallbackMs = 1000;
122
123 class Renderer : public VideoRenderer {
124 public:
Peter Boström5811a392015-12-10 13:02:50 +0100125 Renderer() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000126
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700127 void RenderFrame(const VideoFrame& video_frame,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000128 int /*time_to_render_ms*/) override {
Peter Boström5811a392015-12-10 13:02:50 +0100129 event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000130 }
131
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000132 bool IsTextureSupported() const override { return false; }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000133
Peter Boström5811a392015-12-10 13:02:50 +0100134 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000135
Peter Boström5811a392015-12-10 13:02:50 +0100136 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000137 } renderer;
138
139 class TestFrameCallback : public I420FrameCallback {
140 public:
Peter Boström5811a392015-12-10 13:02:50 +0100141 TestFrameCallback() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000142
Peter Boström5811a392015-12-10 13:02:50 +0100143 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000144
145 private:
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700146 void FrameCallback(VideoFrame* frame) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000147 SleepMs(kDelayRenderCallbackMs);
Peter Boström5811a392015-12-10 13:02:50 +0100148 event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000149 }
150
Peter Boström5811a392015-12-10 13:02:50 +0100151 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000152 };
153
solenberg4fbae2b2015-08-28 04:07:10 -0700154 CreateCalls(Call::Config(), Call::Config());
155
stefanf116bd02015-10-27 08:29:42 -0700156 test::DirectTransport sender_transport(sender_call_.get());
157 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000158 sender_transport.SetReceiver(receiver_call_->Receiver());
159 receiver_transport.SetReceiver(sender_call_->Receiver());
160
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100161 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700162 CreateMatchingReceiveConfigs(&receiver_transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000163
164 TestFrameCallback pre_render_callback;
stefanff483612015-12-21 03:14:00 -0800165 video_receive_configs_[0].pre_render_callback = &pre_render_callback;
166 video_receive_configs_[0].renderer = &renderer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000167
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100168 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000169 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000170
171 // Create frames that are smaller than the send width/height, this is done to
172 // check that the callbacks are done after processing video.
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000173 rtc::scoped_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +0000174 test::FrameGenerator::CreateChromaGenerator(kWidth, kHeight));
stefanff483612015-12-21 03:14:00 -0800175 video_send_stream_->Input()->IncomingCapturedFrame(
176 *frame_generator->NextFrame());
Peter Boström5811a392015-12-10 13:02:50 +0100177 EXPECT_TRUE(pre_render_callback.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000178 << "Timed out while waiting for pre-render callback.";
Peter Boström5811a392015-12-10 13:02:50 +0100179 EXPECT_TRUE(renderer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000180 << "Timed out while waiting for the frame to render.";
181
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000182 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000183
184 sender_transport.StopSending();
185 receiver_transport.StopSending();
186
187 DestroyStreams();
188}
189
190TEST_F(EndToEndTest, TransmitsFirstFrame) {
191 class Renderer : public VideoRenderer {
192 public:
Peter Boström5811a392015-12-10 13:02:50 +0100193 Renderer() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000194
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700195 void RenderFrame(const VideoFrame& video_frame,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000196 int /*time_to_render_ms*/) override {
Peter Boström5811a392015-12-10 13:02:50 +0100197 event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000198 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000199 bool IsTextureSupported() const override { return false; }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000200
Peter Boström5811a392015-12-10 13:02:50 +0100201 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000202
Peter Boström5811a392015-12-10 13:02:50 +0100203 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000204 } renderer;
205
solenberg4fbae2b2015-08-28 04:07:10 -0700206 CreateCalls(Call::Config(), Call::Config());
207
stefanf116bd02015-10-27 08:29:42 -0700208 test::DirectTransport sender_transport(sender_call_.get());
209 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000210 sender_transport.SetReceiver(receiver_call_->Receiver());
211 receiver_transport.SetReceiver(sender_call_->Receiver());
212
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100213 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700214 CreateMatchingReceiveConfigs(&receiver_transport);
stefanff483612015-12-21 03:14:00 -0800215 video_receive_configs_[0].renderer = &renderer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000216
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100217 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000218 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000219
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000220 rtc::scoped_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +0000221 test::FrameGenerator::CreateChromaGenerator(
stefanff483612015-12-21 03:14:00 -0800222 video_encoder_config_.streams[0].width,
223 video_encoder_config_.streams[0].height));
224 video_send_stream_->Input()->IncomingCapturedFrame(
225 *frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000226
Peter Boström5811a392015-12-10 13:02:50 +0100227 EXPECT_TRUE(renderer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000228 << "Timed out while waiting for the frame to render.";
229
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000230 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000231
232 sender_transport.StopSending();
233 receiver_transport.StopSending();
234
235 DestroyStreams();
236}
237
marpan@webrtc.org5f1e2e42014-11-06 02:02:28 +0000238TEST_F(EndToEndTest, SendsAndReceivesVP9) {
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000239 class VP9Observer : public test::EndToEndTest, public VideoRenderer {
240 public:
241 VP9Observer()
242 : EndToEndTest(2 * kDefaultTimeoutMs),
243 encoder_(VideoEncoder::Create(VideoEncoder::kVp9)),
244 decoder_(VP9Decoder::Create()),
245 frame_counter_(0) {}
246
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000247 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100248 EXPECT_TRUE(Wait())
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000249 << "Timed out while waiting for enough frames to be decoded.";
250 }
251
stefanff483612015-12-21 03:14:00 -0800252 void ModifyVideoConfigs(
253 VideoSendStream::Config* send_config,
254 std::vector<VideoReceiveStream::Config>* receive_configs,
255 VideoEncoderConfig* encoder_config) override {
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000256 send_config->encoder_settings.encoder = encoder_.get();
257 send_config->encoder_settings.payload_name = "VP9";
pbosa7d70542015-07-07 07:35:49 -0700258 send_config->encoder_settings.payload_type = 124;
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000259 encoder_config->streams[0].min_bitrate_bps = 50000;
260 encoder_config->streams[0].target_bitrate_bps =
261 encoder_config->streams[0].max_bitrate_bps = 2000000;
262
263 (*receive_configs)[0].renderer = this;
264 (*receive_configs)[0].decoders.resize(1);
265 (*receive_configs)[0].decoders[0].payload_type =
266 send_config->encoder_settings.payload_type;
267 (*receive_configs)[0].decoders[0].payload_name =
268 send_config->encoder_settings.payload_name;
269 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
270 }
271
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700272 void RenderFrame(const VideoFrame& video_frame,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000273 int time_to_render_ms) override {
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000274 const int kRequiredFrames = 500;
275 if (++frame_counter_ == kRequiredFrames)
Peter Boström5811a392015-12-10 13:02:50 +0100276 observation_complete_.Set();
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000277 }
278
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000279 bool IsTextureSupported() const override { return false; }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000280
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000281 private:
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000282 rtc::scoped_ptr<webrtc::VideoEncoder> encoder_;
283 rtc::scoped_ptr<webrtc::VideoDecoder> decoder_;
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000284 int frame_counter_;
285 } test;
286
stefane74eef12016-01-08 06:47:13 -0800287 RunBaseTest(&test);
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000288}
289
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000290TEST_F(EndToEndTest, SendsAndReceivesH264) {
291 class H264Observer : public test::EndToEndTest, public VideoRenderer {
292 public:
293 H264Observer()
294 : EndToEndTest(2 * kDefaultTimeoutMs),
295 fake_encoder_(Clock::GetRealTimeClock()),
296 frame_counter_(0) {}
297
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000298 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100299 EXPECT_TRUE(Wait())
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000300 << "Timed out while waiting for enough frames to be decoded.";
301 }
302
stefanff483612015-12-21 03:14:00 -0800303 void ModifyVideoConfigs(
304 VideoSendStream::Config* send_config,
305 std::vector<VideoReceiveStream::Config>* receive_configs,
306 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org8278c072015-02-23 11:11:49 +0000307 send_config->rtp.nack.rtp_history_ms =
308 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000309 send_config->encoder_settings.encoder = &fake_encoder_;
310 send_config->encoder_settings.payload_name = "H264";
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100311 send_config->encoder_settings.payload_type = kFakeVideoSendPayloadType;
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +0000312 encoder_config->streams[0].min_bitrate_bps = 50000;
313 encoder_config->streams[0].target_bitrate_bps =
314 encoder_config->streams[0].max_bitrate_bps = 2000000;
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000315
316 (*receive_configs)[0].renderer = this;
pbos@webrtc.org776e6f22014-10-29 15:28:39 +0000317 (*receive_configs)[0].decoders.resize(1);
318 (*receive_configs)[0].decoders[0].payload_type =
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000319 send_config->encoder_settings.payload_type;
pbos@webrtc.org776e6f22014-10-29 15:28:39 +0000320 (*receive_configs)[0].decoders[0].payload_name =
321 send_config->encoder_settings.payload_name;
322 (*receive_configs)[0].decoders[0].decoder = &fake_decoder_;
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000323 }
324
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700325 void RenderFrame(const VideoFrame& video_frame,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000326 int time_to_render_ms) override {
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000327 const int kRequiredFrames = 500;
328 if (++frame_counter_ == kRequiredFrames)
Peter Boström5811a392015-12-10 13:02:50 +0100329 observation_complete_.Set();
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000330 }
331
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000332 bool IsTextureSupported() const override { return false; }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000333
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000334 private:
335 test::FakeH264Decoder fake_decoder_;
336 test::FakeH264Encoder fake_encoder_;
337 int frame_counter_;
338 } test;
339
stefane74eef12016-01-08 06:47:13 -0800340 RunBaseTest(&test);
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000341}
342
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000343TEST_F(EndToEndTest, ReceiverUsesLocalSsrc) {
344 class SyncRtcpObserver : public test::EndToEndTest {
345 public:
346 SyncRtcpObserver() : EndToEndTest(kDefaultTimeoutMs) {}
347
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000348 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000349 RTCPUtility::RTCPParserV2 parser(packet, length, true);
350 EXPECT_TRUE(parser.IsValid());
351 uint32_t ssrc = 0;
352 ssrc |= static_cast<uint32_t>(packet[4]) << 24;
353 ssrc |= static_cast<uint32_t>(packet[5]) << 16;
354 ssrc |= static_cast<uint32_t>(packet[6]) << 8;
355 ssrc |= static_cast<uint32_t>(packet[7]) << 0;
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100356 EXPECT_EQ(kReceiverLocalVideoSsrc, ssrc);
Peter Boström5811a392015-12-10 13:02:50 +0100357 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000358
359 return SEND_PACKET;
360 }
361
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000362 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100363 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000364 << "Timed out while waiting for a receiver RTCP packet to be sent.";
365 }
366 } test;
367
stefane74eef12016-01-08 06:47:13 -0800368 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000369}
370
371TEST_F(EndToEndTest, ReceivesAndRetransmitsNack) {
372 static const int kNumberOfNacksToObserve = 2;
373 static const int kLossBurstSize = 2;
374 static const int kPacketsBetweenLossBursts = 9;
375 class NackObserver : public test::EndToEndTest {
376 public:
377 NackObserver()
378 : EndToEndTest(kLongTimeoutMs),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000379 sent_rtp_packets_(0),
380 packets_left_to_drop_(0),
381 nacks_left_(kNumberOfNacksToObserve) {}
382
383 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000384 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700385 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000386 RTPHeader header;
Peter Boström03671cb2015-12-07 15:22:24 +0100387 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000388
389 // Never drop retransmitted packets.
390 if (dropped_packets_.find(header.sequenceNumber) !=
391 dropped_packets_.end()) {
392 retransmitted_packets_.insert(header.sequenceNumber);
Stefan Holmer586b19b2015-09-18 11:14:31 +0200393 if (nacks_left_ <= 0 &&
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000394 retransmitted_packets_.size() == dropped_packets_.size()) {
Peter Boström5811a392015-12-10 13:02:50 +0100395 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000396 }
397 return SEND_PACKET;
398 }
399
400 ++sent_rtp_packets_;
401
402 // Enough NACKs received, stop dropping packets.
Stefan Holmer586b19b2015-09-18 11:14:31 +0200403 if (nacks_left_ <= 0)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000404 return SEND_PACKET;
405
406 // Check if it's time for a new loss burst.
407 if (sent_rtp_packets_ % kPacketsBetweenLossBursts == 0)
408 packets_left_to_drop_ = kLossBurstSize;
409
Stefan Holmer01b48882015-05-05 10:21:24 +0200410 // Never drop padding packets as those won't be retransmitted.
411 if (packets_left_to_drop_ > 0 && header.paddingLength == 0) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000412 --packets_left_to_drop_;
413 dropped_packets_.insert(header.sequenceNumber);
414 return DROP_PACKET;
415 }
416
417 return SEND_PACKET;
418 }
419
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000420 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700421 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000422 RTCPUtility::RTCPParserV2 parser(packet, length, true);
423 EXPECT_TRUE(parser.IsValid());
424
425 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +0200426 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
427 if (packet_type == RTCPUtility::RTCPPacketTypes::kRtpfbNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000428 --nacks_left_;
429 break;
430 }
431 packet_type = parser.Iterate();
432 }
433 return SEND_PACKET;
434 }
435
stefanff483612015-12-21 03:14:00 -0800436 void ModifyVideoConfigs(
437 VideoSendStream::Config* send_config,
438 std::vector<VideoReceiveStream::Config>* receive_configs,
439 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000440 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000441 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000442 }
443
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000444 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100445 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000446 << "Timed out waiting for packets to be NACKed, retransmitted and "
447 "rendered.";
448 }
449
stefanf116bd02015-10-27 08:29:42 -0700450 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000451 std::set<uint16_t> dropped_packets_;
452 std::set<uint16_t> retransmitted_packets_;
453 uint64_t sent_rtp_packets_;
454 int packets_left_to_drop_;
stefanf116bd02015-10-27 08:29:42 -0700455 int nacks_left_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000456 } test;
457
stefane74eef12016-01-08 06:47:13 -0800458 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000459}
460
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000461TEST_F(EndToEndTest, CanReceiveFec) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000462 class FecRenderObserver : public test::EndToEndTest, public VideoRenderer {
463 public:
464 FecRenderObserver()
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000465 : EndToEndTest(kDefaultTimeoutMs), state_(kFirstPacket) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000466
467 private:
stefanf116bd02015-10-27 08:29:42 -0700468 Action OnSendRtp(const uint8_t* packet, size_t length) override {
469 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000470 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000471 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000472
Stefan Holmer01b48882015-05-05 10:21:24 +0200473 int encapsulated_payload_type = -1;
474 if (header.payloadType == kRedPayloadType) {
475 encapsulated_payload_type =
476 static_cast<int>(packet[header.headerLength]);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100477 if (encapsulated_payload_type != kFakeVideoSendPayloadType)
Stefan Holmer01b48882015-05-05 10:21:24 +0200478 EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
479 } else {
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100480 EXPECT_EQ(kFakeVideoSendPayloadType, header.payloadType);
Stefan Holmer01b48882015-05-05 10:21:24 +0200481 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000482
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000483 if (protected_sequence_numbers_.count(header.sequenceNumber) != 0) {
484 // Retransmitted packet, should not count.
485 protected_sequence_numbers_.erase(header.sequenceNumber);
486 EXPECT_GT(protected_timestamps_.count(header.timestamp), 0u);
487 protected_timestamps_.erase(header.timestamp);
488 return SEND_PACKET;
489 }
490
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000491 switch (state_) {
492 case kFirstPacket:
493 state_ = kDropEveryOtherPacketUntilFec;
494 break;
495 case kDropEveryOtherPacketUntilFec:
496 if (encapsulated_payload_type == kUlpfecPayloadType) {
497 state_ = kDropNextMediaPacket;
498 return SEND_PACKET;
499 }
500 if (header.sequenceNumber % 2 == 0)
501 return DROP_PACKET;
502 break;
503 case kDropNextMediaPacket:
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100504 if (encapsulated_payload_type == kFakeVideoSendPayloadType) {
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000505 protected_sequence_numbers_.insert(header.sequenceNumber);
506 protected_timestamps_.insert(header.timestamp);
507 state_ = kDropEveryOtherPacketUntilFec;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000508 return DROP_PACKET;
509 }
510 break;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000511 }
512
513 return SEND_PACKET;
514 }
515
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700516 void RenderFrame(const VideoFrame& video_frame,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000517 int time_to_render_ms) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200518 rtc::CritScope lock(&crit_);
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000519 // Rendering frame with timestamp of packet that was dropped -> FEC
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000520 // protection worked.
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000521 if (protected_timestamps_.count(video_frame.timestamp()) != 0)
Peter Boström5811a392015-12-10 13:02:50 +0100522 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000523 }
524
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000525 bool IsTextureSupported() const override { return false; }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000526
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000527 enum {
528 kFirstPacket,
529 kDropEveryOtherPacketUntilFec,
530 kDropNextMediaPacket,
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000531 } state_;
532
stefanff483612015-12-21 03:14:00 -0800533 void ModifyVideoConfigs(
534 VideoSendStream::Config* send_config,
535 std::vector<VideoReceiveStream::Config>* receive_configs,
536 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000537 // TODO(pbos): Run this test with combined NACK/FEC enabled as well.
538 // int rtp_history_ms = 1000;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000539 // (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000540 // send_config->rtp.nack.rtp_history_ms = rtp_history_ms;
541 send_config->rtp.fec.red_payload_type = kRedPayloadType;
542 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
543
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000544 (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
545 (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
546 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000547 }
548
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000549 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100550 EXPECT_TRUE(Wait())
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000551 << "Timed out waiting for dropped frames frames to be rendered.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000552 }
553
stefanf116bd02015-10-27 08:29:42 -0700554 rtc::CriticalSection crit_;
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000555 std::set<uint32_t> protected_sequence_numbers_ GUARDED_BY(crit_);
556 std::set<uint32_t> protected_timestamps_ GUARDED_BY(crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000557 } test;
558
stefane74eef12016-01-08 06:47:13 -0800559 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000560}
561
Henrik Kjellanderdb313b62015-04-02 08:45:41 +0200562// Flacky on all platforms. See webrtc:4328.
563TEST_F(EndToEndTest, DISABLED_ReceivedFecPacketsNotNacked) {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000564 class FecNackObserver : public test::EndToEndTest {
565 public:
mflodmand1590b22015-12-09 07:07:59 -0800566 FecNackObserver()
stefanf116bd02015-10-27 08:29:42 -0700567 : EndToEndTest(kDefaultTimeoutMs),
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000568 state_(kFirstPacket),
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000569 fec_sequence_number_(0),
570 has_last_sequence_number_(false),
571 last_sequence_number_(0) {}
572
573 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000574 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -0800575 rtc::CritScope lock_(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000576 RTPHeader header;
577 EXPECT_TRUE(parser_->Parse(packet, length, &header));
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000578
Stefan Holmer01b48882015-05-05 10:21:24 +0200579 int encapsulated_payload_type = -1;
580 if (header.payloadType == kRedPayloadType) {
581 encapsulated_payload_type =
582 static_cast<int>(packet[header.headerLength]);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100583 if (encapsulated_payload_type != kFakeVideoSendPayloadType)
Stefan Holmer01b48882015-05-05 10:21:24 +0200584 EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
585 } else {
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100586 EXPECT_EQ(kFakeVideoSendPayloadType, header.payloadType);
Stefan Holmer01b48882015-05-05 10:21:24 +0200587 }
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000588
589 if (has_last_sequence_number_ &&
590 !IsNewerSequenceNumber(header.sequenceNumber,
591 last_sequence_number_)) {
592 // Drop retransmitted packets.
593 return DROP_PACKET;
594 }
595 last_sequence_number_ = header.sequenceNumber;
596 has_last_sequence_number_ = true;
597
598 bool fec_packet = encapsulated_payload_type == kUlpfecPayloadType;
599 switch (state_) {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000600 case kFirstPacket:
601 state_ = kDropEveryOtherPacketUntilFec;
602 break;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000603 case kDropEveryOtherPacketUntilFec:
604 if (fec_packet) {
605 state_ = kDropAllMediaPacketsUntilFec;
606 } else if (header.sequenceNumber % 2 == 0) {
607 return DROP_PACKET;
608 }
609 break;
610 case kDropAllMediaPacketsUntilFec:
611 if (!fec_packet)
612 return DROP_PACKET;
613 fec_sequence_number_ = header.sequenceNumber;
614 state_ = kVerifyFecPacketNotInNackList;
615 break;
616 case kVerifyFecPacketNotInNackList:
617 // Continue to drop packets. Make sure no frame can be decoded.
618 if (fec_packet || header.sequenceNumber % 2 == 0)
619 return DROP_PACKET;
620 break;
621 }
622 return SEND_PACKET;
623 }
624
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000625 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -0800626 rtc::CritScope lock_(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000627 if (state_ == kVerifyFecPacketNotInNackList) {
628 test::RtcpPacketParser rtcp_parser;
629 rtcp_parser.Parse(packet, length);
630 std::vector<uint16_t> nacks = rtcp_parser.nack_item()->last_nack_list();
631 if (!nacks.empty() &&
632 IsNewerSequenceNumber(nacks.back(), fec_sequence_number_)) {
633 EXPECT_TRUE(std::find(
634 nacks.begin(), nacks.end(), fec_sequence_number_) == nacks.end());
Peter Boström5811a392015-12-10 13:02:50 +0100635 observation_complete_.Set();
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000636 }
637 }
638 return SEND_PACKET;
639 }
640
stefane74eef12016-01-08 06:47:13 -0800641 test::PacketTransport* CreateSendTransport(Call* sender_call) override {
642 // At low RTT (< kLowRttNackMs) -> NACK only, no FEC.
643 // Configure some network delay.
644 const int kNetworkDelayMs = 50;
645 FakeNetworkPipe::Config config;
646 config.queue_delay_ms = kNetworkDelayMs;
647 return new test::PacketTransport(sender_call, this,
648 test::PacketTransport::kSender, config);
649 }
650
Stefan Holmere5904162015-03-26 11:11:06 +0100651 // TODO(holmer): Investigate why we don't send FEC packets when the bitrate
652 // is 10 kbps.
653 Call::Config GetSenderCallConfig() override {
solenberg4fbae2b2015-08-28 04:07:10 -0700654 Call::Config config;
Stefan Holmere5904162015-03-26 11:11:06 +0100655 const int kMinBitrateBps = 30000;
656 config.bitrate_config.min_bitrate_bps = kMinBitrateBps;
657 return config;
658 }
659
stefanff483612015-12-21 03:14:00 -0800660 void ModifyVideoConfigs(
661 VideoSendStream::Config* send_config,
662 std::vector<VideoReceiveStream::Config>* receive_configs,
663 VideoEncoderConfig* encoder_config) override {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000664 // Configure hybrid NACK/FEC.
665 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
666 send_config->rtp.fec.red_payload_type = kRedPayloadType;
667 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
668 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
669 (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
670 (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
671 }
672
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000673 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100674 EXPECT_TRUE(Wait())
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000675 << "Timed out while waiting for FEC packets to be received.";
676 }
677
678 enum {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000679 kFirstPacket,
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000680 kDropEveryOtherPacketUntilFec,
681 kDropAllMediaPacketsUntilFec,
682 kVerifyFecPacketNotInNackList,
683 } state_;
684
stefan608213e2015-11-01 14:56:10 -0800685 rtc::CriticalSection crit_;
686 uint16_t fec_sequence_number_ GUARDED_BY(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000687 bool has_last_sequence_number_;
688 uint16_t last_sequence_number_;
stefanf116bd02015-10-27 08:29:42 -0700689 } test;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000690
stefane74eef12016-01-08 06:47:13 -0800691 RunBaseTest(&test);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000692}
693
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000694// This test drops second RTP packet with a marker bit set, makes sure it's
695// retransmitted and renders. Retransmission SSRCs are also checked.
Shao Changbine62202f2015-04-21 20:24:50 +0800696void EndToEndTest::DecodesRetransmittedFrame(bool use_rtx, bool use_red) {
Stefan Holmer586b19b2015-09-18 11:14:31 +0200697 // Must be set high enough to allow the bitrate probing to finish.
698 static const int kMinProbePackets = 30;
699 static const int kDroppedFrameNumber = kMinProbePackets + 1;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000700 class RetransmissionObserver : public test::EndToEndTest,
701 public I420FrameCallback {
702 public:
Shao Changbine62202f2015-04-21 20:24:50 +0800703 explicit RetransmissionObserver(bool use_rtx, bool use_red)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000704 : EndToEndTest(kDefaultTimeoutMs),
Shao Changbine62202f2015-04-21 20:24:50 +0800705 payload_type_(GetPayloadType(false, use_red)),
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100706 retransmission_ssrc_(use_rtx ? kSendRtxSsrcs[0] : kVideoSendSsrcs[0]),
Shao Changbine62202f2015-04-21 20:24:50 +0800707 retransmission_payload_type_(GetPayloadType(use_rtx, use_red)),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000708 marker_bits_observed_(0),
Stefan Holmer586b19b2015-09-18 11:14:31 +0200709 num_packets_observed_(0),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000710 retransmitted_timestamp_(0),
711 frame_retransmitted_(false) {}
712
713 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000714 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700715 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000716 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000717 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000718
Stefan Holmer586b19b2015-09-18 11:14:31 +0200719 // We accept some padding or RTX packets in the beginning to enable
720 // bitrate probing.
721 if (num_packets_observed_++ < kMinProbePackets &&
722 header.payloadType != payload_type_) {
723 EXPECT_TRUE(retransmission_payload_type_ == header.payloadType ||
724 length == header.headerLength + header.paddingLength);
725 return SEND_PACKET;
726 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000727 if (header.timestamp == retransmitted_timestamp_) {
728 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
729 EXPECT_EQ(retransmission_payload_type_, header.payloadType);
730 frame_retransmitted_ = true;
731 return SEND_PACKET;
732 }
733
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100734 EXPECT_EQ(kVideoSendSsrcs[0], header.ssrc);
Shao Changbine62202f2015-04-21 20:24:50 +0800735 EXPECT_EQ(payload_type_, header.payloadType);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000736
Stefan Holmer586b19b2015-09-18 11:14:31 +0200737 // Found the final packet of the frame to inflict loss to, drop this and
738 // expect a retransmission.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000739 if (header.markerBit && ++marker_bits_observed_ == kDroppedFrameNumber) {
740 retransmitted_timestamp_ = header.timestamp;
741 return DROP_PACKET;
742 }
743
744 return SEND_PACKET;
745 }
746
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700747 void FrameCallback(VideoFrame* frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200748 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000749 if (frame->timestamp() == retransmitted_timestamp_) {
750 EXPECT_TRUE(frame_retransmitted_);
Peter Boström5811a392015-12-10 13:02:50 +0100751 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000752 }
753 }
754
stefanff483612015-12-21 03:14:00 -0800755 void ModifyVideoConfigs(
756 VideoSendStream::Config* send_config,
757 std::vector<VideoReceiveStream::Config>* receive_configs,
758 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000759 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000760 (*receive_configs)[0].pre_render_callback = this;
761 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
Shao Changbine62202f2015-04-21 20:24:50 +0800762
763 if (payload_type_ == kRedPayloadType) {
764 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
765 send_config->rtp.fec.red_payload_type = kRedPayloadType;
766 (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
767 (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
768 }
769
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000770 if (retransmission_ssrc_ == kSendRtxSsrcs[0]) {
771 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000772 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100773 (*receive_configs)[0].rtp.rtx[kFakeVideoSendPayloadType].ssrc =
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000774 kSendRtxSsrcs[0];
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100775 (*receive_configs)[0].rtp.rtx[kFakeVideoSendPayloadType].payload_type =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000776 kSendRtxPayloadType;
777 }
778 }
779
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000780 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100781 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000782 << "Timed out while waiting for retransmission to render.";
783 }
784
Shao Changbine62202f2015-04-21 20:24:50 +0800785 int GetPayloadType(bool use_rtx, bool use_red) {
786 return use_rtx ? kSendRtxPayloadType
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100787 : (use_red ? kRedPayloadType : kFakeVideoSendPayloadType);
Shao Changbine62202f2015-04-21 20:24:50 +0800788 }
789
stefanf116bd02015-10-27 08:29:42 -0700790 rtc::CriticalSection crit_;
Shao Changbine62202f2015-04-21 20:24:50 +0800791 const int payload_type_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000792 const uint32_t retransmission_ssrc_;
793 const int retransmission_payload_type_;
794 int marker_bits_observed_;
Stefan Holmer586b19b2015-09-18 11:14:31 +0200795 int num_packets_observed_;
stefanf116bd02015-10-27 08:29:42 -0700796 uint32_t retransmitted_timestamp_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000797 bool frame_retransmitted_;
Shao Changbine62202f2015-04-21 20:24:50 +0800798 } test(use_rtx, use_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000799
stefane74eef12016-01-08 06:47:13 -0800800 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000801}
802
803TEST_F(EndToEndTest, DecodesRetransmittedFrame) {
Shao Changbine62202f2015-04-21 20:24:50 +0800804 DecodesRetransmittedFrame(false, false);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000805}
806
807TEST_F(EndToEndTest, DecodesRetransmittedFrameOverRtx) {
Shao Changbine62202f2015-04-21 20:24:50 +0800808 DecodesRetransmittedFrame(true, false);
809}
810
811TEST_F(EndToEndTest, DecodesRetransmittedFrameByRed) {
812 DecodesRetransmittedFrame(false, true);
813}
814
815TEST_F(EndToEndTest, DecodesRetransmittedFrameByRedOverRtx) {
816 DecodesRetransmittedFrame(true, true);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000817}
818
andresp@webrtc.org02686112014-09-19 08:24:19 +0000819TEST_F(EndToEndTest, UsesFrameCallbacks) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000820 static const int kWidth = 320;
821 static const int kHeight = 240;
822
823 class Renderer : public VideoRenderer {
824 public:
Peter Boström5811a392015-12-10 13:02:50 +0100825 Renderer() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000826
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700827 void RenderFrame(const VideoFrame& video_frame,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000828 int /*time_to_render_ms*/) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000829 EXPECT_EQ(0, *video_frame.buffer(kYPlane))
830 << "Rendered frame should have zero luma which is applied by the "
831 "pre-render callback.";
Peter Boström5811a392015-12-10 13:02:50 +0100832 event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000833 }
834
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000835 bool IsTextureSupported() const override { return false; }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000836
Peter Boström5811a392015-12-10 13:02:50 +0100837 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
838 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000839 } renderer;
840
841 class TestFrameCallback : public I420FrameCallback {
842 public:
843 TestFrameCallback(int expected_luma_byte, int next_luma_byte)
Peter Boström5811a392015-12-10 13:02:50 +0100844 : event_(false, false),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000845 expected_luma_byte_(expected_luma_byte),
846 next_luma_byte_(next_luma_byte) {}
847
Peter Boström5811a392015-12-10 13:02:50 +0100848 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000849
850 private:
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700851 virtual void FrameCallback(VideoFrame* frame) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000852 EXPECT_EQ(kWidth, frame->width())
853 << "Width not as expected, callback done before resize?";
854 EXPECT_EQ(kHeight, frame->height())
855 << "Height not as expected, callback done before resize?";
856
857 // Previous luma specified, observed luma should be fairly close.
858 if (expected_luma_byte_ != -1) {
859 EXPECT_NEAR(expected_luma_byte_, *frame->buffer(kYPlane), 10);
860 }
861
862 memset(frame->buffer(kYPlane),
863 next_luma_byte_,
864 frame->allocated_size(kYPlane));
865
Peter Boström5811a392015-12-10 13:02:50 +0100866 event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000867 }
868
Peter Boström5811a392015-12-10 13:02:50 +0100869 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000870 int expected_luma_byte_;
871 int next_luma_byte_;
872 };
873
874 TestFrameCallback pre_encode_callback(-1, 255); // Changes luma to 255.
875 TestFrameCallback pre_render_callback(255, 0); // Changes luma from 255 to 0.
876
solenberg4fbae2b2015-08-28 04:07:10 -0700877 CreateCalls(Call::Config(), Call::Config());
878
stefanf116bd02015-10-27 08:29:42 -0700879 test::DirectTransport sender_transport(sender_call_.get());
880 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000881 sender_transport.SetReceiver(receiver_call_->Receiver());
882 receiver_transport.SetReceiver(sender_call_->Receiver());
883
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100884 CreateSendConfig(1, 0, &sender_transport);
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000885 rtc::scoped_ptr<VideoEncoder> encoder(
pbos@webrtc.orgab990ae2014-09-17 09:02:25 +0000886 VideoEncoder::Create(VideoEncoder::kVp8));
stefanff483612015-12-21 03:14:00 -0800887 video_send_config_.encoder_settings.encoder = encoder.get();
888 video_send_config_.encoder_settings.payload_name = "VP8";
889 ASSERT_EQ(1u, video_encoder_config_.streams.size()) << "Test setup error.";
890 video_encoder_config_.streams[0].width = kWidth;
891 video_encoder_config_.streams[0].height = kHeight;
892 video_send_config_.pre_encode_callback = &pre_encode_callback;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000893
solenberg4fbae2b2015-08-28 04:07:10 -0700894 CreateMatchingReceiveConfigs(&receiver_transport);
stefanff483612015-12-21 03:14:00 -0800895 video_receive_configs_[0].pre_render_callback = &pre_render_callback;
896 video_receive_configs_[0].renderer = &renderer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000897
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100898 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000899 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000900
901 // Create frames that are smaller than the send width/height, this is done to
902 // check that the callbacks are done after processing video.
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000903 rtc::scoped_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +0000904 test::FrameGenerator::CreateChromaGenerator(kWidth / 2, kHeight / 2));
stefanff483612015-12-21 03:14:00 -0800905 video_send_stream_->Input()->IncomingCapturedFrame(
906 *frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000907
Peter Boström5811a392015-12-10 13:02:50 +0100908 EXPECT_TRUE(pre_encode_callback.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000909 << "Timed out while waiting for pre-encode callback.";
Peter Boström5811a392015-12-10 13:02:50 +0100910 EXPECT_TRUE(pre_render_callback.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000911 << "Timed out while waiting for pre-render callback.";
Peter Boström5811a392015-12-10 13:02:50 +0100912 EXPECT_TRUE(renderer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000913 << "Timed out while waiting for the frame to render.";
914
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000915 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000916
917 sender_transport.StopSending();
918 receiver_transport.StopSending();
919
920 DestroyStreams();
921}
922
923void EndToEndTest::ReceivesPliAndRecovers(int rtp_history_ms) {
924 static const int kPacketsToDrop = 1;
925
926 class PliObserver : public test::EndToEndTest, public VideoRenderer {
927 public:
928 explicit PliObserver(int rtp_history_ms)
929 : EndToEndTest(kLongTimeoutMs),
930 rtp_history_ms_(rtp_history_ms),
931 nack_enabled_(rtp_history_ms > 0),
932 highest_dropped_timestamp_(0),
933 frames_to_drop_(0),
934 received_pli_(false) {}
935
936 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000937 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700938 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000939 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000940 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000941
942 // Drop all retransmitted packets to force a PLI.
943 if (header.timestamp <= highest_dropped_timestamp_)
944 return DROP_PACKET;
945
946 if (frames_to_drop_ > 0) {
947 highest_dropped_timestamp_ = header.timestamp;
948 --frames_to_drop_;
949 return DROP_PACKET;
950 }
951
952 return SEND_PACKET;
953 }
954
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000955 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700956 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000957 RTCPUtility::RTCPParserV2 parser(packet, length, true);
958 EXPECT_TRUE(parser.IsValid());
959
960 for (RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +0200961 packet_type != RTCPUtility::RTCPPacketTypes::kInvalid;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000962 packet_type = parser.Iterate()) {
963 if (!nack_enabled_)
Erik Språng242e22b2015-05-11 10:17:43 +0200964 EXPECT_NE(packet_type, RTCPUtility::RTCPPacketTypes::kRtpfbNack);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000965
Erik Språng242e22b2015-05-11 10:17:43 +0200966 if (packet_type == RTCPUtility::RTCPPacketTypes::kPsfbPli) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000967 received_pli_ = true;
968 break;
969 }
970 }
971 return SEND_PACKET;
972 }
973
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700974 void RenderFrame(const VideoFrame& video_frame,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000975 int time_to_render_ms) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200976 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000977 if (received_pli_ &&
978 video_frame.timestamp() > highest_dropped_timestamp_) {
Peter Boström5811a392015-12-10 13:02:50 +0100979 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000980 }
981 if (!received_pli_)
982 frames_to_drop_ = kPacketsToDrop;
983 }
984
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000985 bool IsTextureSupported() const override { return false; }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000986
stefanff483612015-12-21 03:14:00 -0800987 void ModifyVideoConfigs(
988 VideoSendStream::Config* send_config,
989 std::vector<VideoReceiveStream::Config>* receive_configs,
990 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000991 send_config->rtp.nack.rtp_history_ms = rtp_history_ms_;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000992 (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms_;
993 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000994 }
995
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000996 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100997 EXPECT_TRUE(Wait()) << "Timed out waiting for PLI to be "
998 "received and a frame to be "
999 "rendered afterwards.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001000 }
1001
stefanf116bd02015-10-27 08:29:42 -07001002 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001003 int rtp_history_ms_;
1004 bool nack_enabled_;
stefanf116bd02015-10-27 08:29:42 -07001005 uint32_t highest_dropped_timestamp_ GUARDED_BY(&crit_);
1006 int frames_to_drop_ GUARDED_BY(&crit_);
1007 bool received_pli_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001008 } test(rtp_history_ms);
1009
stefane74eef12016-01-08 06:47:13 -08001010 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001011}
1012
1013TEST_F(EndToEndTest, ReceivesPliAndRecoversWithNack) {
1014 ReceivesPliAndRecovers(1000);
1015}
1016
jbauchdb81ffd2015-11-23 03:59:02 -08001017TEST_F(EndToEndTest, ReceivesPliAndRecoversWithoutNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001018 ReceivesPliAndRecovers(0);
1019}
1020
1021TEST_F(EndToEndTest, UnknownRtpPacketGivesUnknownSsrcReturnCode) {
1022 class PacketInputObserver : public PacketReceiver {
1023 public:
1024 explicit PacketInputObserver(PacketReceiver* receiver)
Peter Boström5811a392015-12-10 13:02:50 +01001025 : receiver_(receiver), delivered_packet_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001026
Peter Boström5811a392015-12-10 13:02:50 +01001027 bool Wait() { return delivered_packet_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001028
1029 private:
stefan68786d22015-09-08 05:36:15 -07001030 DeliveryStatus DeliverPacket(MediaType media_type,
1031 const uint8_t* packet,
1032 size_t length,
1033 const PacketTime& packet_time) override {
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001034 if (RtpHeaderParser::IsRtcp(packet, length)) {
stefan68786d22015-09-08 05:36:15 -07001035 return receiver_->DeliverPacket(media_type, packet, length,
1036 packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001037 } else {
1038 DeliveryStatus delivery_status =
stefan68786d22015-09-08 05:36:15 -07001039 receiver_->DeliverPacket(media_type, packet, length, packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001040 EXPECT_EQ(DELIVERY_UNKNOWN_SSRC, delivery_status);
Peter Boström5811a392015-12-10 13:02:50 +01001041 delivered_packet_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001042 return delivery_status;
1043 }
1044 }
1045
1046 PacketReceiver* receiver_;
Peter Boström5811a392015-12-10 13:02:50 +01001047 rtc::Event delivered_packet_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001048 };
1049
solenberg4fbae2b2015-08-28 04:07:10 -07001050 CreateCalls(Call::Config(), Call::Config());
1051
stefanf116bd02015-10-27 08:29:42 -07001052 test::DirectTransport send_transport(sender_call_.get());
1053 test::DirectTransport receive_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001054 PacketInputObserver input_observer(receiver_call_->Receiver());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001055 send_transport.SetReceiver(&input_observer);
1056 receive_transport.SetReceiver(sender_call_->Receiver());
1057
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001058 CreateSendConfig(1, 0, &send_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07001059 CreateMatchingReceiveConfigs(&receive_transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001060
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001061 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001062 CreateFrameGeneratorCapturer();
1063 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001064
stefanff483612015-12-21 03:14:00 -08001065 receiver_call_->DestroyVideoReceiveStream(video_receive_streams_[0]);
1066 video_receive_streams_.clear();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001067
1068 // Wait() waits for a received packet.
Peter Boström5811a392015-12-10 13:02:50 +01001069 EXPECT_TRUE(input_observer.Wait());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001070
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001071 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001072
1073 DestroyStreams();
1074
1075 send_transport.StopSending();
1076 receive_transport.StopSending();
1077}
1078
pbosda903ea2015-10-02 02:36:56 -07001079void EndToEndTest::RespectsRtcpMode(RtcpMode rtcp_mode) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001080 static const int kNumCompoundRtcpPacketsToObserve = 10;
1081 class RtcpModeObserver : public test::EndToEndTest {
1082 public:
pbosda903ea2015-10-02 02:36:56 -07001083 explicit RtcpModeObserver(RtcpMode rtcp_mode)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001084 : EndToEndTest(kDefaultTimeoutMs),
1085 rtcp_mode_(rtcp_mode),
1086 sent_rtp_(0),
1087 sent_rtcp_(0) {}
1088
1089 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001090 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001091 if (++sent_rtp_ % 3 == 0)
1092 return DROP_PACKET;
1093
1094 return SEND_PACKET;
1095 }
1096
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001097 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001098 ++sent_rtcp_;
1099 RTCPUtility::RTCPParserV2 parser(packet, length, true);
1100 EXPECT_TRUE(parser.IsValid());
1101
1102 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
1103 bool has_report_block = false;
Erik Språng242e22b2015-05-11 10:17:43 +02001104 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
1105 EXPECT_NE(RTCPUtility::RTCPPacketTypes::kSr, packet_type);
1106 if (packet_type == RTCPUtility::RTCPPacketTypes::kRr) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001107 has_report_block = true;
1108 break;
1109 }
1110 packet_type = parser.Iterate();
1111 }
1112
1113 switch (rtcp_mode_) {
pbosda903ea2015-10-02 02:36:56 -07001114 case RtcpMode::kCompound:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001115 if (!has_report_block) {
1116 ADD_FAILURE() << "Received RTCP packet without receiver report for "
pbosda903ea2015-10-02 02:36:56 -07001117 "RtcpMode::kCompound.";
Peter Boström5811a392015-12-10 13:02:50 +01001118 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001119 }
1120
1121 if (sent_rtcp_ >= kNumCompoundRtcpPacketsToObserve)
Peter Boström5811a392015-12-10 13:02:50 +01001122 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001123
1124 break;
pbosda903ea2015-10-02 02:36:56 -07001125 case RtcpMode::kReducedSize:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001126 if (!has_report_block)
Peter Boström5811a392015-12-10 13:02:50 +01001127 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001128 break;
pbosda903ea2015-10-02 02:36:56 -07001129 case RtcpMode::kOff:
1130 RTC_NOTREACHED();
1131 break;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001132 }
1133
1134 return SEND_PACKET;
1135 }
1136
stefanff483612015-12-21 03:14:00 -08001137 void ModifyVideoConfigs(
1138 VideoSendStream::Config* send_config,
1139 std::vector<VideoReceiveStream::Config>* receive_configs,
1140 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001141 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001142 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
1143 (*receive_configs)[0].rtp.rtcp_mode = rtcp_mode_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001144 }
1145
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001146 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001147 EXPECT_TRUE(Wait())
pbosda903ea2015-10-02 02:36:56 -07001148 << (rtcp_mode_ == RtcpMode::kCompound
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001149 ? "Timed out before observing enough compound packets."
1150 : "Timed out before receiving a non-compound RTCP packet.");
1151 }
1152
pbosda903ea2015-10-02 02:36:56 -07001153 RtcpMode rtcp_mode_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001154 int sent_rtp_;
1155 int sent_rtcp_;
1156 } test(rtcp_mode);
1157
stefane74eef12016-01-08 06:47:13 -08001158 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001159}
1160
1161TEST_F(EndToEndTest, UsesRtcpCompoundMode) {
pbosda903ea2015-10-02 02:36:56 -07001162 RespectsRtcpMode(RtcpMode::kCompound);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001163}
1164
1165TEST_F(EndToEndTest, UsesRtcpReducedSizeMode) {
pbosda903ea2015-10-02 02:36:56 -07001166 RespectsRtcpMode(RtcpMode::kReducedSize);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001167}
1168
1169// Test sets up a Call multiple senders with different resolutions and SSRCs.
1170// Another is set up to receive all three of these with different renderers.
sprang867fb522015-08-03 04:38:41 -07001171class MultiStreamTest {
1172 public:
1173 static const size_t kNumStreams = 3;
1174 struct CodecSettings {
1175 uint32_t ssrc;
1176 int width;
1177 int height;
1178 } codec_settings[kNumStreams];
1179
1180 MultiStreamTest() {
1181 // TODO(sprang): Cleanup when msvc supports explicit initializers for array.
1182 codec_settings[0] = {1, 640, 480};
1183 codec_settings[1] = {2, 320, 240};
1184 codec_settings[2] = {3, 240, 160};
1185 }
1186
1187 virtual ~MultiStreamTest() {}
1188
1189 void RunTest() {
solenberg4fbae2b2015-08-28 04:07:10 -07001190 rtc::scoped_ptr<Call> sender_call(Call::Create(Call::Config()));
1191 rtc::scoped_ptr<Call> receiver_call(Call::Create(Call::Config()));
stefanf116bd02015-10-27 08:29:42 -07001192 rtc::scoped_ptr<test::DirectTransport> sender_transport(
1193 CreateSendTransport(sender_call.get()));
1194 rtc::scoped_ptr<test::DirectTransport> receiver_transport(
1195 CreateReceiveTransport(receiver_call.get()));
sprang867fb522015-08-03 04:38:41 -07001196 sender_transport->SetReceiver(receiver_call->Receiver());
1197 receiver_transport->SetReceiver(sender_call->Receiver());
1198
1199 rtc::scoped_ptr<VideoEncoder> encoders[kNumStreams];
1200 for (size_t i = 0; i < kNumStreams; ++i)
1201 encoders[i].reset(VideoEncoder::Create(VideoEncoder::kVp8));
1202
1203 VideoSendStream* send_streams[kNumStreams];
1204 VideoReceiveStream* receive_streams[kNumStreams];
1205
1206 test::FrameGeneratorCapturer* frame_generators[kNumStreams];
1207 ScopedVector<VideoDecoder> allocated_decoders;
1208 for (size_t i = 0; i < kNumStreams; ++i) {
1209 uint32_t ssrc = codec_settings[i].ssrc;
1210 int width = codec_settings[i].width;
1211 int height = codec_settings[i].height;
1212
solenberg4fbae2b2015-08-28 04:07:10 -07001213 VideoSendStream::Config send_config(sender_transport.get());
sprang867fb522015-08-03 04:38:41 -07001214 send_config.rtp.ssrcs.push_back(ssrc);
1215 send_config.encoder_settings.encoder = encoders[i].get();
1216 send_config.encoder_settings.payload_name = "VP8";
1217 send_config.encoder_settings.payload_type = 124;
1218 VideoEncoderConfig encoder_config;
1219 encoder_config.streams = test::CreateVideoStreams(1);
1220 VideoStream* stream = &encoder_config.streams[0];
1221 stream->width = width;
1222 stream->height = height;
1223 stream->max_framerate = 5;
1224 stream->min_bitrate_bps = stream->target_bitrate_bps =
1225 stream->max_bitrate_bps = 100000;
1226
1227 UpdateSendConfig(i, &send_config, &encoder_config, &frame_generators[i]);
1228
1229 send_streams[i] =
1230 sender_call->CreateVideoSendStream(send_config, encoder_config);
1231 send_streams[i]->Start();
1232
solenberg4fbae2b2015-08-28 04:07:10 -07001233 VideoReceiveStream::Config receive_config(receiver_transport.get());
sprang867fb522015-08-03 04:38:41 -07001234 receive_config.rtp.remote_ssrc = ssrc;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001235 receive_config.rtp.local_ssrc = test::CallTest::kReceiverLocalVideoSsrc;
sprang867fb522015-08-03 04:38:41 -07001236 VideoReceiveStream::Decoder decoder =
1237 test::CreateMatchingDecoder(send_config.encoder_settings);
1238 allocated_decoders.push_back(decoder.decoder);
1239 receive_config.decoders.push_back(decoder);
1240
1241 UpdateReceiveConfig(i, &receive_config);
1242
1243 receive_streams[i] =
1244 receiver_call->CreateVideoReceiveStream(receive_config);
1245 receive_streams[i]->Start();
1246
1247 frame_generators[i] = test::FrameGeneratorCapturer::Create(
1248 send_streams[i]->Input(), width, height, 30,
1249 Clock::GetRealTimeClock());
1250 frame_generators[i]->Start();
1251 }
1252
1253 Wait();
1254
1255 for (size_t i = 0; i < kNumStreams; ++i) {
1256 frame_generators[i]->Stop();
1257 sender_call->DestroyVideoSendStream(send_streams[i]);
1258 receiver_call->DestroyVideoReceiveStream(receive_streams[i]);
1259 delete frame_generators[i];
1260 }
1261
1262 sender_transport->StopSending();
1263 receiver_transport->StopSending();
1264 }
1265
1266 protected:
1267 virtual void Wait() = 0;
1268 // Note: frame_generator is a point-to-pointer, since the actual instance
1269 // hasn't been created at the time of this call. Only when packets/frames
1270 // start flowing should this be dereferenced.
1271 virtual void UpdateSendConfig(
1272 size_t stream_index,
1273 VideoSendStream::Config* send_config,
1274 VideoEncoderConfig* encoder_config,
1275 test::FrameGeneratorCapturer** frame_generator) {}
1276 virtual void UpdateReceiveConfig(size_t stream_index,
1277 VideoReceiveStream::Config* receive_config) {
1278 }
stefanf116bd02015-10-27 08:29:42 -07001279 virtual test::DirectTransport* CreateSendTransport(Call* sender_call) {
1280 return new test::DirectTransport(sender_call);
sprang867fb522015-08-03 04:38:41 -07001281 }
stefanf116bd02015-10-27 08:29:42 -07001282 virtual test::DirectTransport* CreateReceiveTransport(Call* receiver_call) {
1283 return new test::DirectTransport(receiver_call);
sprang867fb522015-08-03 04:38:41 -07001284 }
1285};
1286
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001287// Each renderer verifies that it receives the expected resolution, and as soon
1288// as every renderer has received a frame, the test finishes.
andresp@webrtc.org02686112014-09-19 08:24:19 +00001289TEST_F(EndToEndTest, SendsAndReceivesMultipleStreams) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001290 class VideoOutputObserver : public VideoRenderer {
1291 public:
sprang867fb522015-08-03 04:38:41 -07001292 VideoOutputObserver(const MultiStreamTest::CodecSettings& settings,
1293 uint32_t ssrc,
1294 test::FrameGeneratorCapturer** frame_generator)
1295 : settings_(settings),
1296 ssrc_(ssrc),
1297 frame_generator_(frame_generator),
Peter Boström5811a392015-12-10 13:02:50 +01001298 done_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001299
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001300 void RenderFrame(const VideoFrame& video_frame,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001301 int time_to_render_ms) override {
sprang867fb522015-08-03 04:38:41 -07001302 EXPECT_EQ(settings_.width, video_frame.width());
1303 EXPECT_EQ(settings_.height, video_frame.height());
1304 (*frame_generator_)->Stop();
Peter Boström5811a392015-12-10 13:02:50 +01001305 done_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001306 }
1307
sprang867fb522015-08-03 04:38:41 -07001308 uint32_t Ssrc() { return ssrc_; }
1309
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001310 bool IsTextureSupported() const override { return false; }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00001311
Peter Boström5811a392015-12-10 13:02:50 +01001312 bool Wait() { return done_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001313
1314 private:
sprang867fb522015-08-03 04:38:41 -07001315 const MultiStreamTest::CodecSettings& settings_;
1316 const uint32_t ssrc_;
1317 test::FrameGeneratorCapturer** const frame_generator_;
Peter Boström5811a392015-12-10 13:02:50 +01001318 rtc::Event done_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001319 };
1320
sprang867fb522015-08-03 04:38:41 -07001321 class Tester : public MultiStreamTest {
1322 public:
1323 Tester() {}
1324 virtual ~Tester() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001325
sprang867fb522015-08-03 04:38:41 -07001326 protected:
1327 void Wait() override {
1328 for (const auto& observer : observers_) {
Peter Boström5811a392015-12-10 13:02:50 +01001329 EXPECT_TRUE(observer->Wait()) << "Time out waiting for from on ssrc "
1330 << observer->Ssrc();
sprang867fb522015-08-03 04:38:41 -07001331 }
1332 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001333
sprang867fb522015-08-03 04:38:41 -07001334 void UpdateSendConfig(
1335 size_t stream_index,
1336 VideoSendStream::Config* send_config,
1337 VideoEncoderConfig* encoder_config,
1338 test::FrameGeneratorCapturer** frame_generator) override {
1339 observers_[stream_index].reset(new VideoOutputObserver(
1340 codec_settings[stream_index], send_config->rtp.ssrcs.front(),
1341 frame_generator));
1342 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001343
sprang867fb522015-08-03 04:38:41 -07001344 void UpdateReceiveConfig(
1345 size_t stream_index,
1346 VideoReceiveStream::Config* receive_config) override {
1347 receive_config->renderer = observers_[stream_index].get();
1348 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001349
sprang867fb522015-08-03 04:38:41 -07001350 private:
1351 rtc::scoped_ptr<VideoOutputObserver> observers_[kNumStreams];
1352 } tester;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001353
sprang867fb522015-08-03 04:38:41 -07001354 tester.RunTest();
1355}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001356
sprang867fb522015-08-03 04:38:41 -07001357TEST_F(EndToEndTest, AssignsTransportSequenceNumbers) {
sprang867fb522015-08-03 04:38:41 -07001358 static const int kExtensionId = 5;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001359
sprang867fb522015-08-03 04:38:41 -07001360 class RtpExtensionHeaderObserver : public test::DirectTransport {
1361 public:
stefanf116bd02015-10-27 08:29:42 -07001362 RtpExtensionHeaderObserver(Call* sender_call,
1363 const uint32_t& first_media_ssrc,
sprang861c55e2015-10-16 10:01:21 -07001364 const std::map<uint32_t, uint32_t>& ssrc_map)
stefanf116bd02015-10-27 08:29:42 -07001365 : DirectTransport(sender_call),
Peter Boström5811a392015-12-10 13:02:50 +01001366 done_(false, false),
sprang867fb522015-08-03 04:38:41 -07001367 parser_(RtpHeaderParser::Create()),
sprang861c55e2015-10-16 10:01:21 -07001368 first_media_ssrc_(first_media_ssrc),
1369 rtx_to_media_ssrcs_(ssrc_map),
sprang867fb522015-08-03 04:38:41 -07001370 padding_observed_(false),
sprang861c55e2015-10-16 10:01:21 -07001371 rtx_padding_observed_(false),
1372 retransmit_observed_(false),
1373 started_(false) {
sprang867fb522015-08-03 04:38:41 -07001374 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
1375 kExtensionId);
1376 }
1377 virtual ~RtpExtensionHeaderObserver() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001378
stefan1d8a5062015-10-02 03:39:33 -07001379 bool SendRtp(const uint8_t* data,
1380 size_t length,
1381 const PacketOptions& options) override {
sprang861c55e2015-10-16 10:01:21 -07001382 {
1383 rtc::CritScope cs(&lock_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001384
Erik Språng8d629712015-08-04 16:24:03 +02001385 if (IsDone())
sprang861c55e2015-10-16 10:01:21 -07001386 return false;
1387
1388 if (started_) {
1389 RTPHeader header;
1390 EXPECT_TRUE(parser_->Parse(data, length, &header));
1391 bool drop_packet = false;
1392
1393 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
1394 EXPECT_EQ(options.packet_id,
1395 header.extension.transportSequenceNumber);
1396 if (!streams_observed_.empty()) {
1397 // Unwrap packet id and verify uniqueness.
1398 int64_t packet_id = unwrapper_.Unwrap(options.packet_id);
1399 EXPECT_TRUE(received_packed_ids_.insert(packet_id).second);
1400 }
1401
1402 // Drop (up to) every 17th packet, so we get retransmits.
1403 // Only drop media, and not on the first stream (otherwise it will be
1404 // hard to distinguish from padding, which is always sent on the first
1405 // stream).
1406 if (header.payloadType != kSendRtxPayloadType &&
1407 header.ssrc != first_media_ssrc_ &&
1408 header.extension.transportSequenceNumber % 17 == 0) {
1409 dropped_seq_[header.ssrc].insert(header.sequenceNumber);
1410 drop_packet = true;
1411 }
1412
1413 size_t payload_length =
1414 length - (header.headerLength + header.paddingLength);
1415 if (payload_length == 0) {
1416 padding_observed_ = true;
1417 } else if (header.payloadType == kSendRtxPayloadType) {
1418 uint16_t original_sequence_number =
1419 ByteReader<uint16_t>::ReadBigEndian(&data[header.headerLength]);
1420 uint32_t original_ssrc =
1421 rtx_to_media_ssrcs_.find(header.ssrc)->second;
1422 std::set<uint16_t>* seq_no_map = &dropped_seq_[original_ssrc];
1423 auto it = seq_no_map->find(original_sequence_number);
1424 if (it != seq_no_map->end()) {
1425 retransmit_observed_ = true;
1426 seq_no_map->erase(it);
1427 } else {
1428 rtx_padding_observed_ = true;
1429 }
1430 } else {
1431 streams_observed_.insert(header.ssrc);
1432 }
1433
1434 if (IsDone())
Peter Boström5811a392015-12-10 13:02:50 +01001435 done_.Set();
sprang861c55e2015-10-16 10:01:21 -07001436
1437 if (drop_packet)
1438 return true;
1439 }
sprang867fb522015-08-03 04:38:41 -07001440 }
sprang861c55e2015-10-16 10:01:21 -07001441
stefan1d8a5062015-10-02 03:39:33 -07001442 return test::DirectTransport::SendRtp(data, length, options);
sprang867fb522015-08-03 04:38:41 -07001443 }
1444
Erik Språng8d629712015-08-04 16:24:03 +02001445 bool IsDone() {
sprang861c55e2015-10-16 10:01:21 -07001446 bool observed_types_ok =
1447 streams_observed_.size() == MultiStreamTest::kNumStreams &&
1448 padding_observed_ && retransmit_observed_ && rtx_padding_observed_;
1449 if (!observed_types_ok)
1450 return false;
1451 // We should not have any gaps in the sequence number range.
1452 size_t seqno_range =
1453 *received_packed_ids_.rbegin() - *received_packed_ids_.begin() + 1;
1454 return seqno_range == received_packed_ids_.size();
Erik Språng8d629712015-08-04 16:24:03 +02001455 }
1456
Peter Boström5811a392015-12-10 13:02:50 +01001457 bool Wait() {
sprang861c55e2015-10-16 10:01:21 -07001458 {
1459 // Can't be sure until this point that rtx_to_media_ssrcs_ etc have
1460 // been initialized and are OK to read.
1461 rtc::CritScope cs(&lock_);
1462 started_ = true;
1463 }
Peter Boström5811a392015-12-10 13:02:50 +01001464 return done_.Wait(kDefaultTimeoutMs);
sprang861c55e2015-10-16 10:01:21 -07001465 }
sprang867fb522015-08-03 04:38:41 -07001466
sprang861c55e2015-10-16 10:01:21 -07001467 rtc::CriticalSection lock_;
Peter Boström5811a392015-12-10 13:02:50 +01001468 rtc::Event done_;
sprang867fb522015-08-03 04:38:41 -07001469 rtc::scoped_ptr<RtpHeaderParser> parser_;
sprang861c55e2015-10-16 10:01:21 -07001470 SequenceNumberUnwrapper unwrapper_;
1471 std::set<int64_t> received_packed_ids_;
sprang867fb522015-08-03 04:38:41 -07001472 std::set<uint32_t> streams_observed_;
sprang861c55e2015-10-16 10:01:21 -07001473 std::map<uint32_t, std::set<uint16_t>> dropped_seq_;
1474 const uint32_t& first_media_ssrc_;
1475 const std::map<uint32_t, uint32_t>& rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001476 bool padding_observed_;
1477 bool rtx_padding_observed_;
sprang861c55e2015-10-16 10:01:21 -07001478 bool retransmit_observed_;
1479 bool started_;
sprang867fb522015-08-03 04:38:41 -07001480 };
1481
1482 class TransportSequenceNumberTester : public MultiStreamTest {
1483 public:
sprang861c55e2015-10-16 10:01:21 -07001484 TransportSequenceNumberTester()
1485 : first_media_ssrc_(0), observer_(nullptr) {}
sprang867fb522015-08-03 04:38:41 -07001486 virtual ~TransportSequenceNumberTester() {}
1487
1488 protected:
1489 void Wait() override {
henrikg91d6ede2015-09-17 00:24:34 -07001490 RTC_DCHECK(observer_ != nullptr);
Peter Boström5811a392015-12-10 13:02:50 +01001491 EXPECT_TRUE(observer_->Wait());
sprang867fb522015-08-03 04:38:41 -07001492 }
1493
1494 void UpdateSendConfig(
1495 size_t stream_index,
1496 VideoSendStream::Config* send_config,
1497 VideoEncoderConfig* encoder_config,
1498 test::FrameGeneratorCapturer** frame_generator) override {
1499 send_config->rtp.extensions.clear();
1500 send_config->rtp.extensions.push_back(
1501 RtpExtension(RtpExtension::kTransportSequenceNumber, kExtensionId));
1502
1503 // Force some padding to be sent.
1504 const int kPaddingBitrateBps = 50000;
1505 int total_target_bitrate = 0;
1506 for (const VideoStream& stream : encoder_config->streams)
1507 total_target_bitrate += stream.target_bitrate_bps;
1508 encoder_config->min_transmit_bitrate_bps =
1509 total_target_bitrate + kPaddingBitrateBps;
1510
1511 // Configure RTX for redundant payload padding.
1512 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang861c55e2015-10-16 10:01:21 -07001513 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[stream_index]);
sprang867fb522015-08-03 04:38:41 -07001514 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
sprang861c55e2015-10-16 10:01:21 -07001515 rtx_to_media_ssrcs_[kSendRtxSsrcs[stream_index]] =
1516 send_config->rtp.ssrcs[0];
1517
1518 if (stream_index == 0)
1519 first_media_ssrc_ = send_config->rtp.ssrcs[0];
sprang867fb522015-08-03 04:38:41 -07001520 }
1521
1522 void UpdateReceiveConfig(
1523 size_t stream_index,
1524 VideoReceiveStream::Config* receive_config) override {
sprang861c55e2015-10-16 10:01:21 -07001525 receive_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang867fb522015-08-03 04:38:41 -07001526 receive_config->rtp.extensions.clear();
1527 receive_config->rtp.extensions.push_back(
1528 RtpExtension(RtpExtension::kTransportSequenceNumber, kExtensionId));
1529 }
1530
stefanf116bd02015-10-27 08:29:42 -07001531 test::DirectTransport* CreateSendTransport(Call* sender_call) override {
1532 observer_ = new RtpExtensionHeaderObserver(sender_call, first_media_ssrc_,
sprang861c55e2015-10-16 10:01:21 -07001533 rtx_to_media_ssrcs_);
sprang867fb522015-08-03 04:38:41 -07001534 return observer_;
1535 }
1536
1537 private:
sprang861c55e2015-10-16 10:01:21 -07001538 uint32_t first_media_ssrc_;
1539 std::map<uint32_t, uint32_t> rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001540 RtpExtensionHeaderObserver* observer_;
1541 } tester;
1542
1543 tester.RunTest();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001544}
1545
Stefan Holmer04cb7632016-01-14 20:34:30 +01001546class TransportFeedbackTester : public test::EndToEndTest {
1547 public:
1548 explicit TransportFeedbackTester(bool feedback_enabled,
1549 size_t num_video_streams,
1550 size_t num_audio_streams)
1551 : EndToEndTest(::webrtc::EndToEndTest::kDefaultTimeoutMs),
1552 feedback_enabled_(feedback_enabled),
1553 num_video_streams_(num_video_streams),
1554 num_audio_streams_(num_audio_streams) {
1555 // Only one stream of each supported for now.
1556 EXPECT_LE(num_video_streams, 1u);
1557 EXPECT_LE(num_audio_streams, 1u);
1558 }
1559
1560 protected:
1561 Action OnSendRtcp(const uint8_t* data, size_t length) override {
1562 EXPECT_FALSE(HasTransportFeedback(data, length));
1563 return SEND_PACKET;
1564 }
1565
1566 Action OnReceiveRtcp(const uint8_t* data, size_t length) override {
1567 if (HasTransportFeedback(data, length))
1568 observation_complete_.Set();
1569 return SEND_PACKET;
1570 }
1571
1572 bool HasTransportFeedback(const uint8_t* data, size_t length) const {
1573 RTCPUtility::RTCPParserV2 parser(data, length, true);
1574 EXPECT_TRUE(parser.IsValid());
1575
1576 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
1577 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
1578 if (packet_type == RTCPUtility::RTCPPacketTypes::kTransportFeedback)
1579 return true;
1580 packet_type = parser.Iterate();
1581 }
1582
1583 return false;
1584 }
1585
1586 void PerformTest() override {
1587 const int64_t kDisabledFeedbackTimeoutMs = 5000;
1588 EXPECT_EQ(feedback_enabled_,
1589 observation_complete_.Wait(feedback_enabled_
1590 ? test::CallTest::kDefaultTimeoutMs
1591 : kDisabledFeedbackTimeoutMs));
1592 }
1593
1594 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
1595 receiver_call_ = receiver_call;
1596 }
1597
1598 size_t GetNumVideoStreams() const override { return num_video_streams_; }
1599 size_t GetNumAudioStreams() const override { return num_audio_streams_; }
1600
1601 void ModifyVideoConfigs(
1602 VideoSendStream::Config* send_config,
1603 std::vector<VideoReceiveStream::Config>* receive_configs,
1604 VideoEncoderConfig* encoder_config) override {
1605 send_config->rtp.extensions.clear();
1606 send_config->rtp.extensions.push_back(
1607 RtpExtension(RtpExtension::kTransportSequenceNumber, kExtensionId));
1608 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1609 (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
1610 }
1611
1612 void ModifyAudioConfigs(
1613 AudioSendStream::Config* send_config,
1614 std::vector<AudioReceiveStream::Config>* receive_configs) override {
1615 send_config->rtp.extensions.clear();
1616 send_config->rtp.extensions.push_back(
1617 RtpExtension(RtpExtension::kTransportSequenceNumber, kExtensionId));
1618 (*receive_configs)[0].rtp.extensions.clear();
1619 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1620 (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
1621 (*receive_configs)[0].combined_audio_video_bwe = true;
1622 }
1623
1624 private:
Erik Språng6b8d3552015-09-24 15:06:57 +02001625 static const int kExtensionId = 5;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001626 const bool feedback_enabled_;
1627 const size_t num_video_streams_;
1628 const size_t num_audio_streams_;
1629 Call* receiver_call_;
1630};
Erik Språng6b8d3552015-09-24 15:06:57 +02001631
Stefan Holmer04cb7632016-01-14 20:34:30 +01001632TEST_F(EndToEndTest, VideoReceivesTransportFeedback) {
1633 TransportFeedbackTester test(true, 1, 0);
1634 RunBaseTest(&test);
Erik Språng6b8d3552015-09-24 15:06:57 +02001635}
stefan43edf0f2015-11-20 18:05:48 -08001636
Stefan Holmer04cb7632016-01-14 20:34:30 +01001637TEST_F(EndToEndTest, VideoTransportFeedbackNotConfigured) {
1638 TransportFeedbackTester test(false, 1, 0);
1639 RunBaseTest(&test);
stefan43edf0f2015-11-20 18:05:48 -08001640}
1641
Stefan Holmer04cb7632016-01-14 20:34:30 +01001642TEST_F(EndToEndTest, AudioReceivesTransportFeedback) {
1643 TransportFeedbackTester test(true, 0, 1);
1644 RunBaseTest(&test);
1645}
1646
1647TEST_F(EndToEndTest, AudioTransportFeedbackNotConfigured) {
1648 TransportFeedbackTester test(false, 0, 1);
1649 RunBaseTest(&test);
1650}
1651
1652TEST_F(EndToEndTest, AudioVideoReceivesTransportFeedback) {
1653 TransportFeedbackTester test(true, 1, 1);
1654 RunBaseTest(&test);
stefan43edf0f2015-11-20 18:05:48 -08001655}
1656
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001657TEST_F(EndToEndTest, ObserversEncodedFrames) {
1658 class EncodedFrameTestObserver : public EncodedFrameObserver {
1659 public:
1660 EncodedFrameTestObserver()
Peter Boström5811a392015-12-10 13:02:50 +01001661 : length_(0), frame_type_(kEmptyFrame), called_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001662 virtual ~EncodedFrameTestObserver() {}
1663
1664 virtual void EncodedFrameCallback(const EncodedFrame& encoded_frame) {
1665 frame_type_ = encoded_frame.frame_type_;
1666 length_ = encoded_frame.length_;
1667 buffer_.reset(new uint8_t[length_]);
1668 memcpy(buffer_.get(), encoded_frame.data_, length_);
Peter Boström5811a392015-12-10 13:02:50 +01001669 called_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001670 }
1671
Peter Boström5811a392015-12-10 13:02:50 +01001672 bool Wait() { return called_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001673
1674 void ExpectEqualFrames(const EncodedFrameTestObserver& observer) {
1675 ASSERT_EQ(length_, observer.length_)
1676 << "Observed frames are of different lengths.";
1677 EXPECT_EQ(frame_type_, observer.frame_type_)
1678 << "Observed frames have different frame types.";
1679 EXPECT_EQ(0, memcmp(buffer_.get(), observer.buffer_.get(), length_))
1680 << "Observed encoded frames have different content.";
1681 }
1682
1683 private:
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00001684 rtc::scoped_ptr<uint8_t[]> buffer_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001685 size_t length_;
1686 FrameType frame_type_;
Peter Boström5811a392015-12-10 13:02:50 +01001687 rtc::Event called_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001688 };
1689
1690 EncodedFrameTestObserver post_encode_observer;
1691 EncodedFrameTestObserver pre_decode_observer;
1692
solenberg4fbae2b2015-08-28 04:07:10 -07001693 CreateCalls(Call::Config(), Call::Config());
1694
stefanf116bd02015-10-27 08:29:42 -07001695 test::DirectTransport sender_transport(sender_call_.get());
1696 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001697 sender_transport.SetReceiver(receiver_call_->Receiver());
1698 receiver_transport.SetReceiver(sender_call_->Receiver());
1699
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001700 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07001701 CreateMatchingReceiveConfigs(&receiver_transport);
stefanff483612015-12-21 03:14:00 -08001702 video_send_config_.post_encode_callback = &post_encode_observer;
1703 video_receive_configs_[0].pre_decode_callback = &pre_decode_observer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001704
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001705 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001706 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001707
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00001708 rtc::scoped_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +00001709 test::FrameGenerator::CreateChromaGenerator(
stefanff483612015-12-21 03:14:00 -08001710 video_encoder_config_.streams[0].width,
1711 video_encoder_config_.streams[0].height));
1712 video_send_stream_->Input()->IncomingCapturedFrame(
1713 *frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001714
Peter Boström5811a392015-12-10 13:02:50 +01001715 EXPECT_TRUE(post_encode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001716 << "Timed out while waiting for send-side encoded-frame callback.";
1717
Peter Boström5811a392015-12-10 13:02:50 +01001718 EXPECT_TRUE(pre_decode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001719 << "Timed out while waiting for pre-decode encoded-frame callback.";
1720
1721 post_encode_observer.ExpectEqualFrames(pre_decode_observer);
1722
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001723 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001724
1725 sender_transport.StopSending();
1726 receiver_transport.StopSending();
1727
1728 DestroyStreams();
1729}
1730
1731TEST_F(EndToEndTest, ReceiveStreamSendsRemb) {
1732 class RembObserver : public test::EndToEndTest {
1733 public:
1734 RembObserver() : EndToEndTest(kDefaultTimeoutMs) {}
1735
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001736 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001737 RTCPUtility::RTCPParserV2 parser(packet, length, true);
1738 EXPECT_TRUE(parser.IsValid());
1739
1740 bool received_psfb = false;
1741 bool received_remb = false;
1742 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02001743 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
1744 if (packet_type == RTCPUtility::RTCPPacketTypes::kPsfbRemb) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001745 const RTCPUtility::RTCPPacket& packet = parser.Packet();
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001746 EXPECT_EQ(packet.PSFBAPP.SenderSSRC, kReceiverLocalVideoSsrc);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001747 received_psfb = true;
Erik Språng242e22b2015-05-11 10:17:43 +02001748 } else if (packet_type == RTCPUtility::RTCPPacketTypes::kPsfbRembItem) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001749 const RTCPUtility::RTCPPacket& packet = parser.Packet();
1750 EXPECT_GT(packet.REMBItem.BitRate, 0u);
1751 EXPECT_EQ(packet.REMBItem.NumberOfSSRCs, 1u);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001752 EXPECT_EQ(packet.REMBItem.SSRCs[0], kVideoSendSsrcs[0]);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001753 received_remb = true;
1754 }
1755 packet_type = parser.Iterate();
1756 }
1757 if (received_psfb && received_remb)
Peter Boström5811a392015-12-10 13:02:50 +01001758 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001759 return SEND_PACKET;
1760 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001761 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001762 EXPECT_TRUE(Wait()) << "Timed out while waiting for a "
1763 "receiver RTCP REMB packet to be "
1764 "sent.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001765 }
1766 } test;
1767
stefane74eef12016-01-08 06:47:13 -08001768 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001769}
1770
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001771TEST_F(EndToEndTest, VerifyBandwidthStats) {
stefanf116bd02015-10-27 08:29:42 -07001772 class RtcpObserver : public test::EndToEndTest {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001773 public:
1774 RtcpObserver()
1775 : EndToEndTest(kDefaultTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00001776 sender_call_(nullptr),
1777 receiver_call_(nullptr),
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001778 has_seen_pacer_delay_(false) {}
1779
stefanf116bd02015-10-27 08:29:42 -07001780 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001781 Call::Stats sender_stats = sender_call_->GetStats();
1782 Call::Stats receiver_stats = receiver_call_->GetStats();
1783 if (!has_seen_pacer_delay_)
1784 has_seen_pacer_delay_ = sender_stats.pacer_delay_ms > 0;
1785 if (sender_stats.send_bandwidth_bps > 0 &&
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00001786 receiver_stats.recv_bandwidth_bps > 0 && has_seen_pacer_delay_) {
Peter Boström5811a392015-12-10 13:02:50 +01001787 observation_complete_.Set();
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00001788 }
stefanf116bd02015-10-27 08:29:42 -07001789 return SEND_PACKET;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001790 }
1791
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001792 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001793 sender_call_ = sender_call;
1794 receiver_call_ = receiver_call;
1795 }
1796
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001797 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001798 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
1799 "non-zero bandwidth stats.";
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001800 }
1801
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001802 private:
1803 Call* sender_call_;
1804 Call* receiver_call_;
1805 bool has_seen_pacer_delay_;
1806 } test;
1807
stefane74eef12016-01-08 06:47:13 -08001808 RunBaseTest(&test);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001809}
1810
stefan32f81542016-01-20 07:13:58 -08001811
1812// Verifies that it's possible to limit the send BWE by sending a REMB.
1813// This is verified by allowing the send BWE to ramp-up to >1000 kbps,
1814// then have the test generate a REMB of 500 kbps and verify that the send BWE
1815// is reduced to exactly 500 kbps. Then a REMB of 1000 kbps is generated and the
1816// test verifies that the send BWE ramps back up to exactly 1000 kbps.
1817TEST_F(EndToEndTest, RembWithSendSideBwe) {
1818 class BweObserver : public test::EndToEndTest {
1819 public:
1820 BweObserver()
1821 : EndToEndTest(kDefaultTimeoutMs),
1822 sender_call_(nullptr),
1823 clock_(Clock::GetRealTimeClock()),
1824 sender_ssrc_(0),
1825 remb_bitrate_bps_(1000000),
1826 receive_transport_(nullptr),
1827 event_(false, false),
1828 poller_thread_(&BitrateStatsPollingThread,
1829 this,
1830 "BitrateStatsPollingThread"),
1831 state_(kWaitForFirstRampUp) {}
1832
1833 ~BweObserver() {}
1834
1835 test::PacketTransport* CreateReceiveTransport() {
1836 receive_transport_ = new test::PacketTransport(
1837 nullptr, this, test::PacketTransport::kReceiver,
1838 FakeNetworkPipe::Config());
1839 return receive_transport_;
1840 }
1841
1842 Call::Config GetSenderCallConfig() override {
1843 Call::Config config;
1844 // Set a high start bitrate to reduce the test completion time.
1845 config.bitrate_config.start_bitrate_bps = remb_bitrate_bps_;
1846 return config;
1847 }
1848
1849 void ModifyVideoConfigs(
1850 VideoSendStream::Config* send_config,
1851 std::vector<VideoReceiveStream::Config>* receive_configs,
1852 VideoEncoderConfig* encoder_config) override {
1853 ASSERT_EQ(1u, send_config->rtp.ssrcs.size());
1854 send_config->rtp.extensions.clear();
1855 send_config->rtp.extensions.push_back(
1856 RtpExtension(RtpExtension::kTransportSequenceNumber,
1857 test::kTransportSequenceNumberExtensionId));
1858 sender_ssrc_ = send_config->rtp.ssrcs[0];
1859
1860 encoder_config->streams[0].max_bitrate_bps =
1861 encoder_config->streams[0].target_bitrate_bps = 2000000;
1862
1863 ASSERT_EQ(1u, receive_configs->size());
1864 (*receive_configs)[0].rtp.remb = false;
1865 (*receive_configs)[0].rtp.transport_cc = true;
1866 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1867 RtpRtcp::Configuration config;
1868 config.receiver_only = true;
1869 config.clock = clock_;
1870 config.outgoing_transport = receive_transport_;
1871 rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(config));
1872 rtp_rtcp_->SetRemoteSSRC((*receive_configs)[0].rtp.remote_ssrc);
1873 rtp_rtcp_->SetSSRC((*receive_configs)[0].rtp.local_ssrc);
1874 rtp_rtcp_->SetREMBStatus(true);
1875 rtp_rtcp_->SetSendingStatus(true);
1876 rtp_rtcp_->SetRTCPStatus(RtcpMode::kReducedSize);
1877 }
1878
1879 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
1880 sender_call_ = sender_call;
1881 }
1882
1883 static bool BitrateStatsPollingThread(void* obj) {
1884 return static_cast<BweObserver*>(obj)->PollStats();
1885 }
1886
1887 bool PollStats() {
1888 if (sender_call_) {
1889 Call::Stats stats = sender_call_->GetStats();
1890 switch (state_) {
1891 case kWaitForFirstRampUp:
1892 if (stats.send_bandwidth_bps >= remb_bitrate_bps_) {
1893 state_ = kWaitForRemb;
1894 remb_bitrate_bps_ /= 2;
1895 rtp_rtcp_->SetREMBData(
1896 remb_bitrate_bps_,
1897 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
1898 rtp_rtcp_->SendRTCP(kRtcpRr);
1899 }
1900 break;
1901
1902 case kWaitForRemb:
1903 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
1904 state_ = kWaitForSecondRampUp;
1905 remb_bitrate_bps_ *= 2;
1906 rtp_rtcp_->SetREMBData(
1907 remb_bitrate_bps_,
1908 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
1909 rtp_rtcp_->SendRTCP(kRtcpRr);
1910 }
1911 break;
1912
1913 case kWaitForSecondRampUp:
1914 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
1915 observation_complete_.Set();
1916 }
1917 break;
1918 }
1919 }
1920
1921 return !event_.Wait(1000);
1922 }
1923
1924 void PerformTest() override {
1925 poller_thread_.Start();
1926 EXPECT_TRUE(Wait())
1927 << "Timed out while waiting for bitrate to change according to REMB.";
1928 poller_thread_.Stop();
1929 }
1930
1931 private:
1932 enum TestState { kWaitForFirstRampUp, kWaitForRemb, kWaitForSecondRampUp };
1933
1934 Call* sender_call_;
1935 Clock* const clock_;
1936 uint32_t sender_ssrc_;
1937 int remb_bitrate_bps_;
1938 rtc::scoped_ptr<RtpRtcp> rtp_rtcp_;
1939 test::PacketTransport* receive_transport_;
1940 rtc::Event event_;
1941 rtc::PlatformThread poller_thread_;
1942 TestState state_;
1943 } test;
1944
1945 RunBaseTest(&test);
1946}
1947
Åsa Persson352b2d72015-04-15 18:00:40 +02001948TEST_F(EndToEndTest, VerifyNackStats) {
1949 static const int kPacketNumberToDrop = 200;
1950 class NackObserver : public test::EndToEndTest {
1951 public:
1952 NackObserver()
1953 : EndToEndTest(kLongTimeoutMs),
1954 sent_rtp_packets_(0),
1955 dropped_rtp_packet_(0),
1956 dropped_rtp_packet_requested_(false),
1957 send_stream_(nullptr),
1958 start_runtime_ms_(-1) {}
1959
1960 private:
1961 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08001962 rtc::CritScope lock(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02001963 if (++sent_rtp_packets_ == kPacketNumberToDrop) {
1964 rtc::scoped_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
1965 RTPHeader header;
1966 EXPECT_TRUE(parser->Parse(packet, length, &header));
1967 dropped_rtp_packet_ = header.sequenceNumber;
1968 return DROP_PACKET;
1969 }
1970 VerifyStats();
1971 return SEND_PACKET;
1972 }
1973
1974 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08001975 rtc::CritScope lock(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02001976 test::RtcpPacketParser rtcp_parser;
1977 rtcp_parser.Parse(packet, length);
1978 std::vector<uint16_t> nacks = rtcp_parser.nack_item()->last_nack_list();
1979 if (!nacks.empty() && std::find(
1980 nacks.begin(), nacks.end(), dropped_rtp_packet_) != nacks.end()) {
1981 dropped_rtp_packet_requested_ = true;
1982 }
1983 return SEND_PACKET;
1984 }
1985
stefan608213e2015-11-01 14:56:10 -08001986 void VerifyStats() EXCLUSIVE_LOCKS_REQUIRED(&crit_) {
Åsa Persson352b2d72015-04-15 18:00:40 +02001987 if (!dropped_rtp_packet_requested_)
1988 return;
1989 int send_stream_nack_packets = 0;
1990 int receive_stream_nack_packets = 0;
1991 VideoSendStream::Stats stats = send_stream_->GetStats();
1992 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
1993 stats.substreams.begin(); it != stats.substreams.end(); ++it) {
1994 const VideoSendStream::StreamStats& stream_stats = it->second;
1995 send_stream_nack_packets +=
1996 stream_stats.rtcp_packet_type_counts.nack_packets;
1997 }
1998 for (size_t i = 0; i < receive_streams_.size(); ++i) {
1999 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
2000 receive_stream_nack_packets +=
2001 stats.rtcp_packet_type_counts.nack_packets;
2002 }
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002003 if (send_stream_nack_packets >= 1 && receive_stream_nack_packets >= 1) {
Åsa Persson352b2d72015-04-15 18:00:40 +02002004 // NACK packet sent on receive stream and received on sent stream.
2005 if (MinMetricRunTimePassed())
Peter Boström5811a392015-12-10 13:02:50 +01002006 observation_complete_.Set();
Åsa Persson352b2d72015-04-15 18:00:40 +02002007 }
2008 }
2009
2010 bool MinMetricRunTimePassed() {
2011 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
2012 if (start_runtime_ms_ == -1) {
2013 start_runtime_ms_ = now;
2014 return false;
2015 }
2016 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
2017 return elapsed_sec > metrics::kMinRunTimeInSeconds;
2018 }
2019
stefanff483612015-12-21 03:14:00 -08002020 void ModifyVideoConfigs(
2021 VideoSendStream::Config* send_config,
2022 std::vector<VideoReceiveStream::Config>* receive_configs,
2023 VideoEncoderConfig* encoder_config) override {
Åsa Persson352b2d72015-04-15 18:00:40 +02002024 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2025 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2026 }
2027
stefanff483612015-12-21 03:14:00 -08002028 void OnVideoStreamsCreated(
Åsa Persson352b2d72015-04-15 18:00:40 +02002029 VideoSendStream* send_stream,
2030 const std::vector<VideoReceiveStream*>& receive_streams) override {
2031 send_stream_ = send_stream;
2032 receive_streams_ = receive_streams;
2033 }
2034
2035 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002036 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Åsa Persson352b2d72015-04-15 18:00:40 +02002037 }
2038
stefan608213e2015-11-01 14:56:10 -08002039 rtc::CriticalSection crit_;
Åsa Persson352b2d72015-04-15 18:00:40 +02002040 uint64_t sent_rtp_packets_;
stefan608213e2015-11-01 14:56:10 -08002041 uint16_t dropped_rtp_packet_ GUARDED_BY(&crit_);
2042 bool dropped_rtp_packet_requested_ GUARDED_BY(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02002043 std::vector<VideoReceiveStream*> receive_streams_;
2044 VideoSendStream* send_stream_;
2045 int64_t start_runtime_ms_;
2046 } test;
2047
Åsa Persson3c391cb2015-04-27 10:09:49 +02002048 test::ClearHistograms();
stefane74eef12016-01-08 06:47:13 -08002049 RunBaseTest(&test);
Åsa Persson352b2d72015-04-15 18:00:40 +02002050
Åsa Persson3c391cb2015-04-27 10:09:49 +02002051 EXPECT_EQ(1, test::NumHistogramSamples(
Åsa Persson352b2d72015-04-15 18:00:40 +02002052 "WebRTC.Video.UniqueNackRequestsSentInPercent"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002053 EXPECT_EQ(1, test::NumHistogramSamples(
Åsa Persson352b2d72015-04-15 18:00:40 +02002054 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
2055 EXPECT_GT(test::LastHistogramSample(
2056 "WebRTC.Video.NackPacketsSentPerMinute"), 0);
2057 EXPECT_GT(test::LastHistogramSample(
2058 "WebRTC.Video.NackPacketsReceivedPerMinute"), 0);
2059}
2060
sprangb4a1ae52015-12-03 08:10:08 -08002061void EndToEndTest::VerifyHistogramStats(bool use_rtx,
2062 bool use_red,
2063 bool screenshare) {
stefanf116bd02015-10-27 08:29:42 -07002064 class StatsObserver : public test::EndToEndTest {
Åsa Persson3c391cb2015-04-27 10:09:49 +02002065 public:
sprangb4a1ae52015-12-03 08:10:08 -08002066 StatsObserver(bool use_rtx, bool use_red, bool screenshare)
Åsa Persson3c391cb2015-04-27 10:09:49 +02002067 : EndToEndTest(kLongTimeoutMs),
2068 use_rtx_(use_rtx),
2069 use_red_(use_red),
sprangb4a1ae52015-12-03 08:10:08 -08002070 screenshare_(screenshare),
Åsa Persson3c391cb2015-04-27 10:09:49 +02002071 sender_call_(nullptr),
2072 receiver_call_(nullptr),
2073 start_runtime_ms_(-1) {}
2074
2075 private:
2076 Action OnSendRtp(const uint8_t* packet, size_t length) override {
2077 if (MinMetricRunTimePassed())
Peter Boström5811a392015-12-10 13:02:50 +01002078 observation_complete_.Set();
Åsa Persson3c391cb2015-04-27 10:09:49 +02002079
Åsa Persson3c391cb2015-04-27 10:09:49 +02002080 // GetStats calls GetSendChannelRtcpStatistics
2081 // (via VideoSendStream::GetRtt) which updates ReportBlockStats used by
2082 // WebRTC.Video.SentPacketsLostInPercent.
2083 // TODO(asapersson): Remove dependency on calling GetStats.
2084 sender_call_->GetStats();
stefanf116bd02015-10-27 08:29:42 -07002085
2086 return SEND_PACKET;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002087 }
2088
2089 bool MinMetricRunTimePassed() {
2090 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
2091 if (start_runtime_ms_ == -1) {
2092 start_runtime_ms_ = now;
2093 return false;
2094 }
2095 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
2096 return elapsed_sec > metrics::kMinRunTimeInSeconds * 2;
2097 }
2098
stefanff483612015-12-21 03:14:00 -08002099 void ModifyVideoConfigs(
2100 VideoSendStream::Config* send_config,
2101 std::vector<VideoReceiveStream::Config>* receive_configs,
2102 VideoEncoderConfig* encoder_config) override {
Åsa Persson3c391cb2015-04-27 10:09:49 +02002103 // NACK
2104 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2105 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2106 // FEC
2107 if (use_red_) {
2108 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
2109 send_config->rtp.fec.red_payload_type = kRedPayloadType;
2110 (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
2111 (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
2112 }
2113 // RTX
2114 if (use_rtx_) {
2115 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
2116 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002117 (*receive_configs)[0].rtp.rtx[kFakeVideoSendPayloadType].ssrc =
Åsa Persson3c391cb2015-04-27 10:09:49 +02002118 kSendRtxSsrcs[0];
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002119 (*receive_configs)[0].rtp.rtx[kFakeVideoSendPayloadType].payload_type =
Åsa Persson3c391cb2015-04-27 10:09:49 +02002120 kSendRtxPayloadType;
2121 }
sprangb4a1ae52015-12-03 08:10:08 -08002122 encoder_config->content_type =
2123 screenshare_ ? VideoEncoderConfig::ContentType::kScreen
2124 : VideoEncoderConfig::ContentType::kRealtimeVideo;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002125 }
2126
2127 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2128 sender_call_ = sender_call;
2129 receiver_call_ = receiver_call;
2130 }
2131
Åsa Persson3c391cb2015-04-27 10:09:49 +02002132 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002133 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Åsa Persson3c391cb2015-04-27 10:09:49 +02002134 }
2135
sprangb4a1ae52015-12-03 08:10:08 -08002136 const bool use_rtx_;
2137 const bool use_red_;
2138 const bool screenshare_;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002139 Call* sender_call_;
2140 Call* receiver_call_;
2141 int64_t start_runtime_ms_;
sprangb4a1ae52015-12-03 08:10:08 -08002142 } test(use_rtx, use_red, screenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002143
2144 test::ClearHistograms();
stefane74eef12016-01-08 06:47:13 -08002145 RunBaseTest(&test);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002146
stefan91d92602015-11-11 10:13:02 -08002147 // Delete the call for Call stats to be reported.
stefan18adf0a2015-11-17 06:24:56 -08002148 sender_call_.reset();
stefan91d92602015-11-11 10:13:02 -08002149 receiver_call_.reset();
2150
sprangb4a1ae52015-12-03 08:10:08 -08002151 std::string video_prefix =
2152 screenshare ? "WebRTC.Video.Screenshare." : "WebRTC.Video.";
2153
Åsa Persson3c391cb2015-04-27 10:09:49 +02002154 // Verify that stats have been updated once.
stefan91d92602015-11-11 10:13:02 -08002155 EXPECT_EQ(
2156 1, test::NumHistogramSamples("WebRTC.Call.VideoBitrateReceivedInKbps"));
2157 EXPECT_EQ(1,
2158 test::NumHistogramSamples("WebRTC.Call.RtcpBitrateReceivedInBps"));
2159 EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Call.BitrateReceivedInKbps"));
stefan18adf0a2015-11-17 06:24:56 -08002160 EXPECT_EQ(
2161 1, test::NumHistogramSamples("WebRTC.Call.EstimatedSendBitrateInKbps"));
2162 EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Call.PacerBitrateInKbps"));
stefan91d92602015-11-11 10:13:02 -08002163
Åsa Persson3c391cb2015-04-27 10:09:49 +02002164 EXPECT_EQ(1, test::NumHistogramSamples(
2165 "WebRTC.Video.NackPacketsSentPerMinute"));
2166 EXPECT_EQ(1, test::NumHistogramSamples(
2167 "WebRTC.Video.NackPacketsReceivedPerMinute"));
2168 EXPECT_EQ(1, test::NumHistogramSamples(
2169 "WebRTC.Video.FirPacketsSentPerMinute"));
2170 EXPECT_EQ(1, test::NumHistogramSamples(
2171 "WebRTC.Video.FirPacketsReceivedPerMinute"));
2172 EXPECT_EQ(1, test::NumHistogramSamples(
2173 "WebRTC.Video.PliPacketsSentPerMinute"));
2174 EXPECT_EQ(1, test::NumHistogramSamples(
2175 "WebRTC.Video.PliPacketsReceivedPerMinute"));
2176
sprangb4a1ae52015-12-03 08:10:08 -08002177 EXPECT_EQ(
2178 1, test::NumHistogramSamples(video_prefix + "KeyFramesSentInPermille"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002179 EXPECT_EQ(1, test::NumHistogramSamples(
2180 "WebRTC.Video.KeyFramesReceivedInPermille"));
2181
2182 EXPECT_EQ(1, test::NumHistogramSamples(
2183 "WebRTC.Video.SentPacketsLostInPercent"));
2184 EXPECT_EQ(1, test::NumHistogramSamples(
2185 "WebRTC.Video.ReceivedPacketsLostInPercent"));
2186
sprangb4a1ae52015-12-03 08:10:08 -08002187 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "InputWidthInPixels"));
2188 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "InputHeightInPixels"));
2189 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "SentWidthInPixels"));
2190 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "SentHeightInPixels"));
asaperssond89920b2015-07-22 06:52:00 -07002191 EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.ReceivedWidthInPixels"));
2192 EXPECT_EQ(1,
2193 test::NumHistogramSamples("WebRTC.Video.ReceivedHeightInPixels"));
2194
stefanff483612015-12-21 03:14:00 -08002195 EXPECT_EQ(static_cast<int>(video_encoder_config_.streams[0].width),
sprangb4a1ae52015-12-03 08:10:08 -08002196 test::LastHistogramSample(video_prefix + "InputWidthInPixels"));
stefanff483612015-12-21 03:14:00 -08002197 EXPECT_EQ(static_cast<int>(video_encoder_config_.streams[0].height),
sprangb4a1ae52015-12-03 08:10:08 -08002198 test::LastHistogramSample(video_prefix + "InputHeightInPixels"));
stefanff483612015-12-21 03:14:00 -08002199 EXPECT_EQ(static_cast<int>(video_encoder_config_.streams[0].width),
sprangb4a1ae52015-12-03 08:10:08 -08002200 test::LastHistogramSample(video_prefix + "SentWidthInPixels"));
stefanff483612015-12-21 03:14:00 -08002201 EXPECT_EQ(static_cast<int>(video_encoder_config_.streams[0].height),
sprangb4a1ae52015-12-03 08:10:08 -08002202 test::LastHistogramSample(video_prefix + "SentHeightInPixels"));
stefanff483612015-12-21 03:14:00 -08002203 EXPECT_EQ(static_cast<int>(video_encoder_config_.streams[0].width),
asaperssond89920b2015-07-22 06:52:00 -07002204 test::LastHistogramSample("WebRTC.Video.ReceivedWidthInPixels"));
stefanff483612015-12-21 03:14:00 -08002205 EXPECT_EQ(static_cast<int>(video_encoder_config_.streams[0].height),
asaperssond89920b2015-07-22 06:52:00 -07002206 test::LastHistogramSample("WebRTC.Video.ReceivedHeightInPixels"));
2207
sprangb4a1ae52015-12-03 08:10:08 -08002208 EXPECT_EQ(1,
2209 test::NumHistogramSamples(video_prefix + "InputFramesPerSecond"));
2210 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "SentFramesPerSecond"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002211 EXPECT_EQ(1, test::NumHistogramSamples(
2212 "WebRTC.Video.DecodedFramesPerSecond"));
asaperssond89920b2015-07-22 06:52:00 -07002213 EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.RenderFramesPerSecond"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002214
asapersson6f14be82015-11-16 00:40:49 -08002215 EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.OnewayDelayInMs"));
2216 EXPECT_EQ(
2217 1, test::NumHistogramSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
2218
sprangb4a1ae52015-12-03 08:10:08 -08002219 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "EncodeTimeInMs"));
asapersson6718e972015-07-24 00:20:58 -07002220 EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.DecodeTimeInMs"));
2221
Åsa Persson3c391cb2015-04-27 10:09:49 +02002222 EXPECT_EQ(1, test::NumHistogramSamples(
2223 "WebRTC.Video.BitrateSentInKbps"));
2224 EXPECT_EQ(1, test::NumHistogramSamples(
2225 "WebRTC.Video.BitrateReceivedInKbps"));
2226 EXPECT_EQ(1, test::NumHistogramSamples(
2227 "WebRTC.Video.MediaBitrateSentInKbps"));
2228 EXPECT_EQ(1, test::NumHistogramSamples(
2229 "WebRTC.Video.MediaBitrateReceivedInKbps"));
2230 EXPECT_EQ(1, test::NumHistogramSamples(
2231 "WebRTC.Video.PaddingBitrateSentInKbps"));
2232 EXPECT_EQ(1, test::NumHistogramSamples(
2233 "WebRTC.Video.PaddingBitrateReceivedInKbps"));
2234 EXPECT_EQ(1, test::NumHistogramSamples(
2235 "WebRTC.Video.RetransmittedBitrateSentInKbps"));
2236 EXPECT_EQ(1, test::NumHistogramSamples(
2237 "WebRTC.Video.RetransmittedBitrateReceivedInKbps"));
2238
sprangb4a1ae52015-12-03 08:10:08 -08002239 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "SendSideDelayInMs"));
2240 EXPECT_EQ(1,
2241 test::NumHistogramSamples(video_prefix + "SendSideDelayMaxInMs"));
asapersson6f14be82015-11-16 00:40:49 -08002242
Åsa Persson3c391cb2015-04-27 10:09:49 +02002243 int num_rtx_samples = use_rtx ? 1 : 0;
2244 EXPECT_EQ(num_rtx_samples, test::NumHistogramSamples(
2245 "WebRTC.Video.RtxBitrateSentInKbps"));
2246 EXPECT_EQ(num_rtx_samples, test::NumHistogramSamples(
2247 "WebRTC.Video.RtxBitrateReceivedInKbps"));
2248
2249 int num_red_samples = use_red ? 1 : 0;
2250 EXPECT_EQ(num_red_samples, test::NumHistogramSamples(
2251 "WebRTC.Video.FecBitrateSentInKbps"));
2252 EXPECT_EQ(num_red_samples, test::NumHistogramSamples(
2253 "WebRTC.Video.FecBitrateReceivedInKbps"));
2254 EXPECT_EQ(num_red_samples, test::NumHistogramSamples(
2255 "WebRTC.Video.ReceivedFecPacketsInPercent"));
2256}
2257
2258TEST_F(EndToEndTest, VerifyHistogramStatsWithRtx) {
2259 const bool kEnabledRtx = true;
2260 const bool kEnabledRed = false;
sprangb4a1ae52015-12-03 08:10:08 -08002261 const bool kScreenshare = false;
2262 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002263}
2264
2265TEST_F(EndToEndTest, VerifyHistogramStatsWithRed) {
2266 const bool kEnabledRtx = false;
2267 const bool kEnabledRed = true;
sprangb4a1ae52015-12-03 08:10:08 -08002268 const bool kScreenshare = false;
2269 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
2270}
2271
2272TEST_F(EndToEndTest, VerifyHistogramStatsWithScreenshare) {
2273 const bool kEnabledRtx = false;
2274 const bool kEnabledRed = false;
2275 const bool kScreenshare = true;
2276 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002277}
2278
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002279void EndToEndTest::TestXrReceiverReferenceTimeReport(bool enable_rrtr) {
2280 static const int kNumRtcpReportPacketsToObserve = 5;
2281 class RtcpXrObserver : public test::EndToEndTest {
2282 public:
2283 explicit RtcpXrObserver(bool enable_rrtr)
2284 : EndToEndTest(kDefaultTimeoutMs),
2285 enable_rrtr_(enable_rrtr),
2286 sent_rtcp_sr_(0),
2287 sent_rtcp_rr_(0),
2288 sent_rtcp_rrtr_(0),
2289 sent_rtcp_dlrr_(0) {}
2290
2291 private:
2292 // Receive stream should send RR packets (and RRTR packets if enabled).
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002293 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002294 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002295 RTCPUtility::RTCPParserV2 parser(packet, length, true);
2296 EXPECT_TRUE(parser.IsValid());
2297
2298 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02002299 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
2300 if (packet_type == RTCPUtility::RTCPPacketTypes::kRr) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002301 ++sent_rtcp_rr_;
2302 } else if (packet_type ==
Erik Språng242e22b2015-05-11 10:17:43 +02002303 RTCPUtility::RTCPPacketTypes::kXrReceiverReferenceTime) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002304 ++sent_rtcp_rrtr_;
2305 }
Erik Språng242e22b2015-05-11 10:17:43 +02002306 EXPECT_NE(packet_type, RTCPUtility::RTCPPacketTypes::kSr);
2307 EXPECT_NE(packet_type,
2308 RTCPUtility::RTCPPacketTypes::kXrDlrrReportBlockItem);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002309 packet_type = parser.Iterate();
2310 }
2311 return SEND_PACKET;
2312 }
2313 // Send stream should send SR packets (and DLRR packets if enabled).
2314 virtual Action OnSendRtcp(const uint8_t* packet, size_t length) {
stefan608213e2015-11-01 14:56:10 -08002315 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002316 RTCPUtility::RTCPParserV2 parser(packet, length, true);
2317 EXPECT_TRUE(parser.IsValid());
2318
2319 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02002320 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
2321 if (packet_type == RTCPUtility::RTCPPacketTypes::kSr) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002322 ++sent_rtcp_sr_;
Erik Språng242e22b2015-05-11 10:17:43 +02002323 } else if (packet_type ==
2324 RTCPUtility::RTCPPacketTypes::kXrDlrrReportBlockItem) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002325 ++sent_rtcp_dlrr_;
2326 }
Erik Språng242e22b2015-05-11 10:17:43 +02002327 EXPECT_NE(packet_type,
2328 RTCPUtility::RTCPPacketTypes::kXrReceiverReferenceTime);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002329 packet_type = parser.Iterate();
2330 }
2331 if (sent_rtcp_sr_ > kNumRtcpReportPacketsToObserve &&
2332 sent_rtcp_rr_ > kNumRtcpReportPacketsToObserve) {
2333 if (enable_rrtr_) {
2334 EXPECT_GT(sent_rtcp_rrtr_, 0);
2335 EXPECT_GT(sent_rtcp_dlrr_, 0);
2336 } else {
2337 EXPECT_EQ(0, sent_rtcp_rrtr_);
2338 EXPECT_EQ(0, sent_rtcp_dlrr_);
2339 }
Peter Boström5811a392015-12-10 13:02:50 +01002340 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002341 }
2342 return SEND_PACKET;
2343 }
2344
stefanff483612015-12-21 03:14:00 -08002345 void ModifyVideoConfigs(
2346 VideoSendStream::Config* send_config,
2347 std::vector<VideoReceiveStream::Config>* receive_configs,
2348 VideoEncoderConfig* encoder_config) override {
pbosda903ea2015-10-02 02:36:56 -07002349 (*receive_configs)[0].rtp.rtcp_mode = RtcpMode::kReducedSize;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002350 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report =
2351 enable_rrtr_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002352 }
2353
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002354 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002355 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002356 << "Timed out while waiting for RTCP SR/RR packets to be sent.";
2357 }
2358
stefan608213e2015-11-01 14:56:10 -08002359 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002360 bool enable_rrtr_;
2361 int sent_rtcp_sr_;
stefan608213e2015-11-01 14:56:10 -08002362 int sent_rtcp_rr_ GUARDED_BY(&crit_);
2363 int sent_rtcp_rrtr_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002364 int sent_rtcp_dlrr_;
2365 } test(enable_rrtr);
2366
stefane74eef12016-01-08 06:47:13 -08002367 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002368}
2369
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002370void EndToEndTest::TestSendsSetSsrcs(size_t num_ssrcs,
2371 bool send_single_ssrc_first) {
2372 class SendsSetSsrcs : public test::EndToEndTest {
2373 public:
2374 SendsSetSsrcs(const uint32_t* ssrcs,
2375 size_t num_ssrcs,
2376 bool send_single_ssrc_first)
2377 : EndToEndTest(kDefaultTimeoutMs),
2378 num_ssrcs_(num_ssrcs),
2379 send_single_ssrc_first_(send_single_ssrc_first),
2380 ssrcs_to_observe_(num_ssrcs),
sprang867fb522015-08-03 04:38:41 -07002381 expect_single_ssrc_(send_single_ssrc_first),
2382 send_stream_(nullptr) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002383 for (size_t i = 0; i < num_ssrcs; ++i)
2384 valid_ssrcs_[ssrcs[i]] = true;
2385 }
2386
2387 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002388 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002389 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002390 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002391
2392 EXPECT_TRUE(valid_ssrcs_[header.ssrc])
2393 << "Received unknown SSRC: " << header.ssrc;
2394
2395 if (!valid_ssrcs_[header.ssrc])
Peter Boström5811a392015-12-10 13:02:50 +01002396 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002397
2398 if (!is_observed_[header.ssrc]) {
2399 is_observed_[header.ssrc] = true;
2400 --ssrcs_to_observe_;
2401 if (expect_single_ssrc_) {
2402 expect_single_ssrc_ = false;
Peter Boström5811a392015-12-10 13:02:50 +01002403 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002404 }
2405 }
2406
2407 if (ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01002408 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002409
2410 return SEND_PACKET;
2411 }
2412
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002413 size_t GetNumVideoStreams() const override { return num_ssrcs_; }
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002414
stefanff483612015-12-21 03:14:00 -08002415 void ModifyVideoConfigs(
2416 VideoSendStream::Config* send_config,
2417 std::vector<VideoReceiveStream::Config>* receive_configs,
2418 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002419 if (num_ssrcs_ > 1) {
2420 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002421 for (size_t i = 0; i < encoder_config->streams.size(); ++i) {
2422 encoder_config->streams[i].min_bitrate_bps = 10000;
2423 encoder_config->streams[i].target_bitrate_bps = 15000;
2424 encoder_config->streams[i].max_bitrate_bps = 20000;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002425 }
2426 }
2427
stefanff483612015-12-21 03:14:00 -08002428 video_encoder_config_all_streams_ = *encoder_config;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002429 if (send_single_ssrc_first_)
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002430 encoder_config->streams.resize(1);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002431 }
2432
stefanff483612015-12-21 03:14:00 -08002433 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002434 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002435 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002436 send_stream_ = send_stream;
2437 }
2438
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002439 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002440 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
2441 << (send_single_ssrc_first_ ? "first SSRC."
2442 : "SSRCs.");
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002443
2444 if (send_single_ssrc_first_) {
2445 // Set full simulcast and continue with the rest of the SSRCs.
stefanff483612015-12-21 03:14:00 -08002446 send_stream_->ReconfigureVideoEncoder(
2447 video_encoder_config_all_streams_);
Peter Boström5811a392015-12-10 13:02:50 +01002448 EXPECT_TRUE(Wait()) << "Timed out while waiting on additional SSRCs.";
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002449 }
2450 }
2451
2452 private:
2453 std::map<uint32_t, bool> valid_ssrcs_;
2454 std::map<uint32_t, bool> is_observed_;
2455
2456 const size_t num_ssrcs_;
2457 const bool send_single_ssrc_first_;
2458
2459 size_t ssrcs_to_observe_;
2460 bool expect_single_ssrc_;
2461
2462 VideoSendStream* send_stream_;
stefanff483612015-12-21 03:14:00 -08002463 VideoEncoderConfig video_encoder_config_all_streams_;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002464 } test(kVideoSendSsrcs, num_ssrcs, send_single_ssrc_first);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002465
stefane74eef12016-01-08 06:47:13 -08002466 RunBaseTest(&test);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002467}
2468
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002469TEST_F(EndToEndTest, ReportsSetEncoderRates) {
2470 class EncoderRateStatsTest : public test::EndToEndTest,
2471 public test::FakeEncoder {
2472 public:
2473 EncoderRateStatsTest()
2474 : EndToEndTest(kDefaultTimeoutMs),
sprang867fb522015-08-03 04:38:41 -07002475 FakeEncoder(Clock::GetRealTimeClock()),
2476 send_stream_(nullptr),
2477 bitrate_kbps_(0) {}
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002478
stefanff483612015-12-21 03:14:00 -08002479 void OnVideoStreamsCreated(
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002480 VideoSendStream* send_stream,
2481 const std::vector<VideoReceiveStream*>& receive_streams) override {
2482 send_stream_ = send_stream;
2483 }
2484
stefanff483612015-12-21 03:14:00 -08002485 void ModifyVideoConfigs(
2486 VideoSendStream::Config* send_config,
2487 std::vector<VideoReceiveStream::Config>* receive_configs,
2488 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002489 send_config->encoder_settings.encoder = this;
2490 }
2491
2492 int32_t SetRates(uint32_t new_target_bitrate, uint32_t framerate) override {
2493 // Make sure not to trigger on any default zero bitrates.
2494 if (new_target_bitrate == 0)
2495 return 0;
Peter Boströmf2f82832015-05-01 13:00:41 +02002496 rtc::CritScope lock(&crit_);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002497 bitrate_kbps_ = new_target_bitrate;
Peter Boström5811a392015-12-10 13:02:50 +01002498 observation_complete_.Set();
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002499 return 0;
2500 }
2501
2502 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002503 ASSERT_TRUE(Wait())
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002504 << "Timed out while waiting for encoder SetRates() call.";
2505 // Wait for GetStats to report a corresponding bitrate.
Peter Boström5811a392015-12-10 13:02:50 +01002506 for (int i = 0; i < kDefaultTimeoutMs; ++i) {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002507 VideoSendStream::Stats stats = send_stream_->GetStats();
2508 {
Peter Boströmf2f82832015-05-01 13:00:41 +02002509 rtc::CritScope lock(&crit_);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002510 if ((stats.target_media_bitrate_bps + 500) / 1000 ==
2511 static_cast<int>(bitrate_kbps_)) {
2512 return;
2513 }
2514 }
2515 SleepMs(1);
2516 }
2517 FAIL()
2518 << "Timed out waiting for stats reporting the currently set bitrate.";
2519 }
2520
2521 private:
stefanf116bd02015-10-27 08:29:42 -07002522 rtc::CriticalSection crit_;
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002523 VideoSendStream* send_stream_;
2524 uint32_t bitrate_kbps_ GUARDED_BY(crit_);
2525 } test;
2526
stefane74eef12016-01-08 06:47:13 -08002527 RunBaseTest(&test);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002528}
2529
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002530TEST_F(EndToEndTest, GetStats) {
2531 static const int kStartBitrateBps = 3000000;
Peter Boströmdef398832015-05-27 17:59:11 +02002532 static const int kExpectedRenderDelayMs = 20;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002533 class StatsObserver : public test::EndToEndTest, public I420FrameCallback {
2534 public:
stefanf116bd02015-10-27 08:29:42 -07002535 StatsObserver()
2536 : EndToEndTest(kLongTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00002537 send_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002538 expected_send_ssrcs_(),
Peter Boström5811a392015-12-10 13:02:50 +01002539 check_stats_event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002540
2541 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002542 Action OnSendRtp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002543 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002544 return SEND_PACKET;
2545 }
2546
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002547 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002548 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002549 return SEND_PACKET;
2550 }
2551
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002552 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002553 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002554 return SEND_PACKET;
2555 }
2556
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002557 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002558 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002559 return SEND_PACKET;
2560 }
2561
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07002562 void FrameCallback(VideoFrame* video_frame) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002563 // Ensure that we have at least 5ms send side delay.
2564 int64_t render_time = video_frame->render_time_ms();
2565 if (render_time > 0)
2566 video_frame->set_render_time_ms(render_time - 5);
2567 }
2568
2569 bool CheckReceiveStats() {
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002570 for (size_t i = 0; i < receive_streams_.size(); ++i) {
2571 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
2572 EXPECT_EQ(expected_receive_ssrcs_[i], stats.ssrc);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002573
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002574 // Make sure all fields have been populated.
2575 // TODO(pbos): Use CompoundKey if/when we ever know that all stats are
2576 // always filled for all receivers.
2577 receive_stats_filled_["IncomingRate"] |=
2578 stats.network_frame_rate != 0 || stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002579
Peter Boströmb7d9a972015-12-18 16:01:11 +01002580 send_stats_filled_["DecoderImplementationName"] |=
2581 stats.decoder_implementation_name ==
2582 test::FakeDecoder::kImplementationName;
Peter Boströmdef398832015-05-27 17:59:11 +02002583 receive_stats_filled_["RenderDelayAsHighAsExpected"] |=
2584 stats.render_delay_ms >= kExpectedRenderDelayMs;
2585
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002586 receive_stats_filled_["FrameCallback"] |= stats.decode_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002587
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002588 receive_stats_filled_["FrameRendered"] |= stats.render_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002589
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002590 receive_stats_filled_["StatisticsUpdated"] |=
2591 stats.rtcp_stats.cumulative_lost != 0 ||
2592 stats.rtcp_stats.extended_max_sequence_number != 0 ||
2593 stats.rtcp_stats.fraction_lost != 0 || stats.rtcp_stats.jitter != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002594
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002595 receive_stats_filled_["DataCountersUpdated"] |=
2596 stats.rtp_stats.transmitted.payload_bytes != 0 ||
2597 stats.rtp_stats.fec.packets != 0 ||
2598 stats.rtp_stats.transmitted.header_bytes != 0 ||
2599 stats.rtp_stats.transmitted.packets != 0 ||
2600 stats.rtp_stats.transmitted.padding_bytes != 0 ||
2601 stats.rtp_stats.retransmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002602
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002603 receive_stats_filled_["CodecStats"] |=
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002604 stats.target_delay_ms != 0 || stats.discarded_packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002605
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002606 receive_stats_filled_["FrameCounts"] |=
2607 stats.frame_counts.key_frames != 0 ||
2608 stats.frame_counts.delta_frames != 0;
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002609
pbosbb36fdf2015-07-09 07:48:14 -07002610 receive_stats_filled_["CName"] |= !stats.c_name.empty();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002611
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002612 receive_stats_filled_["RtcpPacketTypeCount"] |=
2613 stats.rtcp_packet_type_counts.fir_packets != 0 ||
2614 stats.rtcp_packet_type_counts.nack_packets != 0 ||
2615 stats.rtcp_packet_type_counts.pli_packets != 0 ||
2616 stats.rtcp_packet_type_counts.nack_requests != 0 ||
2617 stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbosf42376c2015-08-28 07:35:32 -07002618
2619 assert(stats.current_payload_type == -1 ||
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002620 stats.current_payload_type == kFakeVideoSendPayloadType);
pbosf42376c2015-08-28 07:35:32 -07002621 receive_stats_filled_["IncomingPayloadType"] |=
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002622 stats.current_payload_type == kFakeVideoSendPayloadType;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002623 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002624
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002625 return AllStatsFilled(receive_stats_filled_);
2626 }
2627
2628 bool CheckSendStats() {
henrikg91d6ede2015-09-17 00:24:34 -07002629 RTC_DCHECK(send_stream_ != nullptr);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002630 VideoSendStream::Stats stats = send_stream_->GetStats();
2631
2632 send_stats_filled_["NumStreams"] |=
2633 stats.substreams.size() == expected_send_ssrcs_.size();
2634
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00002635 send_stats_filled_["CpuOveruseMetrics"] |=
2636 stats.avg_encode_time_ms != 0 || stats.encode_usage_percent != 0;
2637
Peter Boströmb7d9a972015-12-18 16:01:11 +01002638 send_stats_filled_["EncoderImplementationName"] |=
2639 stats.encoder_implementation_name ==
2640 test::FakeEncoder::kImplementationName;
2641
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002642 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002643 stats.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002644 it != stats.substreams.end(); ++it) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002645 EXPECT_TRUE(expected_send_ssrcs_.find(it->first) !=
2646 expected_send_ssrcs_.end());
2647
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002648 send_stats_filled_[CompoundKey("CapturedFrameRate", it->first)] |=
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002649 stats.input_frame_rate != 0;
2650
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002651 const VideoSendStream::StreamStats& stream_stats = it->second;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002652
2653 send_stats_filled_[CompoundKey("StatisticsUpdated", it->first)] |=
2654 stream_stats.rtcp_stats.cumulative_lost != 0 ||
2655 stream_stats.rtcp_stats.extended_max_sequence_number != 0 ||
2656 stream_stats.rtcp_stats.fraction_lost != 0;
2657
2658 send_stats_filled_[CompoundKey("DataCountersUpdated", it->first)] |=
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00002659 stream_stats.rtp_stats.fec.packets != 0 ||
2660 stream_stats.rtp_stats.transmitted.padding_bytes != 0 ||
2661 stream_stats.rtp_stats.retransmitted.packets != 0 ||
2662 stream_stats.rtp_stats.transmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002663
2664 send_stats_filled_[CompoundKey("BitrateStatisticsObserver",
2665 it->first)] |=
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002666 stream_stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002667
2668 send_stats_filled_[CompoundKey("FrameCountObserver", it->first)] |=
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002669 stream_stats.frame_counts.delta_frames != 0 ||
2670 stream_stats.frame_counts.key_frames != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002671
2672 send_stats_filled_[CompoundKey("OutgoingRate", it->first)] |=
2673 stats.encode_frame_rate != 0;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +00002674
2675 send_stats_filled_[CompoundKey("Delay", it->first)] |=
2676 stream_stats.avg_delay_ms != 0 || stream_stats.max_delay_ms != 0;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002677
2678 // TODO(pbos): Use CompoundKey when the test makes sure that all SSRCs
2679 // report dropped packets.
2680 send_stats_filled_["RtcpPacketTypeCount"] |=
2681 stream_stats.rtcp_packet_type_counts.fir_packets != 0 ||
2682 stream_stats.rtcp_packet_type_counts.nack_packets != 0 ||
2683 stream_stats.rtcp_packet_type_counts.pli_packets != 0 ||
2684 stream_stats.rtcp_packet_type_counts.nack_requests != 0 ||
2685 stream_stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002686 }
2687
2688 return AllStatsFilled(send_stats_filled_);
2689 }
2690
2691 std::string CompoundKey(const char* name, uint32_t ssrc) {
2692 std::ostringstream oss;
2693 oss << name << "_" << ssrc;
2694 return oss.str();
2695 }
2696
2697 bool AllStatsFilled(const std::map<std::string, bool>& stats_map) {
2698 for (std::map<std::string, bool>::const_iterator it = stats_map.begin();
2699 it != stats_map.end();
2700 ++it) {
2701 if (!it->second)
2702 return false;
2703 }
2704 return true;
2705 }
2706
stefane74eef12016-01-08 06:47:13 -08002707 test::PacketTransport* CreateSendTransport(Call* sender_call) override {
2708 FakeNetworkPipe::Config network_config;
2709 network_config.loss_percent = 5;
2710 return new test::PacketTransport(
2711 sender_call, this, test::PacketTransport::kSender, network_config);
2712 }
2713
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002714 Call::Config GetSenderCallConfig() override {
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002715 Call::Config config = EndToEndTest::GetSenderCallConfig();
Stefan Holmere5904162015-03-26 11:11:06 +01002716 config.bitrate_config.start_bitrate_bps = kStartBitrateBps;
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002717 return config;
2718 }
2719
stefanff483612015-12-21 03:14:00 -08002720 void ModifyVideoConfigs(
2721 VideoSendStream::Config* send_config,
2722 std::vector<VideoReceiveStream::Config>* receive_configs,
2723 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002724 send_config->pre_encode_callback = this; // Used to inject delay.
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002725 expected_cname_ = send_config->rtp.c_name = "SomeCName";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002726
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002727 const std::vector<uint32_t>& ssrcs = send_config->rtp.ssrcs;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002728 for (size_t i = 0; i < ssrcs.size(); ++i) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002729 expected_send_ssrcs_.insert(ssrcs[i]);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002730 expected_receive_ssrcs_.push_back(
2731 (*receive_configs)[i].rtp.remote_ssrc);
Peter Boströmdef398832015-05-27 17:59:11 +02002732 (*receive_configs)[i].render_delay_ms = kExpectedRenderDelayMs;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002733 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002734 }
2735
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002736 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.orgece38902014-11-14 11:52:04 +00002737
stefanff483612015-12-21 03:14:00 -08002738 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002739 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002740 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002741 send_stream_ = send_stream;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002742 receive_streams_ = receive_streams;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002743 }
2744
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002745 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002746 Clock* clock = Clock::GetRealTimeClock();
2747 int64_t now = clock->TimeInMilliseconds();
2748 int64_t stop_time = now + test::CallTest::kLongTimeoutMs;
2749 bool receive_ok = false;
2750 bool send_ok = false;
2751
2752 while (now < stop_time) {
2753 if (!receive_ok)
2754 receive_ok = CheckReceiveStats();
2755 if (!send_ok)
2756 send_ok = CheckSendStats();
2757
2758 if (receive_ok && send_ok)
2759 return;
2760
2761 int64_t time_until_timout_ = stop_time - now;
2762 if (time_until_timout_ > 0)
Peter Boström5811a392015-12-10 13:02:50 +01002763 check_stats_event_.Wait(time_until_timout_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002764 now = clock->TimeInMilliseconds();
2765 }
2766
2767 ADD_FAILURE() << "Timed out waiting for filled stats.";
2768 for (std::map<std::string, bool>::const_iterator it =
2769 receive_stats_filled_.begin();
2770 it != receive_stats_filled_.end();
2771 ++it) {
2772 if (!it->second) {
2773 ADD_FAILURE() << "Missing receive stats: " << it->first;
2774 }
2775 }
2776
2777 for (std::map<std::string, bool>::const_iterator it =
2778 send_stats_filled_.begin();
2779 it != send_stats_filled_.end();
2780 ++it) {
2781 if (!it->second) {
2782 ADD_FAILURE() << "Missing send stats: " << it->first;
2783 }
2784 }
2785 }
2786
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002787 std::vector<VideoReceiveStream*> receive_streams_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002788 std::map<std::string, bool> receive_stats_filled_;
2789
2790 VideoSendStream* send_stream_;
2791 std::map<std::string, bool> send_stats_filled_;
2792
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002793 std::vector<uint32_t> expected_receive_ssrcs_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002794 std::set<uint32_t> expected_send_ssrcs_;
2795 std::string expected_cname_;
2796
Peter Boström5811a392015-12-10 13:02:50 +01002797 rtc::Event check_stats_event_;
stefanf116bd02015-10-27 08:29:42 -07002798 } test;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002799
stefane74eef12016-01-08 06:47:13 -08002800 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002801}
2802
2803TEST_F(EndToEndTest, ReceiverReferenceTimeReportEnabled) {
2804 TestXrReceiverReferenceTimeReport(true);
2805}
2806
2807TEST_F(EndToEndTest, ReceiverReferenceTimeReportDisabled) {
2808 TestXrReceiverReferenceTimeReport(false);
2809}
2810
2811TEST_F(EndToEndTest, TestReceivedRtpPacketStats) {
2812 static const size_t kNumRtpPacketsToSend = 5;
2813 class ReceivedRtpStatsObserver : public test::EndToEndTest {
2814 public:
2815 ReceivedRtpStatsObserver()
2816 : EndToEndTest(kDefaultTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00002817 receive_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002818 sent_rtp_(0) {}
2819
2820 private:
stefanff483612015-12-21 03:14:00 -08002821 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002822 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002823 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002824 receive_stream_ = receive_streams[0];
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002825 }
2826
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002827 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002828 if (sent_rtp_ >= kNumRtpPacketsToSend) {
2829 VideoReceiveStream::Stats stats = receive_stream_->GetStats();
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00002830 if (kNumRtpPacketsToSend == stats.rtp_stats.transmitted.packets) {
Peter Boström5811a392015-12-10 13:02:50 +01002831 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002832 }
2833 return DROP_PACKET;
2834 }
2835 ++sent_rtp_;
2836 return SEND_PACKET;
2837 }
2838
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002839 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002840 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002841 << "Timed out while verifying number of received RTP packets.";
2842 }
2843
2844 VideoReceiveStream* receive_stream_;
2845 uint32_t sent_rtp_;
2846 } test;
2847
stefane74eef12016-01-08 06:47:13 -08002848 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002849}
2850
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002851TEST_F(EndToEndTest, SendsSetSsrc) { TestSendsSetSsrcs(1, false); }
2852
2853TEST_F(EndToEndTest, SendsSetSimulcastSsrcs) {
2854 TestSendsSetSsrcs(kNumSsrcs, false);
2855}
2856
2857TEST_F(EndToEndTest, CanSwitchToUseAllSsrcs) {
2858 TestSendsSetSsrcs(kNumSsrcs, true);
2859}
2860
mflodman@webrtc.orgf9460682014-07-24 16:41:25 +00002861TEST_F(EndToEndTest, DISABLED_RedundantPayloadsTransmittedOnAllSsrcs) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002862 class ObserveRedundantPayloads: public test::EndToEndTest {
2863 public:
2864 ObserveRedundantPayloads()
2865 : EndToEndTest(kDefaultTimeoutMs), ssrcs_to_observe_(kNumSsrcs) {
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00002866 for (size_t i = 0; i < kNumSsrcs; ++i) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002867 registered_rtx_ssrc_[kSendRtxSsrcs[i]] = true;
2868 }
2869 }
2870
2871 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002872 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002873 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002874 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002875
2876 if (!registered_rtx_ssrc_[header.ssrc])
2877 return SEND_PACKET;
2878
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00002879 EXPECT_LE(header.headerLength + header.paddingLength, length);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002880 const bool packet_is_redundant_payload =
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00002881 header.headerLength + header.paddingLength < length;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002882
2883 if (!packet_is_redundant_payload)
2884 return SEND_PACKET;
2885
2886 if (!observed_redundant_retransmission_[header.ssrc]) {
2887 observed_redundant_retransmission_[header.ssrc] = true;
2888 if (--ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01002889 observation_complete_.Set();
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002890 }
2891
2892 return SEND_PACKET;
2893 }
2894
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002895 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002896
stefanff483612015-12-21 03:14:00 -08002897 void ModifyVideoConfigs(
2898 VideoSendStream::Config* send_config,
2899 std::vector<VideoReceiveStream::Config>* receive_configs,
2900 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002901 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002902 for (size_t i = 0; i < encoder_config->streams.size(); ++i) {
2903 encoder_config->streams[i].min_bitrate_bps = 10000;
2904 encoder_config->streams[i].target_bitrate_bps = 15000;
2905 encoder_config->streams[i].max_bitrate_bps = 20000;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002906 }
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002907
2908 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002909
2910 for (size_t i = 0; i < kNumSsrcs; ++i)
2911 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.orgad3b5a52014-10-24 09:23:21 +00002912
2913 // Significantly higher than max bitrates for all video streams -> forcing
2914 // padding to trigger redundant padding on all RTX SSRCs.
2915 encoder_config->min_transmit_bitrate_bps = 100000;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002916 }
2917
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002918 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002919 EXPECT_TRUE(Wait())
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002920 << "Timed out while waiting for redundant payloads on all SSRCs.";
2921 }
2922
2923 private:
2924 size_t ssrcs_to_observe_;
2925 std::map<uint32_t, bool> observed_redundant_retransmission_;
2926 std::map<uint32_t, bool> registered_rtx_ssrc_;
2927 } test;
2928
stefane74eef12016-01-08 06:47:13 -08002929 RunBaseTest(&test);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002930}
2931
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002932void EndToEndTest::TestRtpStatePreservation(bool use_rtx) {
2933 static const uint32_t kMaxSequenceNumberGap = 100;
2934 static const uint64_t kMaxTimestampGap = kDefaultTimeoutMs * 90;
2935 class RtpSequenceObserver : public test::RtpRtcpObserver {
2936 public:
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00002937 explicit RtpSequenceObserver(bool use_rtx)
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002938 : test::RtpRtcpObserver(kDefaultTimeoutMs),
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002939 ssrcs_to_observe_(kNumSsrcs) {
2940 for (size_t i = 0; i < kNumSsrcs; ++i) {
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002941 configured_ssrcs_[kVideoSendSsrcs[i]] = true;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002942 if (use_rtx)
2943 configured_ssrcs_[kSendRtxSsrcs[i]] = true;
2944 }
2945 }
2946
2947 void ResetExpectedSsrcs(size_t num_expected_ssrcs) {
Peter Boströmf2f82832015-05-01 13:00:41 +02002948 rtc::CritScope lock(&crit_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002949 ssrc_observed_.clear();
2950 ssrcs_to_observe_ = num_expected_ssrcs;
2951 }
2952
2953 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002954 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002955 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002956 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002957 const uint32_t ssrc = header.ssrc;
2958 const uint16_t sequence_number = header.sequenceNumber;
2959 const uint32_t timestamp = header.timestamp;
2960 const bool only_padding =
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00002961 header.headerLength + header.paddingLength == length;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002962
2963 EXPECT_TRUE(configured_ssrcs_[ssrc])
2964 << "Received SSRC that wasn't configured: " << ssrc;
2965
2966 std::map<uint32_t, uint16_t>::iterator it =
2967 last_observed_sequence_number_.find(header.ssrc);
2968 if (it == last_observed_sequence_number_.end()) {
2969 last_observed_sequence_number_[ssrc] = sequence_number;
2970 last_observed_timestamp_[ssrc] = timestamp;
2971 } else {
2972 // Verify sequence numbers are reasonably close.
2973 uint32_t extended_sequence_number = sequence_number;
2974 // Check for roll-over.
2975 if (sequence_number < last_observed_sequence_number_[ssrc])
2976 extended_sequence_number += 0xFFFFu + 1;
2977 EXPECT_LE(
2978 extended_sequence_number - last_observed_sequence_number_[ssrc],
2979 kMaxSequenceNumberGap)
2980 << "Gap in sequence numbers ("
2981 << last_observed_sequence_number_[ssrc] << " -> " << sequence_number
2982 << ") too large for SSRC: " << ssrc << ".";
2983 last_observed_sequence_number_[ssrc] = sequence_number;
2984
2985 // TODO(pbos): Remove this check if we ever have monotonically
2986 // increasing timestamps. Right now padding packets add a delta which
2987 // can cause reordering between padding packets and regular packets,
2988 // hence we drop padding-only packets to not flake.
2989 if (only_padding) {
2990 // Verify that timestamps are reasonably close.
2991 uint64_t extended_timestamp = timestamp;
2992 // Check for roll-over.
2993 if (timestamp < last_observed_timestamp_[ssrc])
2994 extended_timestamp += static_cast<uint64_t>(0xFFFFFFFFu) + 1;
2995 EXPECT_LE(extended_timestamp - last_observed_timestamp_[ssrc],
2996 kMaxTimestampGap)
2997 << "Gap in timestamps (" << last_observed_timestamp_[ssrc]
2998 << " -> " << timestamp << ") too large for SSRC: " << ssrc << ".";
2999 }
3000 last_observed_timestamp_[ssrc] = timestamp;
3001 }
3002
Peter Boströmf2f82832015-05-01 13:00:41 +02003003 rtc::CritScope lock(&crit_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003004 // Wait for media packets on all ssrcs.
3005 if (!ssrc_observed_[ssrc] && !only_padding) {
3006 ssrc_observed_[ssrc] = true;
3007 if (--ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01003008 observation_complete_.Set();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003009 }
3010
3011 return SEND_PACKET;
3012 }
3013
3014 std::map<uint32_t, uint16_t> last_observed_sequence_number_;
3015 std::map<uint32_t, uint32_t> last_observed_timestamp_;
3016 std::map<uint32_t, bool> configured_ssrcs_;
3017
Peter Boströmf2f82832015-05-01 13:00:41 +02003018 rtc::CriticalSection crit_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003019 size_t ssrcs_to_observe_ GUARDED_BY(crit_);
3020 std::map<uint32_t, bool> ssrc_observed_ GUARDED_BY(crit_);
3021 } observer(use_rtx);
3022
solenberg4fbae2b2015-08-28 04:07:10 -07003023 CreateCalls(Call::Config(), Call::Config());
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003024
stefanf116bd02015-10-27 08:29:42 -07003025 test::PacketTransport send_transport(sender_call_.get(), &observer,
3026 test::PacketTransport::kSender,
3027 FakeNetworkPipe::Config());
3028 test::PacketTransport receive_transport(nullptr, &observer,
3029 test::PacketTransport::kReceiver,
3030 FakeNetworkPipe::Config());
3031 send_transport.SetReceiver(receiver_call_->Receiver());
3032 receive_transport.SetReceiver(sender_call_->Receiver());
3033
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003034 CreateSendConfig(kNumSsrcs, 0, &send_transport);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003035
3036 if (use_rtx) {
3037 for (size_t i = 0; i < kNumSsrcs; ++i) {
stefanff483612015-12-21 03:14:00 -08003038 video_send_config_.rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003039 }
stefanff483612015-12-21 03:14:00 -08003040 video_send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003041 }
3042
3043 // Lower bitrates so that all streams send initially.
stefanff483612015-12-21 03:14:00 -08003044 for (size_t i = 0; i < video_encoder_config_.streams.size(); ++i) {
3045 video_encoder_config_.streams[i].min_bitrate_bps = 10000;
3046 video_encoder_config_.streams[i].target_bitrate_bps = 15000;
3047 video_encoder_config_.streams[i].max_bitrate_bps = 20000;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003048 }
3049
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003050 // Use the same total bitrates when sending a single stream to avoid lowering
3051 // the bitrate estimate and requiring a subsequent rampup.
stefanff483612015-12-21 03:14:00 -08003052 VideoEncoderConfig one_stream = video_encoder_config_;
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003053 one_stream.streams.resize(1);
stefanff483612015-12-21 03:14:00 -08003054 for (size_t i = 1; i < video_encoder_config_.streams.size(); ++i) {
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003055 one_stream.streams.front().min_bitrate_bps +=
stefanff483612015-12-21 03:14:00 -08003056 video_encoder_config_.streams[i].min_bitrate_bps;
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003057 one_stream.streams.front().target_bitrate_bps +=
stefanff483612015-12-21 03:14:00 -08003058 video_encoder_config_.streams[i].target_bitrate_bps;
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003059 one_stream.streams.front().max_bitrate_bps +=
stefanff483612015-12-21 03:14:00 -08003060 video_encoder_config_.streams[i].max_bitrate_bps;
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003061 }
3062
stefanf116bd02015-10-27 08:29:42 -07003063 CreateMatchingReceiveConfigs(&receive_transport);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003064
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003065 CreateVideoStreams();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003066 CreateFrameGeneratorCapturer();
3067
3068 Start();
Peter Boström5811a392015-12-10 13:02:50 +01003069 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003070 << "Timed out waiting for all SSRCs to send packets.";
3071
3072 // Test stream resetting more than once to make sure that the state doesn't
3073 // get set once (this could be due to using std::map::insert for instance).
3074 for (size_t i = 0; i < 3; ++i) {
3075 frame_generator_capturer_->Stop();
stefanff483612015-12-21 03:14:00 -08003076 sender_call_->DestroyVideoSendStream(video_send_stream_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003077
3078 // Re-create VideoSendStream with only one stream.
stefanff483612015-12-21 03:14:00 -08003079 video_send_stream_ =
3080 sender_call_->CreateVideoSendStream(video_send_config_, one_stream);
3081 video_send_stream_->Start();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003082 CreateFrameGeneratorCapturer();
3083 frame_generator_capturer_->Start();
3084
3085 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01003086 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003087
3088 // Reconfigure back to use all streams.
stefanff483612015-12-21 03:14:00 -08003089 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003090 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01003091 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003092 << "Timed out waiting for all SSRCs to send packets.";
3093
3094 // Reconfigure down to one stream.
stefanff483612015-12-21 03:14:00 -08003095 video_send_stream_->ReconfigureVideoEncoder(one_stream);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003096 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01003097 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003098
3099 // Reconfigure back to use all streams.
stefanff483612015-12-21 03:14:00 -08003100 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003101 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01003102 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003103 << "Timed out waiting for all SSRCs to send packets.";
3104 }
3105
stefanf116bd02015-10-27 08:29:42 -07003106 send_transport.StopSending();
3107 receive_transport.StopSending();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003108
3109 Stop();
3110 DestroyStreams();
3111}
3112
aluebs@webrtc.orgb623c5c2014-08-26 14:22:51 +00003113TEST_F(EndToEndTest, DISABLED_RestartingSendStreamPreservesRtpState) {
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003114 TestRtpStatePreservation(false);
3115}
3116
3117TEST_F(EndToEndTest, RestartingSendStreamPreservesRtpStatesWithRtx) {
3118 TestRtpStatePreservation(true);
3119}
3120
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003121TEST_F(EndToEndTest, RespectsNetworkState) {
3122 // TODO(pbos): Remove accepted downtime packets etc. when signaling network
3123 // down blocks until no more packets will be sent.
3124
3125 // Pacer will send from its packet list and then send required padding before
3126 // checking paused_ again. This should be enough for one round of pacing,
3127 // otherwise increase.
3128 static const int kNumAcceptedDowntimeRtp = 5;
3129 // A single RTCP may be in the pipeline.
3130 static const int kNumAcceptedDowntimeRtcp = 1;
3131 class NetworkStateTest : public test::EndToEndTest, public test::FakeEncoder {
3132 public:
3133 NetworkStateTest()
3134 : EndToEndTest(kDefaultTimeoutMs),
3135 FakeEncoder(Clock::GetRealTimeClock()),
Peter Boström5811a392015-12-10 13:02:50 +01003136 encoded_frames_(false, false),
3137 packet_event_(false, false),
sprang867fb522015-08-03 04:38:41 -07003138 sender_call_(nullptr),
3139 receiver_call_(nullptr),
Jelena Marusiccd670222015-07-16 09:30:09 +02003140 sender_state_(kNetworkUp),
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003141 sender_rtp_(0),
3142 sender_rtcp_(0),
3143 receiver_rtcp_(0),
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003144 down_frames_(0) {}
3145
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003146 Action OnSendRtp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003147 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003148 ++sender_rtp_;
Peter Boström5811a392015-12-10 13:02:50 +01003149 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003150 return SEND_PACKET;
3151 }
3152
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003153 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003154 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003155 ++sender_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01003156 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003157 return SEND_PACKET;
3158 }
3159
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003160 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003161 ADD_FAILURE() << "Unexpected receiver RTP, should not be sending.";
3162 return SEND_PACKET;
3163 }
3164
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003165 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003166 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003167 ++receiver_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01003168 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003169 return SEND_PACKET;
3170 }
3171
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003172 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003173 sender_call_ = sender_call;
3174 receiver_call_ = receiver_call;
3175 }
3176
stefanff483612015-12-21 03:14:00 -08003177 void ModifyVideoConfigs(
3178 VideoSendStream::Config* send_config,
3179 std::vector<VideoReceiveStream::Config>* receive_configs,
3180 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003181 send_config->encoder_settings.encoder = this;
3182 }
3183
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003184 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003185 EXPECT_TRUE(encoded_frames_.Wait(kDefaultTimeoutMs))
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003186 << "No frames received by the encoder.";
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003187 // Wait for packets from both sender/receiver.
3188 WaitForPacketsOrSilence(false, false);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003189
3190 // Sender-side network down.
Jelena Marusiccd670222015-07-16 09:30:09 +02003191 sender_call_->SignalNetworkState(kNetworkDown);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003192 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003193 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003194 // After network goes down we shouldn't be encoding more frames.
Jelena Marusiccd670222015-07-16 09:30:09 +02003195 sender_state_ = kNetworkDown;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003196 }
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003197 // Wait for receiver-packets and no sender packets.
3198 WaitForPacketsOrSilence(true, false);
3199
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003200 // Receiver-side network down.
Jelena Marusiccd670222015-07-16 09:30:09 +02003201 receiver_call_->SignalNetworkState(kNetworkDown);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003202 WaitForPacketsOrSilence(true, true);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003203
3204 // Network back up again for both.
3205 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003206 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003207 // It's OK to encode frames again, as we're about to bring up the
3208 // network.
Jelena Marusiccd670222015-07-16 09:30:09 +02003209 sender_state_ = kNetworkUp;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003210 }
Jelena Marusiccd670222015-07-16 09:30:09 +02003211 sender_call_->SignalNetworkState(kNetworkUp);
3212 receiver_call_->SignalNetworkState(kNetworkUp);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003213 WaitForPacketsOrSilence(false, false);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003214 }
3215
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07003216 int32_t Encode(const VideoFrame& input_image,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003217 const CodecSpecificInfo* codec_specific_info,
pbos22993e12015-10-19 02:39:06 -07003218 const std::vector<FrameType>* frame_types) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003219 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003220 rtc::CritScope lock(&test_crit_);
Jelena Marusiccd670222015-07-16 09:30:09 +02003221 if (sender_state_ == kNetworkDown) {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003222 ++down_frames_;
3223 EXPECT_LE(down_frames_, 1)
3224 << "Encoding more than one frame while network is down.";
3225 if (down_frames_ > 1)
Peter Boström5811a392015-12-10 13:02:50 +01003226 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003227 } else {
Peter Boström5811a392015-12-10 13:02:50 +01003228 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003229 }
3230 }
3231 return test::FakeEncoder::Encode(
3232 input_image, codec_specific_info, frame_types);
3233 }
3234
3235 private:
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003236 void WaitForPacketsOrSilence(bool sender_down, bool receiver_down) {
3237 int64_t initial_time_ms = clock_->TimeInMilliseconds();
3238 int initial_sender_rtp;
3239 int initial_sender_rtcp;
3240 int initial_receiver_rtcp;
3241 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003242 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003243 initial_sender_rtp = sender_rtp_;
3244 initial_sender_rtcp = sender_rtcp_;
3245 initial_receiver_rtcp = receiver_rtcp_;
3246 }
3247 bool sender_done = false;
3248 bool receiver_done = false;
mflodmand1590b22015-12-09 07:07:59 -08003249 while (!sender_done || !receiver_done) {
Peter Boström5811a392015-12-10 13:02:50 +01003250 packet_event_.Wait(kSilenceTimeoutMs);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003251 int64_t time_now_ms = clock_->TimeInMilliseconds();
Peter Boströmf2f82832015-05-01 13:00:41 +02003252 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003253 if (sender_down) {
3254 ASSERT_LE(sender_rtp_ - initial_sender_rtp, kNumAcceptedDowntimeRtp)
3255 << "RTP sent during sender-side downtime.";
3256 ASSERT_LE(sender_rtcp_ - initial_sender_rtcp,
3257 kNumAcceptedDowntimeRtcp)
3258 << "RTCP sent during sender-side downtime.";
3259 if (time_now_ms - initial_time_ms >=
3260 static_cast<int64_t>(kSilenceTimeoutMs)) {
3261 sender_done = true;
3262 }
3263 } else {
3264 if (sender_rtp_ > initial_sender_rtp)
3265 sender_done = true;
3266 }
3267 if (receiver_down) {
3268 ASSERT_LE(receiver_rtcp_ - initial_receiver_rtcp,
3269 kNumAcceptedDowntimeRtcp)
3270 << "RTCP sent during receiver-side downtime.";
3271 if (time_now_ms - initial_time_ms >=
3272 static_cast<int64_t>(kSilenceTimeoutMs)) {
3273 receiver_done = true;
3274 }
3275 } else {
3276 if (receiver_rtcp_ > initial_receiver_rtcp)
3277 receiver_done = true;
3278 }
3279 }
3280 }
3281
Peter Boströmf2f82832015-05-01 13:00:41 +02003282 rtc::CriticalSection test_crit_;
Peter Boström5811a392015-12-10 13:02:50 +01003283 rtc::Event encoded_frames_;
3284 rtc::Event packet_event_;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003285 Call* sender_call_;
3286 Call* receiver_call_;
Jelena Marusiccd670222015-07-16 09:30:09 +02003287 NetworkState sender_state_ GUARDED_BY(test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003288 int sender_rtp_ GUARDED_BY(test_crit_);
3289 int sender_rtcp_ GUARDED_BY(test_crit_);
3290 int receiver_rtcp_ GUARDED_BY(test_crit_);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003291 int down_frames_ GUARDED_BY(test_crit_);
3292 } test;
3293
stefane74eef12016-01-08 06:47:13 -08003294 RunBaseTest(&test);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003295}
3296
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003297TEST_F(EndToEndTest, CallReportsRttForSender) {
3298 static const int kSendDelayMs = 30;
3299 static const int kReceiveDelayMs = 70;
3300
solenberg4fbae2b2015-08-28 04:07:10 -07003301 CreateCalls(Call::Config(), Call::Config());
3302
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003303 FakeNetworkPipe::Config config;
3304 config.queue_delay_ms = kSendDelayMs;
stefanf116bd02015-10-27 08:29:42 -07003305 test::DirectTransport sender_transport(config, sender_call_.get());
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003306 config.queue_delay_ms = kReceiveDelayMs;
stefanf116bd02015-10-27 08:29:42 -07003307 test::DirectTransport receiver_transport(config, receiver_call_.get());
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003308 sender_transport.SetReceiver(receiver_call_->Receiver());
3309 receiver_transport.SetReceiver(sender_call_->Receiver());
3310
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003311 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07003312 CreateMatchingReceiveConfigs(&receiver_transport);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003313
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003314 CreateVideoStreams();
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003315 CreateFrameGeneratorCapturer();
3316 Start();
3317
3318 int64_t start_time_ms = clock_->TimeInMilliseconds();
3319 while (true) {
3320 Call::Stats stats = sender_call_->GetStats();
3321 ASSERT_GE(start_time_ms + kDefaultTimeoutMs,
3322 clock_->TimeInMilliseconds())
3323 << "No RTT stats before timeout!";
3324 if (stats.rtt_ms != -1) {
3325 EXPECT_GE(stats.rtt_ms, kSendDelayMs + kReceiveDelayMs);
3326 break;
3327 }
3328 SleepMs(10);
3329 }
3330
3331 Stop();
3332 DestroyStreams();
3333}
3334
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003335TEST_F(EndToEndTest, NewSendStreamsRespectNetworkDown) {
3336 class UnusedEncoder : public test::FakeEncoder {
mflodmand1590b22015-12-09 07:07:59 -08003337 public:
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003338 UnusedEncoder() : FakeEncoder(Clock::GetRealTimeClock()) {}
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07003339 int32_t Encode(const VideoFrame& input_image,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003340 const CodecSpecificInfo* codec_specific_info,
pbos22993e12015-10-19 02:39:06 -07003341 const std::vector<FrameType>* frame_types) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003342 ADD_FAILURE() << "Unexpected frame encode.";
3343 return test::FakeEncoder::Encode(
3344 input_image, codec_specific_info, frame_types);
3345 }
3346 };
3347
solenberg4fbae2b2015-08-28 04:07:10 -07003348 CreateSenderCall(Call::Config());
Jelena Marusiccd670222015-07-16 09:30:09 +02003349 sender_call_->SignalNetworkState(kNetworkDown);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003350
solenberg4fbae2b2015-08-28 04:07:10 -07003351 UnusedTransport transport;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003352 CreateSendConfig(1, 0, &transport);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003353 UnusedEncoder unused_encoder;
stefanff483612015-12-21 03:14:00 -08003354 video_send_config_.encoder_settings.encoder = &unused_encoder;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003355 CreateVideoStreams();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003356 CreateFrameGeneratorCapturer();
3357
3358 Start();
3359 SleepMs(kSilenceTimeoutMs);
3360 Stop();
3361
3362 DestroyStreams();
3363}
3364
3365TEST_F(EndToEndTest, NewReceiveStreamsRespectNetworkDown) {
solenberg4fbae2b2015-08-28 04:07:10 -07003366 CreateCalls(Call::Config(), Call::Config());
Jelena Marusiccd670222015-07-16 09:30:09 +02003367 receiver_call_->SignalNetworkState(kNetworkDown);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003368
stefanf116bd02015-10-27 08:29:42 -07003369 test::DirectTransport sender_transport(sender_call_.get());
solenberg4fbae2b2015-08-28 04:07:10 -07003370 sender_transport.SetReceiver(receiver_call_->Receiver());
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003371 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07003372 UnusedTransport transport;
3373 CreateMatchingReceiveConfigs(&transport);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003374 CreateVideoStreams();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003375 CreateFrameGeneratorCapturer();
3376
3377 Start();
3378 SleepMs(kSilenceTimeoutMs);
3379 Stop();
3380
3381 sender_transport.StopSending();
3382
3383 DestroyStreams();
3384}
pbos@webrtc.org09cc6862014-11-04 13:48:15 +00003385
Peter Boströmd7da1202015-06-05 14:09:38 +02003386void VerifyEmptyNackConfig(const NackConfig& config) {
3387 EXPECT_EQ(0, config.rtp_history_ms)
3388 << "Enabling NACK requires rtcp-fb: nack negotiation.";
3389}
3390
3391void VerifyEmptyFecConfig(const FecConfig& config) {
3392 EXPECT_EQ(-1, config.ulpfec_payload_type)
3393 << "Enabling FEC requires rtpmap: ulpfec negotiation.";
3394 EXPECT_EQ(-1, config.red_payload_type)
3395 << "Enabling FEC requires rtpmap: red negotiation.";
3396 EXPECT_EQ(-1, config.red_rtx_payload_type)
3397 << "Enabling RTX in FEC requires rtpmap: rtx negotiation.";
3398}
3399
3400TEST_F(EndToEndTest, VerifyDefaultSendConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07003401 VideoSendStream::Config default_send_config(nullptr);
Peter Boströmd7da1202015-06-05 14:09:38 +02003402 EXPECT_EQ(0, default_send_config.rtp.nack.rtp_history_ms)
3403 << "Enabling NACK require rtcp-fb: nack negotiation.";
3404 EXPECT_TRUE(default_send_config.rtp.rtx.ssrcs.empty())
3405 << "Enabling RTX requires rtpmap: rtx negotiation.";
3406 EXPECT_TRUE(default_send_config.rtp.extensions.empty())
3407 << "Enabling RTP extensions require negotiation.";
3408
3409 VerifyEmptyNackConfig(default_send_config.rtp.nack);
3410 VerifyEmptyFecConfig(default_send_config.rtp.fec);
3411}
3412
3413TEST_F(EndToEndTest, VerifyDefaultReceiveConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07003414 VideoReceiveStream::Config default_receive_config(nullptr);
pbosda903ea2015-10-02 02:36:56 -07003415 EXPECT_EQ(RtcpMode::kCompound, default_receive_config.rtp.rtcp_mode)
Peter Boströmd7da1202015-06-05 14:09:38 +02003416 << "Reduced-size RTCP require rtcp-rsize to be negotiated.";
3417 EXPECT_FALSE(default_receive_config.rtp.remb)
3418 << "REMB require rtcp-fb: goog-remb to be negotiated.";
3419 EXPECT_FALSE(
3420 default_receive_config.rtp.rtcp_xr.receiver_reference_time_report)
3421 << "RTCP XR settings require rtcp-xr to be negotiated.";
3422 EXPECT_TRUE(default_receive_config.rtp.rtx.empty())
3423 << "Enabling RTX requires rtpmap: rtx negotiation.";
3424 EXPECT_TRUE(default_receive_config.rtp.extensions.empty())
3425 << "Enabling RTP extensions require negotiation.";
3426
3427 VerifyEmptyNackConfig(default_receive_config.rtp.nack);
3428 VerifyEmptyFecConfig(default_receive_config.rtp.fec);
3429}
3430
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003431TEST_F(EndToEndTest, TransportSeqNumOnAudioAndVideo) {
3432 static const int kExtensionId = 8;
3433 class TransportSequenceNumberTest : public test::EndToEndTest {
3434 public:
3435 TransportSequenceNumberTest()
3436 : EndToEndTest(kDefaultTimeoutMs),
3437 video_observed_(false),
3438 audio_observed_(false) {
3439 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
3440 kExtensionId);
3441 }
3442
3443 size_t GetNumVideoStreams() const override { return 1; }
3444 size_t GetNumAudioStreams() const override { return 1; }
3445
3446 void ModifyVideoConfigs(
3447 VideoSendStream::Config* send_config,
3448 std::vector<VideoReceiveStream::Config>* receive_configs,
3449 VideoEncoderConfig* encoder_config) override {
3450 send_config->rtp.extensions.clear();
3451 send_config->rtp.extensions.push_back(
3452 RtpExtension(RtpExtension::kTransportSequenceNumber, kExtensionId));
3453 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
3454 }
3455
3456 void ModifyAudioConfigs(
3457 AudioSendStream::Config* send_config,
3458 std::vector<AudioReceiveStream::Config>* receive_configs) override {
3459 send_config->rtp.extensions.clear();
3460 send_config->rtp.extensions.push_back(
3461 RtpExtension(RtpExtension::kTransportSequenceNumber, kExtensionId));
3462 (*receive_configs)[0].rtp.extensions.clear();
3463 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
3464 }
3465
3466 Action OnSendRtp(const uint8_t* packet, size_t length) override {
3467 RTPHeader header;
3468 EXPECT_TRUE(parser_->Parse(packet, length, &header));
3469 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
3470 // Unwrap packet id and verify uniqueness.
3471 int64_t packet_id =
3472 unwrapper_.Unwrap(header.extension.transportSequenceNumber);
3473 EXPECT_TRUE(received_packet_ids_.insert(packet_id).second);
3474
3475 if (header.ssrc == kVideoSendSsrcs[0])
3476 video_observed_ = true;
3477 if (header.ssrc == kAudioSendSsrc)
3478 audio_observed_ = true;
3479 if (audio_observed_ && video_observed_ &&
3480 received_packet_ids_.size() == 50) {
3481 size_t packet_id_range =
3482 *received_packet_ids_.rbegin() - *received_packet_ids_.begin() + 1;
3483 EXPECT_EQ(received_packet_ids_.size(), packet_id_range);
3484 observation_complete_.Set();
3485 }
3486 return SEND_PACKET;
3487 }
3488
3489 void PerformTest() override {
3490 EXPECT_TRUE(Wait()) << "Timed out while waiting for audio and video "
3491 "packets with transport sequence number.";
3492 }
3493
3494 private:
3495 bool video_observed_;
3496 bool audio_observed_;
3497 SequenceNumberUnwrapper unwrapper_;
3498 std::set<int64_t> received_packet_ids_;
3499 } test;
3500
stefane74eef12016-01-08 06:47:13 -08003501 RunBaseTest(&test);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003502}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003503} // namespace webrtc