blob: 48dc3e8bbd223495345f3482c03ef4e50dd278a5 [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"
sprang861c55e2015-10-16 10:01:21 -070023#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000024#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
marpan@webrtc.org5b883172014-11-01 06:10:48 +000025#include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h"
26#include "webrtc/modules/video_coding/codecs/vp9/include/vp9.h"
Henrik Kjellander2557b862015-11-18 22:00:21 +010027#include "webrtc/modules/video_coding/include/video_coding_defines.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010028#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010029#include "webrtc/system_wrappers/include/metrics.h"
30#include "webrtc/system_wrappers/include/sleep.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000031#include "webrtc/test/call_test.h"
32#include "webrtc/test/direct_transport.h"
33#include "webrtc/test/encoder_settings.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000034#include "webrtc/test/fake_decoder.h"
35#include "webrtc/test/fake_encoder.h"
36#include "webrtc/test/frame_generator.h"
37#include "webrtc/test/frame_generator_capturer.h"
Åsa Persson352b2d72015-04-15 18:00:40 +020038#include "webrtc/test/histogram.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000039#include "webrtc/test/null_transport.h"
asapersson@webrtc.org37c05592015-01-28 13:58:27 +000040#include "webrtc/test/rtcp_packet_parser.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000041#include "webrtc/test/rtp_rtcp_observer.h"
42#include "webrtc/test/testsupport/fileutils.h"
43#include "webrtc/test/testsupport/perf_test.h"
pbos@webrtc.orgab990ae2014-09-17 09:02:25 +000044#include "webrtc/video_encoder.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000045
46namespace webrtc {
47
Peter Boström5811a392015-12-10 13:02:50 +010048static const int kSilenceTimeoutMs = 2000;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000049
50class EndToEndTest : public test::CallTest {
51 public:
52 EndToEndTest() {}
53
54 virtual ~EndToEndTest() {
stefanff483612015-12-21 03:14:00 -080055 EXPECT_EQ(nullptr, video_send_stream_);
56 EXPECT_TRUE(video_receive_streams_.empty());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000057 }
58
59 protected:
pbos2d566682015-09-28 09:59:31 -070060 class UnusedTransport : public Transport {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000061 private:
stefan1d8a5062015-10-02 03:39:33 -070062 bool SendRtp(const uint8_t* packet,
63 size_t length,
64 const PacketOptions& options) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000065 ADD_FAILURE() << "Unexpected RTP sent.";
66 return false;
67 }
68
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000069 bool SendRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000070 ADD_FAILURE() << "Unexpected RTCP sent.";
71 return false;
72 }
73 };
74
Shao Changbine62202f2015-04-21 20:24:50 +080075 void DecodesRetransmittedFrame(bool use_rtx, bool use_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000076 void ReceivesPliAndRecovers(int rtp_history_ms);
pbosda903ea2015-10-02 02:36:56 -070077 void RespectsRtcpMode(RtcpMode rtcp_mode);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000078 void TestXrReceiverReferenceTimeReport(bool enable_rrtr);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +000079 void TestSendsSetSsrcs(size_t num_ssrcs, bool send_single_ssrc_first);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +000080 void TestRtpStatePreservation(bool use_rtx);
sprangb4a1ae52015-12-03 08:10:08 -080081 void VerifyHistogramStats(bool use_rtx, bool use_red, bool screenshare);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000082};
83
84TEST_F(EndToEndTest, ReceiverCanBeStartedTwice) {
solenberg4fbae2b2015-08-28 04:07:10 -070085 CreateCalls(Call::Config(), Call::Config());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000086
solenberg4fbae2b2015-08-28 04:07:10 -070087 test::NullTransport transport;
Stefan Holmer9fea80f2016-01-07 17:43:18 +010088 CreateSendConfig(1, 0, &transport);
solenberg4fbae2b2015-08-28 04:07:10 -070089 CreateMatchingReceiveConfigs(&transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000090
Stefan Holmer9fea80f2016-01-07 17:43:18 +010091 CreateVideoStreams();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000092
stefanff483612015-12-21 03:14:00 -080093 video_receive_streams_[0]->Start();
94 video_receive_streams_[0]->Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000095
96 DestroyStreams();
97}
98
99TEST_F(EndToEndTest, ReceiverCanBeStoppedTwice) {
solenberg4fbae2b2015-08-28 04:07:10 -0700100 CreateCalls(Call::Config(), Call::Config());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000101
solenberg4fbae2b2015-08-28 04:07:10 -0700102 test::NullTransport transport;
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100103 CreateSendConfig(1, 0, &transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700104 CreateMatchingReceiveConfigs(&transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000105
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100106 CreateVideoStreams();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000107
stefanff483612015-12-21 03:14:00 -0800108 video_receive_streams_[0]->Stop();
109 video_receive_streams_[0]->Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000110
111 DestroyStreams();
112}
113
114TEST_F(EndToEndTest, RendersSingleDelayedFrame) {
115 static const int kWidth = 320;
116 static const int kHeight = 240;
117 // This constant is chosen to be higher than the timeout in the video_render
118 // module. This makes sure that frames aren't dropped if there are no other
119 // frames in the queue.
120 static const int kDelayRenderCallbackMs = 1000;
121
122 class Renderer : public VideoRenderer {
123 public:
Peter Boström5811a392015-12-10 13:02:50 +0100124 Renderer() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000125
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700126 void RenderFrame(const VideoFrame& video_frame,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000127 int /*time_to_render_ms*/) override {
Peter Boström5811a392015-12-10 13:02:50 +0100128 event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000129 }
130
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000131 bool IsTextureSupported() const override { return false; }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000132
Peter Boström5811a392015-12-10 13:02:50 +0100133 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000134
Peter Boström5811a392015-12-10 13:02:50 +0100135 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000136 } renderer;
137
138 class TestFrameCallback : public I420FrameCallback {
139 public:
Peter Boström5811a392015-12-10 13:02:50 +0100140 TestFrameCallback() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000141
Peter Boström5811a392015-12-10 13:02:50 +0100142 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000143
144 private:
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700145 void FrameCallback(VideoFrame* frame) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000146 SleepMs(kDelayRenderCallbackMs);
Peter Boström5811a392015-12-10 13:02:50 +0100147 event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000148 }
149
Peter Boström5811a392015-12-10 13:02:50 +0100150 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000151 };
152
solenberg4fbae2b2015-08-28 04:07:10 -0700153 CreateCalls(Call::Config(), Call::Config());
154
stefanf116bd02015-10-27 08:29:42 -0700155 test::DirectTransport sender_transport(sender_call_.get());
156 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000157 sender_transport.SetReceiver(receiver_call_->Receiver());
158 receiver_transport.SetReceiver(sender_call_->Receiver());
159
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100160 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700161 CreateMatchingReceiveConfigs(&receiver_transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000162
163 TestFrameCallback pre_render_callback;
stefanff483612015-12-21 03:14:00 -0800164 video_receive_configs_[0].pre_render_callback = &pre_render_callback;
165 video_receive_configs_[0].renderer = &renderer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000166
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100167 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000168 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000169
170 // Create frames that are smaller than the send width/height, this is done to
171 // check that the callbacks are done after processing video.
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000172 rtc::scoped_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +0000173 test::FrameGenerator::CreateChromaGenerator(kWidth, kHeight));
stefanff483612015-12-21 03:14:00 -0800174 video_send_stream_->Input()->IncomingCapturedFrame(
175 *frame_generator->NextFrame());
Peter Boström5811a392015-12-10 13:02:50 +0100176 EXPECT_TRUE(pre_render_callback.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000177 << "Timed out while waiting for pre-render callback.";
Peter Boström5811a392015-12-10 13:02:50 +0100178 EXPECT_TRUE(renderer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000179 << "Timed out while waiting for the frame to render.";
180
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000181 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000182
183 sender_transport.StopSending();
184 receiver_transport.StopSending();
185
186 DestroyStreams();
187}
188
189TEST_F(EndToEndTest, TransmitsFirstFrame) {
190 class Renderer : public VideoRenderer {
191 public:
Peter Boström5811a392015-12-10 13:02:50 +0100192 Renderer() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000193
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700194 void RenderFrame(const VideoFrame& video_frame,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000195 int /*time_to_render_ms*/) override {
Peter Boström5811a392015-12-10 13:02:50 +0100196 event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000197 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000198 bool IsTextureSupported() const override { return false; }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000199
Peter Boström5811a392015-12-10 13:02:50 +0100200 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000201
Peter Boström5811a392015-12-10 13:02:50 +0100202 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000203 } renderer;
204
solenberg4fbae2b2015-08-28 04:07:10 -0700205 CreateCalls(Call::Config(), Call::Config());
206
stefanf116bd02015-10-27 08:29:42 -0700207 test::DirectTransport sender_transport(sender_call_.get());
208 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000209 sender_transport.SetReceiver(receiver_call_->Receiver());
210 receiver_transport.SetReceiver(sender_call_->Receiver());
211
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100212 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700213 CreateMatchingReceiveConfigs(&receiver_transport);
stefanff483612015-12-21 03:14:00 -0800214 video_receive_configs_[0].renderer = &renderer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000215
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100216 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000217 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000218
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000219 rtc::scoped_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +0000220 test::FrameGenerator::CreateChromaGenerator(
stefanff483612015-12-21 03:14:00 -0800221 video_encoder_config_.streams[0].width,
222 video_encoder_config_.streams[0].height));
223 video_send_stream_->Input()->IncomingCapturedFrame(
224 *frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000225
Peter Boström5811a392015-12-10 13:02:50 +0100226 EXPECT_TRUE(renderer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000227 << "Timed out while waiting for the frame to render.";
228
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000229 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000230
231 sender_transport.StopSending();
232 receiver_transport.StopSending();
233
234 DestroyStreams();
235}
236
marpan@webrtc.org5f1e2e42014-11-06 02:02:28 +0000237TEST_F(EndToEndTest, SendsAndReceivesVP9) {
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000238 class VP9Observer : public test::EndToEndTest, public VideoRenderer {
239 public:
240 VP9Observer()
241 : EndToEndTest(2 * kDefaultTimeoutMs),
242 encoder_(VideoEncoder::Create(VideoEncoder::kVp9)),
243 decoder_(VP9Decoder::Create()),
244 frame_counter_(0) {}
245
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000246 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100247 EXPECT_TRUE(Wait())
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000248 << "Timed out while waiting for enough frames to be decoded.";
249 }
250
stefanff483612015-12-21 03:14:00 -0800251 void ModifyVideoConfigs(
252 VideoSendStream::Config* send_config,
253 std::vector<VideoReceiveStream::Config>* receive_configs,
254 VideoEncoderConfig* encoder_config) override {
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000255 send_config->encoder_settings.encoder = encoder_.get();
256 send_config->encoder_settings.payload_name = "VP9";
pbosa7d70542015-07-07 07:35:49 -0700257 send_config->encoder_settings.payload_type = 124;
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000258 encoder_config->streams[0].min_bitrate_bps = 50000;
259 encoder_config->streams[0].target_bitrate_bps =
260 encoder_config->streams[0].max_bitrate_bps = 2000000;
261
262 (*receive_configs)[0].renderer = this;
263 (*receive_configs)[0].decoders.resize(1);
264 (*receive_configs)[0].decoders[0].payload_type =
265 send_config->encoder_settings.payload_type;
266 (*receive_configs)[0].decoders[0].payload_name =
267 send_config->encoder_settings.payload_name;
268 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
269 }
270
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700271 void RenderFrame(const VideoFrame& video_frame,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000272 int time_to_render_ms) override {
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000273 const int kRequiredFrames = 500;
274 if (++frame_counter_ == kRequiredFrames)
Peter Boström5811a392015-12-10 13:02:50 +0100275 observation_complete_.Set();
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000276 }
277
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000278 bool IsTextureSupported() const override { return false; }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000279
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000280 private:
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000281 rtc::scoped_ptr<webrtc::VideoEncoder> encoder_;
282 rtc::scoped_ptr<webrtc::VideoDecoder> decoder_;
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000283 int frame_counter_;
284 } test;
285
stefane74eef12016-01-08 06:47:13 -0800286 RunBaseTest(&test);
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000287}
288
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000289TEST_F(EndToEndTest, SendsAndReceivesH264) {
290 class H264Observer : public test::EndToEndTest, public VideoRenderer {
291 public:
292 H264Observer()
293 : EndToEndTest(2 * kDefaultTimeoutMs),
294 fake_encoder_(Clock::GetRealTimeClock()),
295 frame_counter_(0) {}
296
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000297 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100298 EXPECT_TRUE(Wait())
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000299 << "Timed out while waiting for enough frames to be decoded.";
300 }
301
stefanff483612015-12-21 03:14:00 -0800302 void ModifyVideoConfigs(
303 VideoSendStream::Config* send_config,
304 std::vector<VideoReceiveStream::Config>* receive_configs,
305 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org8278c072015-02-23 11:11:49 +0000306 send_config->rtp.nack.rtp_history_ms =
307 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000308 send_config->encoder_settings.encoder = &fake_encoder_;
309 send_config->encoder_settings.payload_name = "H264";
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100310 send_config->encoder_settings.payload_type = kFakeVideoSendPayloadType;
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +0000311 encoder_config->streams[0].min_bitrate_bps = 50000;
312 encoder_config->streams[0].target_bitrate_bps =
313 encoder_config->streams[0].max_bitrate_bps = 2000000;
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000314
315 (*receive_configs)[0].renderer = this;
pbos@webrtc.org776e6f22014-10-29 15:28:39 +0000316 (*receive_configs)[0].decoders.resize(1);
317 (*receive_configs)[0].decoders[0].payload_type =
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000318 send_config->encoder_settings.payload_type;
pbos@webrtc.org776e6f22014-10-29 15:28:39 +0000319 (*receive_configs)[0].decoders[0].payload_name =
320 send_config->encoder_settings.payload_name;
321 (*receive_configs)[0].decoders[0].decoder = &fake_decoder_;
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000322 }
323
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700324 void RenderFrame(const VideoFrame& video_frame,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000325 int time_to_render_ms) override {
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000326 const int kRequiredFrames = 500;
327 if (++frame_counter_ == kRequiredFrames)
Peter Boström5811a392015-12-10 13:02:50 +0100328 observation_complete_.Set();
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000329 }
330
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000331 bool IsTextureSupported() const override { return false; }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000332
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000333 private:
334 test::FakeH264Decoder fake_decoder_;
335 test::FakeH264Encoder fake_encoder_;
336 int frame_counter_;
337 } test;
338
stefane74eef12016-01-08 06:47:13 -0800339 RunBaseTest(&test);
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000340}
341
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000342TEST_F(EndToEndTest, ReceiverUsesLocalSsrc) {
343 class SyncRtcpObserver : public test::EndToEndTest {
344 public:
345 SyncRtcpObserver() : EndToEndTest(kDefaultTimeoutMs) {}
346
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000347 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000348 RTCPUtility::RTCPParserV2 parser(packet, length, true);
349 EXPECT_TRUE(parser.IsValid());
350 uint32_t ssrc = 0;
351 ssrc |= static_cast<uint32_t>(packet[4]) << 24;
352 ssrc |= static_cast<uint32_t>(packet[5]) << 16;
353 ssrc |= static_cast<uint32_t>(packet[6]) << 8;
354 ssrc |= static_cast<uint32_t>(packet[7]) << 0;
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100355 EXPECT_EQ(kReceiverLocalVideoSsrc, ssrc);
Peter Boström5811a392015-12-10 13:02:50 +0100356 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000357
358 return SEND_PACKET;
359 }
360
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000361 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100362 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000363 << "Timed out while waiting for a receiver RTCP packet to be sent.";
364 }
365 } test;
366
stefane74eef12016-01-08 06:47:13 -0800367 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000368}
369
370TEST_F(EndToEndTest, ReceivesAndRetransmitsNack) {
371 static const int kNumberOfNacksToObserve = 2;
372 static const int kLossBurstSize = 2;
373 static const int kPacketsBetweenLossBursts = 9;
374 class NackObserver : public test::EndToEndTest {
375 public:
376 NackObserver()
377 : EndToEndTest(kLongTimeoutMs),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000378 sent_rtp_packets_(0),
379 packets_left_to_drop_(0),
380 nacks_left_(kNumberOfNacksToObserve) {}
381
382 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000383 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700384 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000385 RTPHeader header;
Peter Boström03671cb2015-12-07 15:22:24 +0100386 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000387
388 // Never drop retransmitted packets.
389 if (dropped_packets_.find(header.sequenceNumber) !=
390 dropped_packets_.end()) {
391 retransmitted_packets_.insert(header.sequenceNumber);
Stefan Holmer586b19b2015-09-18 11:14:31 +0200392 if (nacks_left_ <= 0 &&
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000393 retransmitted_packets_.size() == dropped_packets_.size()) {
Peter Boström5811a392015-12-10 13:02:50 +0100394 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000395 }
396 return SEND_PACKET;
397 }
398
399 ++sent_rtp_packets_;
400
401 // Enough NACKs received, stop dropping packets.
Stefan Holmer586b19b2015-09-18 11:14:31 +0200402 if (nacks_left_ <= 0)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000403 return SEND_PACKET;
404
405 // Check if it's time for a new loss burst.
406 if (sent_rtp_packets_ % kPacketsBetweenLossBursts == 0)
407 packets_left_to_drop_ = kLossBurstSize;
408
Stefan Holmer01b48882015-05-05 10:21:24 +0200409 // Never drop padding packets as those won't be retransmitted.
410 if (packets_left_to_drop_ > 0 && header.paddingLength == 0) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000411 --packets_left_to_drop_;
412 dropped_packets_.insert(header.sequenceNumber);
413 return DROP_PACKET;
414 }
415
416 return SEND_PACKET;
417 }
418
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000419 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700420 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000421 RTCPUtility::RTCPParserV2 parser(packet, length, true);
422 EXPECT_TRUE(parser.IsValid());
423
424 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +0200425 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
426 if (packet_type == RTCPUtility::RTCPPacketTypes::kRtpfbNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000427 --nacks_left_;
428 break;
429 }
430 packet_type = parser.Iterate();
431 }
432 return SEND_PACKET;
433 }
434
stefanff483612015-12-21 03:14:00 -0800435 void ModifyVideoConfigs(
436 VideoSendStream::Config* send_config,
437 std::vector<VideoReceiveStream::Config>* receive_configs,
438 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000439 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000440 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000441 }
442
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000443 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100444 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000445 << "Timed out waiting for packets to be NACKed, retransmitted and "
446 "rendered.";
447 }
448
stefanf116bd02015-10-27 08:29:42 -0700449 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000450 std::set<uint16_t> dropped_packets_;
451 std::set<uint16_t> retransmitted_packets_;
452 uint64_t sent_rtp_packets_;
453 int packets_left_to_drop_;
stefanf116bd02015-10-27 08:29:42 -0700454 int nacks_left_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000455 } test;
456
stefane74eef12016-01-08 06:47:13 -0800457 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000458}
459
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000460TEST_F(EndToEndTest, CanReceiveFec) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000461 class FecRenderObserver : public test::EndToEndTest, public VideoRenderer {
462 public:
463 FecRenderObserver()
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000464 : EndToEndTest(kDefaultTimeoutMs), state_(kFirstPacket) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000465
466 private:
stefanf116bd02015-10-27 08:29:42 -0700467 Action OnSendRtp(const uint8_t* packet, size_t length) override {
468 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000469 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000470 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000471
Stefan Holmer01b48882015-05-05 10:21:24 +0200472 int encapsulated_payload_type = -1;
473 if (header.payloadType == kRedPayloadType) {
474 encapsulated_payload_type =
475 static_cast<int>(packet[header.headerLength]);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100476 if (encapsulated_payload_type != kFakeVideoSendPayloadType)
Stefan Holmer01b48882015-05-05 10:21:24 +0200477 EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
478 } else {
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100479 EXPECT_EQ(kFakeVideoSendPayloadType, header.payloadType);
Stefan Holmer01b48882015-05-05 10:21:24 +0200480 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000481
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000482 if (protected_sequence_numbers_.count(header.sequenceNumber) != 0) {
483 // Retransmitted packet, should not count.
484 protected_sequence_numbers_.erase(header.sequenceNumber);
485 EXPECT_GT(protected_timestamps_.count(header.timestamp), 0u);
486 protected_timestamps_.erase(header.timestamp);
487 return SEND_PACKET;
488 }
489
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000490 switch (state_) {
491 case kFirstPacket:
492 state_ = kDropEveryOtherPacketUntilFec;
493 break;
494 case kDropEveryOtherPacketUntilFec:
495 if (encapsulated_payload_type == kUlpfecPayloadType) {
496 state_ = kDropNextMediaPacket;
497 return SEND_PACKET;
498 }
499 if (header.sequenceNumber % 2 == 0)
500 return DROP_PACKET;
501 break;
502 case kDropNextMediaPacket:
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100503 if (encapsulated_payload_type == kFakeVideoSendPayloadType) {
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000504 protected_sequence_numbers_.insert(header.sequenceNumber);
505 protected_timestamps_.insert(header.timestamp);
506 state_ = kDropEveryOtherPacketUntilFec;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000507 return DROP_PACKET;
508 }
509 break;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000510 }
511
512 return SEND_PACKET;
513 }
514
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700515 void RenderFrame(const VideoFrame& video_frame,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000516 int time_to_render_ms) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200517 rtc::CritScope lock(&crit_);
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000518 // Rendering frame with timestamp of packet that was dropped -> FEC
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000519 // protection worked.
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000520 if (protected_timestamps_.count(video_frame.timestamp()) != 0)
Peter Boström5811a392015-12-10 13:02:50 +0100521 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000522 }
523
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000524 bool IsTextureSupported() const override { return false; }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000525
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000526 enum {
527 kFirstPacket,
528 kDropEveryOtherPacketUntilFec,
529 kDropNextMediaPacket,
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000530 } state_;
531
stefanff483612015-12-21 03:14:00 -0800532 void ModifyVideoConfigs(
533 VideoSendStream::Config* send_config,
534 std::vector<VideoReceiveStream::Config>* receive_configs,
535 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000536 // TODO(pbos): Run this test with combined NACK/FEC enabled as well.
537 // int rtp_history_ms = 1000;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000538 // (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000539 // send_config->rtp.nack.rtp_history_ms = rtp_history_ms;
540 send_config->rtp.fec.red_payload_type = kRedPayloadType;
541 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
542
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000543 (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
544 (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
545 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000546 }
547
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000548 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100549 EXPECT_TRUE(Wait())
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000550 << "Timed out waiting for dropped frames frames to be rendered.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000551 }
552
stefanf116bd02015-10-27 08:29:42 -0700553 rtc::CriticalSection crit_;
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000554 std::set<uint32_t> protected_sequence_numbers_ GUARDED_BY(crit_);
555 std::set<uint32_t> protected_timestamps_ GUARDED_BY(crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000556 } test;
557
stefane74eef12016-01-08 06:47:13 -0800558 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000559}
560
Henrik Kjellanderdb313b62015-04-02 08:45:41 +0200561// Flacky on all platforms. See webrtc:4328.
562TEST_F(EndToEndTest, DISABLED_ReceivedFecPacketsNotNacked) {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000563 class FecNackObserver : public test::EndToEndTest {
564 public:
mflodmand1590b22015-12-09 07:07:59 -0800565 FecNackObserver()
stefanf116bd02015-10-27 08:29:42 -0700566 : EndToEndTest(kDefaultTimeoutMs),
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000567 state_(kFirstPacket),
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000568 fec_sequence_number_(0),
569 has_last_sequence_number_(false),
570 last_sequence_number_(0) {}
571
572 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000573 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -0800574 rtc::CritScope lock_(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000575 RTPHeader header;
576 EXPECT_TRUE(parser_->Parse(packet, length, &header));
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000577
Stefan Holmer01b48882015-05-05 10:21:24 +0200578 int encapsulated_payload_type = -1;
579 if (header.payloadType == kRedPayloadType) {
580 encapsulated_payload_type =
581 static_cast<int>(packet[header.headerLength]);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100582 if (encapsulated_payload_type != kFakeVideoSendPayloadType)
Stefan Holmer01b48882015-05-05 10:21:24 +0200583 EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
584 } else {
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100585 EXPECT_EQ(kFakeVideoSendPayloadType, header.payloadType);
Stefan Holmer01b48882015-05-05 10:21:24 +0200586 }
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000587
588 if (has_last_sequence_number_ &&
589 !IsNewerSequenceNumber(header.sequenceNumber,
590 last_sequence_number_)) {
591 // Drop retransmitted packets.
592 return DROP_PACKET;
593 }
594 last_sequence_number_ = header.sequenceNumber;
595 has_last_sequence_number_ = true;
596
597 bool fec_packet = encapsulated_payload_type == kUlpfecPayloadType;
598 switch (state_) {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000599 case kFirstPacket:
600 state_ = kDropEveryOtherPacketUntilFec;
601 break;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000602 case kDropEveryOtherPacketUntilFec:
603 if (fec_packet) {
604 state_ = kDropAllMediaPacketsUntilFec;
605 } else if (header.sequenceNumber % 2 == 0) {
606 return DROP_PACKET;
607 }
608 break;
609 case kDropAllMediaPacketsUntilFec:
610 if (!fec_packet)
611 return DROP_PACKET;
612 fec_sequence_number_ = header.sequenceNumber;
613 state_ = kVerifyFecPacketNotInNackList;
614 break;
615 case kVerifyFecPacketNotInNackList:
616 // Continue to drop packets. Make sure no frame can be decoded.
617 if (fec_packet || header.sequenceNumber % 2 == 0)
618 return DROP_PACKET;
619 break;
620 }
621 return SEND_PACKET;
622 }
623
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000624 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -0800625 rtc::CritScope lock_(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000626 if (state_ == kVerifyFecPacketNotInNackList) {
627 test::RtcpPacketParser rtcp_parser;
628 rtcp_parser.Parse(packet, length);
629 std::vector<uint16_t> nacks = rtcp_parser.nack_item()->last_nack_list();
630 if (!nacks.empty() &&
631 IsNewerSequenceNumber(nacks.back(), fec_sequence_number_)) {
632 EXPECT_TRUE(std::find(
633 nacks.begin(), nacks.end(), fec_sequence_number_) == nacks.end());
Peter Boström5811a392015-12-10 13:02:50 +0100634 observation_complete_.Set();
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000635 }
636 }
637 return SEND_PACKET;
638 }
639
stefane74eef12016-01-08 06:47:13 -0800640 test::PacketTransport* CreateSendTransport(Call* sender_call) override {
641 // At low RTT (< kLowRttNackMs) -> NACK only, no FEC.
642 // Configure some network delay.
643 const int kNetworkDelayMs = 50;
644 FakeNetworkPipe::Config config;
645 config.queue_delay_ms = kNetworkDelayMs;
646 return new test::PacketTransport(sender_call, this,
647 test::PacketTransport::kSender, config);
648 }
649
Stefan Holmere5904162015-03-26 11:11:06 +0100650 // TODO(holmer): Investigate why we don't send FEC packets when the bitrate
651 // is 10 kbps.
652 Call::Config GetSenderCallConfig() override {
solenberg4fbae2b2015-08-28 04:07:10 -0700653 Call::Config config;
Stefan Holmere5904162015-03-26 11:11:06 +0100654 const int kMinBitrateBps = 30000;
655 config.bitrate_config.min_bitrate_bps = kMinBitrateBps;
656 return config;
657 }
658
stefanff483612015-12-21 03:14:00 -0800659 void ModifyVideoConfigs(
660 VideoSendStream::Config* send_config,
661 std::vector<VideoReceiveStream::Config>* receive_configs,
662 VideoEncoderConfig* encoder_config) override {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000663 // Configure hybrid NACK/FEC.
664 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
665 send_config->rtp.fec.red_payload_type = kRedPayloadType;
666 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
667 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
668 (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
669 (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
670 }
671
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000672 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100673 EXPECT_TRUE(Wait())
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000674 << "Timed out while waiting for FEC packets to be received.";
675 }
676
677 enum {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000678 kFirstPacket,
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000679 kDropEveryOtherPacketUntilFec,
680 kDropAllMediaPacketsUntilFec,
681 kVerifyFecPacketNotInNackList,
682 } state_;
683
stefan608213e2015-11-01 14:56:10 -0800684 rtc::CriticalSection crit_;
685 uint16_t fec_sequence_number_ GUARDED_BY(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000686 bool has_last_sequence_number_;
687 uint16_t last_sequence_number_;
stefanf116bd02015-10-27 08:29:42 -0700688 } test;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000689
stefane74eef12016-01-08 06:47:13 -0800690 RunBaseTest(&test);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000691}
692
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000693// This test drops second RTP packet with a marker bit set, makes sure it's
694// retransmitted and renders. Retransmission SSRCs are also checked.
Shao Changbine62202f2015-04-21 20:24:50 +0800695void EndToEndTest::DecodesRetransmittedFrame(bool use_rtx, bool use_red) {
Stefan Holmer586b19b2015-09-18 11:14:31 +0200696 // Must be set high enough to allow the bitrate probing to finish.
697 static const int kMinProbePackets = 30;
698 static const int kDroppedFrameNumber = kMinProbePackets + 1;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000699 class RetransmissionObserver : public test::EndToEndTest,
700 public I420FrameCallback {
701 public:
Shao Changbine62202f2015-04-21 20:24:50 +0800702 explicit RetransmissionObserver(bool use_rtx, bool use_red)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000703 : EndToEndTest(kDefaultTimeoutMs),
Shao Changbine62202f2015-04-21 20:24:50 +0800704 payload_type_(GetPayloadType(false, use_red)),
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100705 retransmission_ssrc_(use_rtx ? kSendRtxSsrcs[0] : kVideoSendSsrcs[0]),
Shao Changbine62202f2015-04-21 20:24:50 +0800706 retransmission_payload_type_(GetPayloadType(use_rtx, use_red)),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000707 marker_bits_observed_(0),
Stefan Holmer586b19b2015-09-18 11:14:31 +0200708 num_packets_observed_(0),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000709 retransmitted_timestamp_(0),
710 frame_retransmitted_(false) {}
711
712 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000713 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700714 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000715 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000716 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000717
Stefan Holmer586b19b2015-09-18 11:14:31 +0200718 // We accept some padding or RTX packets in the beginning to enable
719 // bitrate probing.
720 if (num_packets_observed_++ < kMinProbePackets &&
721 header.payloadType != payload_type_) {
722 EXPECT_TRUE(retransmission_payload_type_ == header.payloadType ||
723 length == header.headerLength + header.paddingLength);
724 return SEND_PACKET;
725 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000726 if (header.timestamp == retransmitted_timestamp_) {
727 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
728 EXPECT_EQ(retransmission_payload_type_, header.payloadType);
729 frame_retransmitted_ = true;
730 return SEND_PACKET;
731 }
732
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100733 EXPECT_EQ(kVideoSendSsrcs[0], header.ssrc);
Shao Changbine62202f2015-04-21 20:24:50 +0800734 EXPECT_EQ(payload_type_, header.payloadType);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000735
Stefan Holmer586b19b2015-09-18 11:14:31 +0200736 // Found the final packet of the frame to inflict loss to, drop this and
737 // expect a retransmission.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000738 if (header.markerBit && ++marker_bits_observed_ == kDroppedFrameNumber) {
739 retransmitted_timestamp_ = header.timestamp;
740 return DROP_PACKET;
741 }
742
743 return SEND_PACKET;
744 }
745
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700746 void FrameCallback(VideoFrame* frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200747 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000748 if (frame->timestamp() == retransmitted_timestamp_) {
749 EXPECT_TRUE(frame_retransmitted_);
Peter Boström5811a392015-12-10 13:02:50 +0100750 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000751 }
752 }
753
stefanff483612015-12-21 03:14:00 -0800754 void ModifyVideoConfigs(
755 VideoSendStream::Config* send_config,
756 std::vector<VideoReceiveStream::Config>* receive_configs,
757 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000758 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000759 (*receive_configs)[0].pre_render_callback = this;
760 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
Shao Changbine62202f2015-04-21 20:24:50 +0800761
762 if (payload_type_ == kRedPayloadType) {
763 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
764 send_config->rtp.fec.red_payload_type = kRedPayloadType;
765 (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
766 (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
767 }
768
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000769 if (retransmission_ssrc_ == kSendRtxSsrcs[0]) {
770 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000771 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100772 (*receive_configs)[0].rtp.rtx[kFakeVideoSendPayloadType].ssrc =
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000773 kSendRtxSsrcs[0];
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100774 (*receive_configs)[0].rtp.rtx[kFakeVideoSendPayloadType].payload_type =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000775 kSendRtxPayloadType;
776 }
777 }
778
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000779 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100780 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000781 << "Timed out while waiting for retransmission to render.";
782 }
783
Shao Changbine62202f2015-04-21 20:24:50 +0800784 int GetPayloadType(bool use_rtx, bool use_red) {
785 return use_rtx ? kSendRtxPayloadType
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100786 : (use_red ? kRedPayloadType : kFakeVideoSendPayloadType);
Shao Changbine62202f2015-04-21 20:24:50 +0800787 }
788
stefanf116bd02015-10-27 08:29:42 -0700789 rtc::CriticalSection crit_;
Shao Changbine62202f2015-04-21 20:24:50 +0800790 const int payload_type_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000791 const uint32_t retransmission_ssrc_;
792 const int retransmission_payload_type_;
793 int marker_bits_observed_;
Stefan Holmer586b19b2015-09-18 11:14:31 +0200794 int num_packets_observed_;
stefanf116bd02015-10-27 08:29:42 -0700795 uint32_t retransmitted_timestamp_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000796 bool frame_retransmitted_;
Shao Changbine62202f2015-04-21 20:24:50 +0800797 } test(use_rtx, use_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000798
stefane74eef12016-01-08 06:47:13 -0800799 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000800}
801
802TEST_F(EndToEndTest, DecodesRetransmittedFrame) {
Shao Changbine62202f2015-04-21 20:24:50 +0800803 DecodesRetransmittedFrame(false, false);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000804}
805
806TEST_F(EndToEndTest, DecodesRetransmittedFrameOverRtx) {
Shao Changbine62202f2015-04-21 20:24:50 +0800807 DecodesRetransmittedFrame(true, false);
808}
809
810TEST_F(EndToEndTest, DecodesRetransmittedFrameByRed) {
811 DecodesRetransmittedFrame(false, true);
812}
813
814TEST_F(EndToEndTest, DecodesRetransmittedFrameByRedOverRtx) {
815 DecodesRetransmittedFrame(true, true);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000816}
817
andresp@webrtc.org02686112014-09-19 08:24:19 +0000818TEST_F(EndToEndTest, UsesFrameCallbacks) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000819 static const int kWidth = 320;
820 static const int kHeight = 240;
821
822 class Renderer : public VideoRenderer {
823 public:
Peter Boström5811a392015-12-10 13:02:50 +0100824 Renderer() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000825
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700826 void RenderFrame(const VideoFrame& video_frame,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000827 int /*time_to_render_ms*/) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000828 EXPECT_EQ(0, *video_frame.buffer(kYPlane))
829 << "Rendered frame should have zero luma which is applied by the "
830 "pre-render callback.";
Peter Boström5811a392015-12-10 13:02:50 +0100831 event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000832 }
833
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000834 bool IsTextureSupported() const override { return false; }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000835
Peter Boström5811a392015-12-10 13:02:50 +0100836 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
837 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000838 } renderer;
839
840 class TestFrameCallback : public I420FrameCallback {
841 public:
842 TestFrameCallback(int expected_luma_byte, int next_luma_byte)
Peter Boström5811a392015-12-10 13:02:50 +0100843 : event_(false, false),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000844 expected_luma_byte_(expected_luma_byte),
845 next_luma_byte_(next_luma_byte) {}
846
Peter Boström5811a392015-12-10 13:02:50 +0100847 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000848
849 private:
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700850 virtual void FrameCallback(VideoFrame* frame) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000851 EXPECT_EQ(kWidth, frame->width())
852 << "Width not as expected, callback done before resize?";
853 EXPECT_EQ(kHeight, frame->height())
854 << "Height not as expected, callback done before resize?";
855
856 // Previous luma specified, observed luma should be fairly close.
857 if (expected_luma_byte_ != -1) {
858 EXPECT_NEAR(expected_luma_byte_, *frame->buffer(kYPlane), 10);
859 }
860
861 memset(frame->buffer(kYPlane),
862 next_luma_byte_,
863 frame->allocated_size(kYPlane));
864
Peter Boström5811a392015-12-10 13:02:50 +0100865 event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000866 }
867
Peter Boström5811a392015-12-10 13:02:50 +0100868 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000869 int expected_luma_byte_;
870 int next_luma_byte_;
871 };
872
873 TestFrameCallback pre_encode_callback(-1, 255); // Changes luma to 255.
874 TestFrameCallback pre_render_callback(255, 0); // Changes luma from 255 to 0.
875
solenberg4fbae2b2015-08-28 04:07:10 -0700876 CreateCalls(Call::Config(), Call::Config());
877
stefanf116bd02015-10-27 08:29:42 -0700878 test::DirectTransport sender_transport(sender_call_.get());
879 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000880 sender_transport.SetReceiver(receiver_call_->Receiver());
881 receiver_transport.SetReceiver(sender_call_->Receiver());
882
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100883 CreateSendConfig(1, 0, &sender_transport);
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000884 rtc::scoped_ptr<VideoEncoder> encoder(
pbos@webrtc.orgab990ae2014-09-17 09:02:25 +0000885 VideoEncoder::Create(VideoEncoder::kVp8));
stefanff483612015-12-21 03:14:00 -0800886 video_send_config_.encoder_settings.encoder = encoder.get();
887 video_send_config_.encoder_settings.payload_name = "VP8";
888 ASSERT_EQ(1u, video_encoder_config_.streams.size()) << "Test setup error.";
889 video_encoder_config_.streams[0].width = kWidth;
890 video_encoder_config_.streams[0].height = kHeight;
891 video_send_config_.pre_encode_callback = &pre_encode_callback;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000892
solenberg4fbae2b2015-08-28 04:07:10 -0700893 CreateMatchingReceiveConfigs(&receiver_transport);
stefanff483612015-12-21 03:14:00 -0800894 video_receive_configs_[0].pre_render_callback = &pre_render_callback;
895 video_receive_configs_[0].renderer = &renderer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000896
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100897 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000898 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000899
900 // Create frames that are smaller than the send width/height, this is done to
901 // check that the callbacks are done after processing video.
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000902 rtc::scoped_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +0000903 test::FrameGenerator::CreateChromaGenerator(kWidth / 2, kHeight / 2));
stefanff483612015-12-21 03:14:00 -0800904 video_send_stream_->Input()->IncomingCapturedFrame(
905 *frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000906
Peter Boström5811a392015-12-10 13:02:50 +0100907 EXPECT_TRUE(pre_encode_callback.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000908 << "Timed out while waiting for pre-encode callback.";
Peter Boström5811a392015-12-10 13:02:50 +0100909 EXPECT_TRUE(pre_render_callback.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000910 << "Timed out while waiting for pre-render callback.";
Peter Boström5811a392015-12-10 13:02:50 +0100911 EXPECT_TRUE(renderer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000912 << "Timed out while waiting for the frame to render.";
913
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000914 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000915
916 sender_transport.StopSending();
917 receiver_transport.StopSending();
918
919 DestroyStreams();
920}
921
922void EndToEndTest::ReceivesPliAndRecovers(int rtp_history_ms) {
923 static const int kPacketsToDrop = 1;
924
925 class PliObserver : public test::EndToEndTest, public VideoRenderer {
926 public:
927 explicit PliObserver(int rtp_history_ms)
928 : EndToEndTest(kLongTimeoutMs),
929 rtp_history_ms_(rtp_history_ms),
930 nack_enabled_(rtp_history_ms > 0),
931 highest_dropped_timestamp_(0),
932 frames_to_drop_(0),
933 received_pli_(false) {}
934
935 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000936 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700937 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000938 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000939 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000940
941 // Drop all retransmitted packets to force a PLI.
942 if (header.timestamp <= highest_dropped_timestamp_)
943 return DROP_PACKET;
944
945 if (frames_to_drop_ > 0) {
946 highest_dropped_timestamp_ = header.timestamp;
947 --frames_to_drop_;
948 return DROP_PACKET;
949 }
950
951 return SEND_PACKET;
952 }
953
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000954 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700955 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000956 RTCPUtility::RTCPParserV2 parser(packet, length, true);
957 EXPECT_TRUE(parser.IsValid());
958
959 for (RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +0200960 packet_type != RTCPUtility::RTCPPacketTypes::kInvalid;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000961 packet_type = parser.Iterate()) {
962 if (!nack_enabled_)
Erik Språng242e22b2015-05-11 10:17:43 +0200963 EXPECT_NE(packet_type, RTCPUtility::RTCPPacketTypes::kRtpfbNack);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000964
Erik Språng242e22b2015-05-11 10:17:43 +0200965 if (packet_type == RTCPUtility::RTCPPacketTypes::kPsfbPli) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000966 received_pli_ = true;
967 break;
968 }
969 }
970 return SEND_PACKET;
971 }
972
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700973 void RenderFrame(const VideoFrame& video_frame,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000974 int time_to_render_ms) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200975 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000976 if (received_pli_ &&
977 video_frame.timestamp() > highest_dropped_timestamp_) {
Peter Boström5811a392015-12-10 13:02:50 +0100978 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000979 }
980 if (!received_pli_)
981 frames_to_drop_ = kPacketsToDrop;
982 }
983
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000984 bool IsTextureSupported() const override { return false; }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000985
stefanff483612015-12-21 03:14:00 -0800986 void ModifyVideoConfigs(
987 VideoSendStream::Config* send_config,
988 std::vector<VideoReceiveStream::Config>* receive_configs,
989 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000990 send_config->rtp.nack.rtp_history_ms = rtp_history_ms_;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000991 (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms_;
992 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000993 }
994
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000995 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100996 EXPECT_TRUE(Wait()) << "Timed out waiting for PLI to be "
997 "received and a frame to be "
998 "rendered afterwards.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000999 }
1000
stefanf116bd02015-10-27 08:29:42 -07001001 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001002 int rtp_history_ms_;
1003 bool nack_enabled_;
stefanf116bd02015-10-27 08:29:42 -07001004 uint32_t highest_dropped_timestamp_ GUARDED_BY(&crit_);
1005 int frames_to_drop_ GUARDED_BY(&crit_);
1006 bool received_pli_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001007 } test(rtp_history_ms);
1008
stefane74eef12016-01-08 06:47:13 -08001009 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001010}
1011
1012TEST_F(EndToEndTest, ReceivesPliAndRecoversWithNack) {
1013 ReceivesPliAndRecovers(1000);
1014}
1015
jbauchdb81ffd2015-11-23 03:59:02 -08001016TEST_F(EndToEndTest, ReceivesPliAndRecoversWithoutNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001017 ReceivesPliAndRecovers(0);
1018}
1019
1020TEST_F(EndToEndTest, UnknownRtpPacketGivesUnknownSsrcReturnCode) {
1021 class PacketInputObserver : public PacketReceiver {
1022 public:
1023 explicit PacketInputObserver(PacketReceiver* receiver)
Peter Boström5811a392015-12-10 13:02:50 +01001024 : receiver_(receiver), delivered_packet_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001025
Peter Boström5811a392015-12-10 13:02:50 +01001026 bool Wait() { return delivered_packet_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001027
1028 private:
stefan68786d22015-09-08 05:36:15 -07001029 DeliveryStatus DeliverPacket(MediaType media_type,
1030 const uint8_t* packet,
1031 size_t length,
1032 const PacketTime& packet_time) override {
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001033 if (RtpHeaderParser::IsRtcp(packet, length)) {
stefan68786d22015-09-08 05:36:15 -07001034 return receiver_->DeliverPacket(media_type, packet, length,
1035 packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001036 } else {
1037 DeliveryStatus delivery_status =
stefan68786d22015-09-08 05:36:15 -07001038 receiver_->DeliverPacket(media_type, packet, length, packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001039 EXPECT_EQ(DELIVERY_UNKNOWN_SSRC, delivery_status);
Peter Boström5811a392015-12-10 13:02:50 +01001040 delivered_packet_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001041 return delivery_status;
1042 }
1043 }
1044
1045 PacketReceiver* receiver_;
Peter Boström5811a392015-12-10 13:02:50 +01001046 rtc::Event delivered_packet_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001047 };
1048
solenberg4fbae2b2015-08-28 04:07:10 -07001049 CreateCalls(Call::Config(), Call::Config());
1050
stefanf116bd02015-10-27 08:29:42 -07001051 test::DirectTransport send_transport(sender_call_.get());
1052 test::DirectTransport receive_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001053 PacketInputObserver input_observer(receiver_call_->Receiver());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001054 send_transport.SetReceiver(&input_observer);
1055 receive_transport.SetReceiver(sender_call_->Receiver());
1056
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001057 CreateSendConfig(1, 0, &send_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07001058 CreateMatchingReceiveConfigs(&receive_transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001059
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001060 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001061 CreateFrameGeneratorCapturer();
1062 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001063
stefanff483612015-12-21 03:14:00 -08001064 receiver_call_->DestroyVideoReceiveStream(video_receive_streams_[0]);
1065 video_receive_streams_.clear();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001066
1067 // Wait() waits for a received packet.
Peter Boström5811a392015-12-10 13:02:50 +01001068 EXPECT_TRUE(input_observer.Wait());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001069
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001070 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001071
1072 DestroyStreams();
1073
1074 send_transport.StopSending();
1075 receive_transport.StopSending();
1076}
1077
pbosda903ea2015-10-02 02:36:56 -07001078void EndToEndTest::RespectsRtcpMode(RtcpMode rtcp_mode) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001079 static const int kNumCompoundRtcpPacketsToObserve = 10;
1080 class RtcpModeObserver : public test::EndToEndTest {
1081 public:
pbosda903ea2015-10-02 02:36:56 -07001082 explicit RtcpModeObserver(RtcpMode rtcp_mode)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001083 : EndToEndTest(kDefaultTimeoutMs),
1084 rtcp_mode_(rtcp_mode),
1085 sent_rtp_(0),
1086 sent_rtcp_(0) {}
1087
1088 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001089 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001090 if (++sent_rtp_ % 3 == 0)
1091 return DROP_PACKET;
1092
1093 return SEND_PACKET;
1094 }
1095
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001096 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001097 ++sent_rtcp_;
1098 RTCPUtility::RTCPParserV2 parser(packet, length, true);
1099 EXPECT_TRUE(parser.IsValid());
1100
1101 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
1102 bool has_report_block = false;
Erik Språng242e22b2015-05-11 10:17:43 +02001103 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
1104 EXPECT_NE(RTCPUtility::RTCPPacketTypes::kSr, packet_type);
1105 if (packet_type == RTCPUtility::RTCPPacketTypes::kRr) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001106 has_report_block = true;
1107 break;
1108 }
1109 packet_type = parser.Iterate();
1110 }
1111
1112 switch (rtcp_mode_) {
pbosda903ea2015-10-02 02:36:56 -07001113 case RtcpMode::kCompound:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001114 if (!has_report_block) {
1115 ADD_FAILURE() << "Received RTCP packet without receiver report for "
pbosda903ea2015-10-02 02:36:56 -07001116 "RtcpMode::kCompound.";
Peter Boström5811a392015-12-10 13:02:50 +01001117 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001118 }
1119
1120 if (sent_rtcp_ >= kNumCompoundRtcpPacketsToObserve)
Peter Boström5811a392015-12-10 13:02:50 +01001121 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001122
1123 break;
pbosda903ea2015-10-02 02:36:56 -07001124 case RtcpMode::kReducedSize:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001125 if (!has_report_block)
Peter Boström5811a392015-12-10 13:02:50 +01001126 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001127 break;
pbosda903ea2015-10-02 02:36:56 -07001128 case RtcpMode::kOff:
1129 RTC_NOTREACHED();
1130 break;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001131 }
1132
1133 return SEND_PACKET;
1134 }
1135
stefanff483612015-12-21 03:14:00 -08001136 void ModifyVideoConfigs(
1137 VideoSendStream::Config* send_config,
1138 std::vector<VideoReceiveStream::Config>* receive_configs,
1139 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001140 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001141 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
1142 (*receive_configs)[0].rtp.rtcp_mode = rtcp_mode_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001143 }
1144
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001145 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001146 EXPECT_TRUE(Wait())
pbosda903ea2015-10-02 02:36:56 -07001147 << (rtcp_mode_ == RtcpMode::kCompound
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001148 ? "Timed out before observing enough compound packets."
1149 : "Timed out before receiving a non-compound RTCP packet.");
1150 }
1151
pbosda903ea2015-10-02 02:36:56 -07001152 RtcpMode rtcp_mode_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001153 int sent_rtp_;
1154 int sent_rtcp_;
1155 } test(rtcp_mode);
1156
stefane74eef12016-01-08 06:47:13 -08001157 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001158}
1159
1160TEST_F(EndToEndTest, UsesRtcpCompoundMode) {
pbosda903ea2015-10-02 02:36:56 -07001161 RespectsRtcpMode(RtcpMode::kCompound);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001162}
1163
1164TEST_F(EndToEndTest, UsesRtcpReducedSizeMode) {
pbosda903ea2015-10-02 02:36:56 -07001165 RespectsRtcpMode(RtcpMode::kReducedSize);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001166}
1167
1168// Test sets up a Call multiple senders with different resolutions and SSRCs.
1169// Another is set up to receive all three of these with different renderers.
sprang867fb522015-08-03 04:38:41 -07001170class MultiStreamTest {
1171 public:
1172 static const size_t kNumStreams = 3;
1173 struct CodecSettings {
1174 uint32_t ssrc;
1175 int width;
1176 int height;
1177 } codec_settings[kNumStreams];
1178
1179 MultiStreamTest() {
1180 // TODO(sprang): Cleanup when msvc supports explicit initializers for array.
1181 codec_settings[0] = {1, 640, 480};
1182 codec_settings[1] = {2, 320, 240};
1183 codec_settings[2] = {3, 240, 160};
1184 }
1185
1186 virtual ~MultiStreamTest() {}
1187
1188 void RunTest() {
solenberg4fbae2b2015-08-28 04:07:10 -07001189 rtc::scoped_ptr<Call> sender_call(Call::Create(Call::Config()));
1190 rtc::scoped_ptr<Call> receiver_call(Call::Create(Call::Config()));
stefanf116bd02015-10-27 08:29:42 -07001191 rtc::scoped_ptr<test::DirectTransport> sender_transport(
1192 CreateSendTransport(sender_call.get()));
1193 rtc::scoped_ptr<test::DirectTransport> receiver_transport(
1194 CreateReceiveTransport(receiver_call.get()));
sprang867fb522015-08-03 04:38:41 -07001195 sender_transport->SetReceiver(receiver_call->Receiver());
1196 receiver_transport->SetReceiver(sender_call->Receiver());
1197
1198 rtc::scoped_ptr<VideoEncoder> encoders[kNumStreams];
1199 for (size_t i = 0; i < kNumStreams; ++i)
1200 encoders[i].reset(VideoEncoder::Create(VideoEncoder::kVp8));
1201
1202 VideoSendStream* send_streams[kNumStreams];
1203 VideoReceiveStream* receive_streams[kNumStreams];
1204
1205 test::FrameGeneratorCapturer* frame_generators[kNumStreams];
1206 ScopedVector<VideoDecoder> allocated_decoders;
1207 for (size_t i = 0; i < kNumStreams; ++i) {
1208 uint32_t ssrc = codec_settings[i].ssrc;
1209 int width = codec_settings[i].width;
1210 int height = codec_settings[i].height;
1211
solenberg4fbae2b2015-08-28 04:07:10 -07001212 VideoSendStream::Config send_config(sender_transport.get());
sprang867fb522015-08-03 04:38:41 -07001213 send_config.rtp.ssrcs.push_back(ssrc);
1214 send_config.encoder_settings.encoder = encoders[i].get();
1215 send_config.encoder_settings.payload_name = "VP8";
1216 send_config.encoder_settings.payload_type = 124;
1217 VideoEncoderConfig encoder_config;
1218 encoder_config.streams = test::CreateVideoStreams(1);
1219 VideoStream* stream = &encoder_config.streams[0];
1220 stream->width = width;
1221 stream->height = height;
1222 stream->max_framerate = 5;
1223 stream->min_bitrate_bps = stream->target_bitrate_bps =
1224 stream->max_bitrate_bps = 100000;
1225
1226 UpdateSendConfig(i, &send_config, &encoder_config, &frame_generators[i]);
1227
1228 send_streams[i] =
1229 sender_call->CreateVideoSendStream(send_config, encoder_config);
1230 send_streams[i]->Start();
1231
solenberg4fbae2b2015-08-28 04:07:10 -07001232 VideoReceiveStream::Config receive_config(receiver_transport.get());
sprang867fb522015-08-03 04:38:41 -07001233 receive_config.rtp.remote_ssrc = ssrc;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001234 receive_config.rtp.local_ssrc = test::CallTest::kReceiverLocalVideoSsrc;
sprang867fb522015-08-03 04:38:41 -07001235 VideoReceiveStream::Decoder decoder =
1236 test::CreateMatchingDecoder(send_config.encoder_settings);
1237 allocated_decoders.push_back(decoder.decoder);
1238 receive_config.decoders.push_back(decoder);
1239
1240 UpdateReceiveConfig(i, &receive_config);
1241
1242 receive_streams[i] =
1243 receiver_call->CreateVideoReceiveStream(receive_config);
1244 receive_streams[i]->Start();
1245
1246 frame_generators[i] = test::FrameGeneratorCapturer::Create(
1247 send_streams[i]->Input(), width, height, 30,
1248 Clock::GetRealTimeClock());
1249 frame_generators[i]->Start();
1250 }
1251
1252 Wait();
1253
1254 for (size_t i = 0; i < kNumStreams; ++i) {
1255 frame_generators[i]->Stop();
1256 sender_call->DestroyVideoSendStream(send_streams[i]);
1257 receiver_call->DestroyVideoReceiveStream(receive_streams[i]);
1258 delete frame_generators[i];
1259 }
1260
1261 sender_transport->StopSending();
1262 receiver_transport->StopSending();
1263 }
1264
1265 protected:
1266 virtual void Wait() = 0;
1267 // Note: frame_generator is a point-to-pointer, since the actual instance
1268 // hasn't been created at the time of this call. Only when packets/frames
1269 // start flowing should this be dereferenced.
1270 virtual void UpdateSendConfig(
1271 size_t stream_index,
1272 VideoSendStream::Config* send_config,
1273 VideoEncoderConfig* encoder_config,
1274 test::FrameGeneratorCapturer** frame_generator) {}
1275 virtual void UpdateReceiveConfig(size_t stream_index,
1276 VideoReceiveStream::Config* receive_config) {
1277 }
stefanf116bd02015-10-27 08:29:42 -07001278 virtual test::DirectTransport* CreateSendTransport(Call* sender_call) {
1279 return new test::DirectTransport(sender_call);
sprang867fb522015-08-03 04:38:41 -07001280 }
stefanf116bd02015-10-27 08:29:42 -07001281 virtual test::DirectTransport* CreateReceiveTransport(Call* receiver_call) {
1282 return new test::DirectTransport(receiver_call);
sprang867fb522015-08-03 04:38:41 -07001283 }
1284};
1285
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001286// Each renderer verifies that it receives the expected resolution, and as soon
1287// as every renderer has received a frame, the test finishes.
andresp@webrtc.org02686112014-09-19 08:24:19 +00001288TEST_F(EndToEndTest, SendsAndReceivesMultipleStreams) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001289 class VideoOutputObserver : public VideoRenderer {
1290 public:
sprang867fb522015-08-03 04:38:41 -07001291 VideoOutputObserver(const MultiStreamTest::CodecSettings& settings,
1292 uint32_t ssrc,
1293 test::FrameGeneratorCapturer** frame_generator)
1294 : settings_(settings),
1295 ssrc_(ssrc),
1296 frame_generator_(frame_generator),
Peter Boström5811a392015-12-10 13:02:50 +01001297 done_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001298
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001299 void RenderFrame(const VideoFrame& video_frame,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001300 int time_to_render_ms) override {
sprang867fb522015-08-03 04:38:41 -07001301 EXPECT_EQ(settings_.width, video_frame.width());
1302 EXPECT_EQ(settings_.height, video_frame.height());
1303 (*frame_generator_)->Stop();
Peter Boström5811a392015-12-10 13:02:50 +01001304 done_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001305 }
1306
sprang867fb522015-08-03 04:38:41 -07001307 uint32_t Ssrc() { return ssrc_; }
1308
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001309 bool IsTextureSupported() const override { return false; }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00001310
Peter Boström5811a392015-12-10 13:02:50 +01001311 bool Wait() { return done_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001312
1313 private:
sprang867fb522015-08-03 04:38:41 -07001314 const MultiStreamTest::CodecSettings& settings_;
1315 const uint32_t ssrc_;
1316 test::FrameGeneratorCapturer** const frame_generator_;
Peter Boström5811a392015-12-10 13:02:50 +01001317 rtc::Event done_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001318 };
1319
sprang867fb522015-08-03 04:38:41 -07001320 class Tester : public MultiStreamTest {
1321 public:
1322 Tester() {}
1323 virtual ~Tester() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001324
sprang867fb522015-08-03 04:38:41 -07001325 protected:
1326 void Wait() override {
1327 for (const auto& observer : observers_) {
Peter Boström5811a392015-12-10 13:02:50 +01001328 EXPECT_TRUE(observer->Wait()) << "Time out waiting for from on ssrc "
1329 << observer->Ssrc();
sprang867fb522015-08-03 04:38:41 -07001330 }
1331 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001332
sprang867fb522015-08-03 04:38:41 -07001333 void UpdateSendConfig(
1334 size_t stream_index,
1335 VideoSendStream::Config* send_config,
1336 VideoEncoderConfig* encoder_config,
1337 test::FrameGeneratorCapturer** frame_generator) override {
1338 observers_[stream_index].reset(new VideoOutputObserver(
1339 codec_settings[stream_index], send_config->rtp.ssrcs.front(),
1340 frame_generator));
1341 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001342
sprang867fb522015-08-03 04:38:41 -07001343 void UpdateReceiveConfig(
1344 size_t stream_index,
1345 VideoReceiveStream::Config* receive_config) override {
1346 receive_config->renderer = observers_[stream_index].get();
1347 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001348
sprang867fb522015-08-03 04:38:41 -07001349 private:
1350 rtc::scoped_ptr<VideoOutputObserver> observers_[kNumStreams];
1351 } tester;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001352
sprang867fb522015-08-03 04:38:41 -07001353 tester.RunTest();
1354}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001355
sprang867fb522015-08-03 04:38:41 -07001356TEST_F(EndToEndTest, AssignsTransportSequenceNumbers) {
sprang867fb522015-08-03 04:38:41 -07001357 static const int kExtensionId = 5;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001358
sprang867fb522015-08-03 04:38:41 -07001359 class RtpExtensionHeaderObserver : public test::DirectTransport {
1360 public:
stefanf116bd02015-10-27 08:29:42 -07001361 RtpExtensionHeaderObserver(Call* sender_call,
1362 const uint32_t& first_media_ssrc,
sprang861c55e2015-10-16 10:01:21 -07001363 const std::map<uint32_t, uint32_t>& ssrc_map)
stefanf116bd02015-10-27 08:29:42 -07001364 : DirectTransport(sender_call),
Peter Boström5811a392015-12-10 13:02:50 +01001365 done_(false, false),
sprang867fb522015-08-03 04:38:41 -07001366 parser_(RtpHeaderParser::Create()),
sprang861c55e2015-10-16 10:01:21 -07001367 first_media_ssrc_(first_media_ssrc),
1368 rtx_to_media_ssrcs_(ssrc_map),
sprang867fb522015-08-03 04:38:41 -07001369 padding_observed_(false),
sprang861c55e2015-10-16 10:01:21 -07001370 rtx_padding_observed_(false),
1371 retransmit_observed_(false),
1372 started_(false) {
sprang867fb522015-08-03 04:38:41 -07001373 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
1374 kExtensionId);
1375 }
1376 virtual ~RtpExtensionHeaderObserver() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001377
stefan1d8a5062015-10-02 03:39:33 -07001378 bool SendRtp(const uint8_t* data,
1379 size_t length,
1380 const PacketOptions& options) override {
sprang861c55e2015-10-16 10:01:21 -07001381 {
1382 rtc::CritScope cs(&lock_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001383
Erik Språng8d629712015-08-04 16:24:03 +02001384 if (IsDone())
sprang861c55e2015-10-16 10:01:21 -07001385 return false;
1386
1387 if (started_) {
1388 RTPHeader header;
1389 EXPECT_TRUE(parser_->Parse(data, length, &header));
1390 bool drop_packet = false;
1391
1392 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
1393 EXPECT_EQ(options.packet_id,
1394 header.extension.transportSequenceNumber);
1395 if (!streams_observed_.empty()) {
1396 // Unwrap packet id and verify uniqueness.
1397 int64_t packet_id = unwrapper_.Unwrap(options.packet_id);
1398 EXPECT_TRUE(received_packed_ids_.insert(packet_id).second);
1399 }
1400
1401 // Drop (up to) every 17th packet, so we get retransmits.
1402 // Only drop media, and not on the first stream (otherwise it will be
1403 // hard to distinguish from padding, which is always sent on the first
1404 // stream).
1405 if (header.payloadType != kSendRtxPayloadType &&
1406 header.ssrc != first_media_ssrc_ &&
1407 header.extension.transportSequenceNumber % 17 == 0) {
1408 dropped_seq_[header.ssrc].insert(header.sequenceNumber);
1409 drop_packet = true;
1410 }
1411
1412 size_t payload_length =
1413 length - (header.headerLength + header.paddingLength);
1414 if (payload_length == 0) {
1415 padding_observed_ = true;
1416 } else if (header.payloadType == kSendRtxPayloadType) {
1417 uint16_t original_sequence_number =
1418 ByteReader<uint16_t>::ReadBigEndian(&data[header.headerLength]);
1419 uint32_t original_ssrc =
1420 rtx_to_media_ssrcs_.find(header.ssrc)->second;
1421 std::set<uint16_t>* seq_no_map = &dropped_seq_[original_ssrc];
1422 auto it = seq_no_map->find(original_sequence_number);
1423 if (it != seq_no_map->end()) {
1424 retransmit_observed_ = true;
1425 seq_no_map->erase(it);
1426 } else {
1427 rtx_padding_observed_ = true;
1428 }
1429 } else {
1430 streams_observed_.insert(header.ssrc);
1431 }
1432
1433 if (IsDone())
Peter Boström5811a392015-12-10 13:02:50 +01001434 done_.Set();
sprang861c55e2015-10-16 10:01:21 -07001435
1436 if (drop_packet)
1437 return true;
1438 }
sprang867fb522015-08-03 04:38:41 -07001439 }
sprang861c55e2015-10-16 10:01:21 -07001440
stefan1d8a5062015-10-02 03:39:33 -07001441 return test::DirectTransport::SendRtp(data, length, options);
sprang867fb522015-08-03 04:38:41 -07001442 }
1443
Erik Språng8d629712015-08-04 16:24:03 +02001444 bool IsDone() {
sprang861c55e2015-10-16 10:01:21 -07001445 bool observed_types_ok =
1446 streams_observed_.size() == MultiStreamTest::kNumStreams &&
1447 padding_observed_ && retransmit_observed_ && rtx_padding_observed_;
1448 if (!observed_types_ok)
1449 return false;
1450 // We should not have any gaps in the sequence number range.
1451 size_t seqno_range =
1452 *received_packed_ids_.rbegin() - *received_packed_ids_.begin() + 1;
1453 return seqno_range == received_packed_ids_.size();
Erik Språng8d629712015-08-04 16:24:03 +02001454 }
1455
Peter Boström5811a392015-12-10 13:02:50 +01001456 bool Wait() {
sprang861c55e2015-10-16 10:01:21 -07001457 {
1458 // Can't be sure until this point that rtx_to_media_ssrcs_ etc have
1459 // been initialized and are OK to read.
1460 rtc::CritScope cs(&lock_);
1461 started_ = true;
1462 }
Peter Boström5811a392015-12-10 13:02:50 +01001463 return done_.Wait(kDefaultTimeoutMs);
sprang861c55e2015-10-16 10:01:21 -07001464 }
sprang867fb522015-08-03 04:38:41 -07001465
sprang861c55e2015-10-16 10:01:21 -07001466 rtc::CriticalSection lock_;
Peter Boström5811a392015-12-10 13:02:50 +01001467 rtc::Event done_;
sprang867fb522015-08-03 04:38:41 -07001468 rtc::scoped_ptr<RtpHeaderParser> parser_;
sprang861c55e2015-10-16 10:01:21 -07001469 SequenceNumberUnwrapper unwrapper_;
1470 std::set<int64_t> received_packed_ids_;
sprang867fb522015-08-03 04:38:41 -07001471 std::set<uint32_t> streams_observed_;
sprang861c55e2015-10-16 10:01:21 -07001472 std::map<uint32_t, std::set<uint16_t>> dropped_seq_;
1473 const uint32_t& first_media_ssrc_;
1474 const std::map<uint32_t, uint32_t>& rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001475 bool padding_observed_;
1476 bool rtx_padding_observed_;
sprang861c55e2015-10-16 10:01:21 -07001477 bool retransmit_observed_;
1478 bool started_;
sprang867fb522015-08-03 04:38:41 -07001479 };
1480
1481 class TransportSequenceNumberTester : public MultiStreamTest {
1482 public:
sprang861c55e2015-10-16 10:01:21 -07001483 TransportSequenceNumberTester()
1484 : first_media_ssrc_(0), observer_(nullptr) {}
sprang867fb522015-08-03 04:38:41 -07001485 virtual ~TransportSequenceNumberTester() {}
1486
1487 protected:
1488 void Wait() override {
henrikg91d6ede2015-09-17 00:24:34 -07001489 RTC_DCHECK(observer_ != nullptr);
Peter Boström5811a392015-12-10 13:02:50 +01001490 EXPECT_TRUE(observer_->Wait());
sprang867fb522015-08-03 04:38:41 -07001491 }
1492
1493 void UpdateSendConfig(
1494 size_t stream_index,
1495 VideoSendStream::Config* send_config,
1496 VideoEncoderConfig* encoder_config,
1497 test::FrameGeneratorCapturer** frame_generator) override {
1498 send_config->rtp.extensions.clear();
1499 send_config->rtp.extensions.push_back(
1500 RtpExtension(RtpExtension::kTransportSequenceNumber, kExtensionId));
1501
1502 // Force some padding to be sent.
1503 const int kPaddingBitrateBps = 50000;
1504 int total_target_bitrate = 0;
1505 for (const VideoStream& stream : encoder_config->streams)
1506 total_target_bitrate += stream.target_bitrate_bps;
1507 encoder_config->min_transmit_bitrate_bps =
1508 total_target_bitrate + kPaddingBitrateBps;
1509
1510 // Configure RTX for redundant payload padding.
1511 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang861c55e2015-10-16 10:01:21 -07001512 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[stream_index]);
sprang867fb522015-08-03 04:38:41 -07001513 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
sprang861c55e2015-10-16 10:01:21 -07001514 rtx_to_media_ssrcs_[kSendRtxSsrcs[stream_index]] =
1515 send_config->rtp.ssrcs[0];
1516
1517 if (stream_index == 0)
1518 first_media_ssrc_ = send_config->rtp.ssrcs[0];
sprang867fb522015-08-03 04:38:41 -07001519 }
1520
1521 void UpdateReceiveConfig(
1522 size_t stream_index,
1523 VideoReceiveStream::Config* receive_config) override {
sprang861c55e2015-10-16 10:01:21 -07001524 receive_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang867fb522015-08-03 04:38:41 -07001525 receive_config->rtp.extensions.clear();
1526 receive_config->rtp.extensions.push_back(
1527 RtpExtension(RtpExtension::kTransportSequenceNumber, kExtensionId));
1528 }
1529
stefanf116bd02015-10-27 08:29:42 -07001530 test::DirectTransport* CreateSendTransport(Call* sender_call) override {
1531 observer_ = new RtpExtensionHeaderObserver(sender_call, first_media_ssrc_,
sprang861c55e2015-10-16 10:01:21 -07001532 rtx_to_media_ssrcs_);
sprang867fb522015-08-03 04:38:41 -07001533 return observer_;
1534 }
1535
1536 private:
sprang861c55e2015-10-16 10:01:21 -07001537 uint32_t first_media_ssrc_;
1538 std::map<uint32_t, uint32_t> rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001539 RtpExtensionHeaderObserver* observer_;
1540 } tester;
1541
1542 tester.RunTest();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001543}
1544
Stefan Holmer04cb7632016-01-14 20:34:30 +01001545class TransportFeedbackTester : public test::EndToEndTest {
1546 public:
1547 explicit TransportFeedbackTester(bool feedback_enabled,
1548 size_t num_video_streams,
1549 size_t num_audio_streams)
1550 : EndToEndTest(::webrtc::EndToEndTest::kDefaultTimeoutMs),
1551 feedback_enabled_(feedback_enabled),
1552 num_video_streams_(num_video_streams),
1553 num_audio_streams_(num_audio_streams) {
1554 // Only one stream of each supported for now.
1555 EXPECT_LE(num_video_streams, 1u);
1556 EXPECT_LE(num_audio_streams, 1u);
1557 }
1558
1559 protected:
1560 Action OnSendRtcp(const uint8_t* data, size_t length) override {
1561 EXPECT_FALSE(HasTransportFeedback(data, length));
1562 return SEND_PACKET;
1563 }
1564
1565 Action OnReceiveRtcp(const uint8_t* data, size_t length) override {
1566 if (HasTransportFeedback(data, length))
1567 observation_complete_.Set();
1568 return SEND_PACKET;
1569 }
1570
1571 bool HasTransportFeedback(const uint8_t* data, size_t length) const {
1572 RTCPUtility::RTCPParserV2 parser(data, length, true);
1573 EXPECT_TRUE(parser.IsValid());
1574
1575 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
1576 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
1577 if (packet_type == RTCPUtility::RTCPPacketTypes::kTransportFeedback)
1578 return true;
1579 packet_type = parser.Iterate();
1580 }
1581
1582 return false;
1583 }
1584
1585 void PerformTest() override {
1586 const int64_t kDisabledFeedbackTimeoutMs = 5000;
1587 EXPECT_EQ(feedback_enabled_,
1588 observation_complete_.Wait(feedback_enabled_
1589 ? test::CallTest::kDefaultTimeoutMs
1590 : kDisabledFeedbackTimeoutMs));
1591 }
1592
1593 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
1594 receiver_call_ = receiver_call;
1595 }
1596
1597 size_t GetNumVideoStreams() const override { return num_video_streams_; }
1598 size_t GetNumAudioStreams() const override { return num_audio_streams_; }
1599
1600 void ModifyVideoConfigs(
1601 VideoSendStream::Config* send_config,
1602 std::vector<VideoReceiveStream::Config>* receive_configs,
1603 VideoEncoderConfig* encoder_config) override {
1604 send_config->rtp.extensions.clear();
1605 send_config->rtp.extensions.push_back(
1606 RtpExtension(RtpExtension::kTransportSequenceNumber, kExtensionId));
1607 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1608 (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
1609 }
1610
1611 void ModifyAudioConfigs(
1612 AudioSendStream::Config* send_config,
1613 std::vector<AudioReceiveStream::Config>* receive_configs) override {
1614 send_config->rtp.extensions.clear();
1615 send_config->rtp.extensions.push_back(
1616 RtpExtension(RtpExtension::kTransportSequenceNumber, kExtensionId));
1617 (*receive_configs)[0].rtp.extensions.clear();
1618 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1619 (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
1620 (*receive_configs)[0].combined_audio_video_bwe = true;
1621 }
1622
1623 private:
Erik Språng6b8d3552015-09-24 15:06:57 +02001624 static const int kExtensionId = 5;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001625 const bool feedback_enabled_;
1626 const size_t num_video_streams_;
1627 const size_t num_audio_streams_;
1628 Call* receiver_call_;
1629};
Erik Språng6b8d3552015-09-24 15:06:57 +02001630
Stefan Holmer04cb7632016-01-14 20:34:30 +01001631TEST_F(EndToEndTest, VideoReceivesTransportFeedback) {
1632 TransportFeedbackTester test(true, 1, 0);
1633 RunBaseTest(&test);
Erik Språng6b8d3552015-09-24 15:06:57 +02001634}
stefan43edf0f2015-11-20 18:05:48 -08001635
Stefan Holmer04cb7632016-01-14 20:34:30 +01001636TEST_F(EndToEndTest, VideoTransportFeedbackNotConfigured) {
1637 TransportFeedbackTester test(false, 1, 0);
1638 RunBaseTest(&test);
stefan43edf0f2015-11-20 18:05:48 -08001639}
1640
Stefan Holmer04cb7632016-01-14 20:34:30 +01001641TEST_F(EndToEndTest, AudioReceivesTransportFeedback) {
1642 TransportFeedbackTester test(true, 0, 1);
1643 RunBaseTest(&test);
1644}
1645
1646TEST_F(EndToEndTest, AudioTransportFeedbackNotConfigured) {
1647 TransportFeedbackTester test(false, 0, 1);
1648 RunBaseTest(&test);
1649}
1650
1651TEST_F(EndToEndTest, AudioVideoReceivesTransportFeedback) {
1652 TransportFeedbackTester test(true, 1, 1);
1653 RunBaseTest(&test);
stefan43edf0f2015-11-20 18:05:48 -08001654}
1655
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001656TEST_F(EndToEndTest, ObserversEncodedFrames) {
1657 class EncodedFrameTestObserver : public EncodedFrameObserver {
1658 public:
1659 EncodedFrameTestObserver()
Peter Boström5811a392015-12-10 13:02:50 +01001660 : length_(0), frame_type_(kEmptyFrame), called_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001661 virtual ~EncodedFrameTestObserver() {}
1662
1663 virtual void EncodedFrameCallback(const EncodedFrame& encoded_frame) {
1664 frame_type_ = encoded_frame.frame_type_;
1665 length_ = encoded_frame.length_;
1666 buffer_.reset(new uint8_t[length_]);
1667 memcpy(buffer_.get(), encoded_frame.data_, length_);
Peter Boström5811a392015-12-10 13:02:50 +01001668 called_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001669 }
1670
Peter Boström5811a392015-12-10 13:02:50 +01001671 bool Wait() { return called_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001672
1673 void ExpectEqualFrames(const EncodedFrameTestObserver& observer) {
1674 ASSERT_EQ(length_, observer.length_)
1675 << "Observed frames are of different lengths.";
1676 EXPECT_EQ(frame_type_, observer.frame_type_)
1677 << "Observed frames have different frame types.";
1678 EXPECT_EQ(0, memcmp(buffer_.get(), observer.buffer_.get(), length_))
1679 << "Observed encoded frames have different content.";
1680 }
1681
1682 private:
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00001683 rtc::scoped_ptr<uint8_t[]> buffer_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001684 size_t length_;
1685 FrameType frame_type_;
Peter Boström5811a392015-12-10 13:02:50 +01001686 rtc::Event called_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001687 };
1688
1689 EncodedFrameTestObserver post_encode_observer;
1690 EncodedFrameTestObserver pre_decode_observer;
1691
solenberg4fbae2b2015-08-28 04:07:10 -07001692 CreateCalls(Call::Config(), Call::Config());
1693
stefanf116bd02015-10-27 08:29:42 -07001694 test::DirectTransport sender_transport(sender_call_.get());
1695 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001696 sender_transport.SetReceiver(receiver_call_->Receiver());
1697 receiver_transport.SetReceiver(sender_call_->Receiver());
1698
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001699 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07001700 CreateMatchingReceiveConfigs(&receiver_transport);
stefanff483612015-12-21 03:14:00 -08001701 video_send_config_.post_encode_callback = &post_encode_observer;
1702 video_receive_configs_[0].pre_decode_callback = &pre_decode_observer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001703
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001704 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001705 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001706
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00001707 rtc::scoped_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +00001708 test::FrameGenerator::CreateChromaGenerator(
stefanff483612015-12-21 03:14:00 -08001709 video_encoder_config_.streams[0].width,
1710 video_encoder_config_.streams[0].height));
1711 video_send_stream_->Input()->IncomingCapturedFrame(
1712 *frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001713
Peter Boström5811a392015-12-10 13:02:50 +01001714 EXPECT_TRUE(post_encode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001715 << "Timed out while waiting for send-side encoded-frame callback.";
1716
Peter Boström5811a392015-12-10 13:02:50 +01001717 EXPECT_TRUE(pre_decode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001718 << "Timed out while waiting for pre-decode encoded-frame callback.";
1719
1720 post_encode_observer.ExpectEqualFrames(pre_decode_observer);
1721
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001722 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001723
1724 sender_transport.StopSending();
1725 receiver_transport.StopSending();
1726
1727 DestroyStreams();
1728}
1729
1730TEST_F(EndToEndTest, ReceiveStreamSendsRemb) {
1731 class RembObserver : public test::EndToEndTest {
1732 public:
1733 RembObserver() : EndToEndTest(kDefaultTimeoutMs) {}
1734
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001735 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001736 RTCPUtility::RTCPParserV2 parser(packet, length, true);
1737 EXPECT_TRUE(parser.IsValid());
1738
1739 bool received_psfb = false;
1740 bool received_remb = false;
1741 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02001742 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
1743 if (packet_type == RTCPUtility::RTCPPacketTypes::kPsfbRemb) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001744 const RTCPUtility::RTCPPacket& packet = parser.Packet();
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001745 EXPECT_EQ(packet.PSFBAPP.SenderSSRC, kReceiverLocalVideoSsrc);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001746 received_psfb = true;
Erik Språng242e22b2015-05-11 10:17:43 +02001747 } else if (packet_type == RTCPUtility::RTCPPacketTypes::kPsfbRembItem) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001748 const RTCPUtility::RTCPPacket& packet = parser.Packet();
1749 EXPECT_GT(packet.REMBItem.BitRate, 0u);
1750 EXPECT_EQ(packet.REMBItem.NumberOfSSRCs, 1u);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001751 EXPECT_EQ(packet.REMBItem.SSRCs[0], kVideoSendSsrcs[0]);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001752 received_remb = true;
1753 }
1754 packet_type = parser.Iterate();
1755 }
1756 if (received_psfb && received_remb)
Peter Boström5811a392015-12-10 13:02:50 +01001757 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001758 return SEND_PACKET;
1759 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001760 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001761 EXPECT_TRUE(Wait()) << "Timed out while waiting for a "
1762 "receiver RTCP REMB packet to be "
1763 "sent.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001764 }
1765 } test;
1766
stefane74eef12016-01-08 06:47:13 -08001767 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001768}
1769
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001770TEST_F(EndToEndTest, VerifyBandwidthStats) {
stefanf116bd02015-10-27 08:29:42 -07001771 class RtcpObserver : public test::EndToEndTest {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001772 public:
1773 RtcpObserver()
1774 : EndToEndTest(kDefaultTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00001775 sender_call_(nullptr),
1776 receiver_call_(nullptr),
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001777 has_seen_pacer_delay_(false) {}
1778
stefanf116bd02015-10-27 08:29:42 -07001779 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001780 Call::Stats sender_stats = sender_call_->GetStats();
1781 Call::Stats receiver_stats = receiver_call_->GetStats();
1782 if (!has_seen_pacer_delay_)
1783 has_seen_pacer_delay_ = sender_stats.pacer_delay_ms > 0;
1784 if (sender_stats.send_bandwidth_bps > 0 &&
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00001785 receiver_stats.recv_bandwidth_bps > 0 && has_seen_pacer_delay_) {
Peter Boström5811a392015-12-10 13:02:50 +01001786 observation_complete_.Set();
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00001787 }
stefanf116bd02015-10-27 08:29:42 -07001788 return SEND_PACKET;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001789 }
1790
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001791 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001792 sender_call_ = sender_call;
1793 receiver_call_ = receiver_call;
1794 }
1795
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001796 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001797 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
1798 "non-zero bandwidth stats.";
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001799 }
1800
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001801 private:
1802 Call* sender_call_;
1803 Call* receiver_call_;
1804 bool has_seen_pacer_delay_;
1805 } test;
1806
stefane74eef12016-01-08 06:47:13 -08001807 RunBaseTest(&test);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001808}
1809
Åsa Persson352b2d72015-04-15 18:00:40 +02001810TEST_F(EndToEndTest, VerifyNackStats) {
1811 static const int kPacketNumberToDrop = 200;
1812 class NackObserver : public test::EndToEndTest {
1813 public:
1814 NackObserver()
1815 : EndToEndTest(kLongTimeoutMs),
1816 sent_rtp_packets_(0),
1817 dropped_rtp_packet_(0),
1818 dropped_rtp_packet_requested_(false),
1819 send_stream_(nullptr),
1820 start_runtime_ms_(-1) {}
1821
1822 private:
1823 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08001824 rtc::CritScope lock(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02001825 if (++sent_rtp_packets_ == kPacketNumberToDrop) {
1826 rtc::scoped_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
1827 RTPHeader header;
1828 EXPECT_TRUE(parser->Parse(packet, length, &header));
1829 dropped_rtp_packet_ = header.sequenceNumber;
1830 return DROP_PACKET;
1831 }
1832 VerifyStats();
1833 return SEND_PACKET;
1834 }
1835
1836 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08001837 rtc::CritScope lock(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02001838 test::RtcpPacketParser rtcp_parser;
1839 rtcp_parser.Parse(packet, length);
1840 std::vector<uint16_t> nacks = rtcp_parser.nack_item()->last_nack_list();
1841 if (!nacks.empty() && std::find(
1842 nacks.begin(), nacks.end(), dropped_rtp_packet_) != nacks.end()) {
1843 dropped_rtp_packet_requested_ = true;
1844 }
1845 return SEND_PACKET;
1846 }
1847
stefan608213e2015-11-01 14:56:10 -08001848 void VerifyStats() EXCLUSIVE_LOCKS_REQUIRED(&crit_) {
Åsa Persson352b2d72015-04-15 18:00:40 +02001849 if (!dropped_rtp_packet_requested_)
1850 return;
1851 int send_stream_nack_packets = 0;
1852 int receive_stream_nack_packets = 0;
1853 VideoSendStream::Stats stats = send_stream_->GetStats();
1854 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
1855 stats.substreams.begin(); it != stats.substreams.end(); ++it) {
1856 const VideoSendStream::StreamStats& stream_stats = it->second;
1857 send_stream_nack_packets +=
1858 stream_stats.rtcp_packet_type_counts.nack_packets;
1859 }
1860 for (size_t i = 0; i < receive_streams_.size(); ++i) {
1861 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
1862 receive_stream_nack_packets +=
1863 stats.rtcp_packet_type_counts.nack_packets;
1864 }
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001865 if (send_stream_nack_packets >= 1 && receive_stream_nack_packets >= 1) {
Åsa Persson352b2d72015-04-15 18:00:40 +02001866 // NACK packet sent on receive stream and received on sent stream.
1867 if (MinMetricRunTimePassed())
Peter Boström5811a392015-12-10 13:02:50 +01001868 observation_complete_.Set();
Åsa Persson352b2d72015-04-15 18:00:40 +02001869 }
1870 }
1871
1872 bool MinMetricRunTimePassed() {
1873 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
1874 if (start_runtime_ms_ == -1) {
1875 start_runtime_ms_ = now;
1876 return false;
1877 }
1878 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
1879 return elapsed_sec > metrics::kMinRunTimeInSeconds;
1880 }
1881
stefanff483612015-12-21 03:14:00 -08001882 void ModifyVideoConfigs(
1883 VideoSendStream::Config* send_config,
1884 std::vector<VideoReceiveStream::Config>* receive_configs,
1885 VideoEncoderConfig* encoder_config) override {
Åsa Persson352b2d72015-04-15 18:00:40 +02001886 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
1887 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
1888 }
1889
stefanff483612015-12-21 03:14:00 -08001890 void OnVideoStreamsCreated(
Åsa Persson352b2d72015-04-15 18:00:40 +02001891 VideoSendStream* send_stream,
1892 const std::vector<VideoReceiveStream*>& receive_streams) override {
1893 send_stream_ = send_stream;
1894 receive_streams_ = receive_streams;
1895 }
1896
1897 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001898 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Åsa Persson352b2d72015-04-15 18:00:40 +02001899 }
1900
stefan608213e2015-11-01 14:56:10 -08001901 rtc::CriticalSection crit_;
Åsa Persson352b2d72015-04-15 18:00:40 +02001902 uint64_t sent_rtp_packets_;
stefan608213e2015-11-01 14:56:10 -08001903 uint16_t dropped_rtp_packet_ GUARDED_BY(&crit_);
1904 bool dropped_rtp_packet_requested_ GUARDED_BY(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02001905 std::vector<VideoReceiveStream*> receive_streams_;
1906 VideoSendStream* send_stream_;
1907 int64_t start_runtime_ms_;
1908 } test;
1909
Åsa Persson3c391cb2015-04-27 10:09:49 +02001910 test::ClearHistograms();
stefane74eef12016-01-08 06:47:13 -08001911 RunBaseTest(&test);
Åsa Persson352b2d72015-04-15 18:00:40 +02001912
Åsa Persson3c391cb2015-04-27 10:09:49 +02001913 EXPECT_EQ(1, test::NumHistogramSamples(
Åsa Persson352b2d72015-04-15 18:00:40 +02001914 "WebRTC.Video.UniqueNackRequestsSentInPercent"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02001915 EXPECT_EQ(1, test::NumHistogramSamples(
Åsa Persson352b2d72015-04-15 18:00:40 +02001916 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
1917 EXPECT_GT(test::LastHistogramSample(
1918 "WebRTC.Video.NackPacketsSentPerMinute"), 0);
1919 EXPECT_GT(test::LastHistogramSample(
1920 "WebRTC.Video.NackPacketsReceivedPerMinute"), 0);
1921}
1922
sprangb4a1ae52015-12-03 08:10:08 -08001923void EndToEndTest::VerifyHistogramStats(bool use_rtx,
1924 bool use_red,
1925 bool screenshare) {
stefanf116bd02015-10-27 08:29:42 -07001926 class StatsObserver : public test::EndToEndTest {
Åsa Persson3c391cb2015-04-27 10:09:49 +02001927 public:
sprangb4a1ae52015-12-03 08:10:08 -08001928 StatsObserver(bool use_rtx, bool use_red, bool screenshare)
Åsa Persson3c391cb2015-04-27 10:09:49 +02001929 : EndToEndTest(kLongTimeoutMs),
1930 use_rtx_(use_rtx),
1931 use_red_(use_red),
sprangb4a1ae52015-12-03 08:10:08 -08001932 screenshare_(screenshare),
Åsa Persson3c391cb2015-04-27 10:09:49 +02001933 sender_call_(nullptr),
1934 receiver_call_(nullptr),
1935 start_runtime_ms_(-1) {}
1936
1937 private:
1938 Action OnSendRtp(const uint8_t* packet, size_t length) override {
1939 if (MinMetricRunTimePassed())
Peter Boström5811a392015-12-10 13:02:50 +01001940 observation_complete_.Set();
Åsa Persson3c391cb2015-04-27 10:09:49 +02001941
Åsa Persson3c391cb2015-04-27 10:09:49 +02001942 // GetStats calls GetSendChannelRtcpStatistics
1943 // (via VideoSendStream::GetRtt) which updates ReportBlockStats used by
1944 // WebRTC.Video.SentPacketsLostInPercent.
1945 // TODO(asapersson): Remove dependency on calling GetStats.
1946 sender_call_->GetStats();
stefanf116bd02015-10-27 08:29:42 -07001947
1948 return SEND_PACKET;
Åsa Persson3c391cb2015-04-27 10:09:49 +02001949 }
1950
1951 bool MinMetricRunTimePassed() {
1952 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
1953 if (start_runtime_ms_ == -1) {
1954 start_runtime_ms_ = now;
1955 return false;
1956 }
1957 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
1958 return elapsed_sec > metrics::kMinRunTimeInSeconds * 2;
1959 }
1960
stefanff483612015-12-21 03:14:00 -08001961 void ModifyVideoConfigs(
1962 VideoSendStream::Config* send_config,
1963 std::vector<VideoReceiveStream::Config>* receive_configs,
1964 VideoEncoderConfig* encoder_config) override {
Åsa Persson3c391cb2015-04-27 10:09:49 +02001965 // NACK
1966 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
1967 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
1968 // FEC
1969 if (use_red_) {
1970 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
1971 send_config->rtp.fec.red_payload_type = kRedPayloadType;
1972 (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
1973 (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
1974 }
1975 // RTX
1976 if (use_rtx_) {
1977 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
1978 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001979 (*receive_configs)[0].rtp.rtx[kFakeVideoSendPayloadType].ssrc =
Åsa Persson3c391cb2015-04-27 10:09:49 +02001980 kSendRtxSsrcs[0];
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001981 (*receive_configs)[0].rtp.rtx[kFakeVideoSendPayloadType].payload_type =
Åsa Persson3c391cb2015-04-27 10:09:49 +02001982 kSendRtxPayloadType;
1983 }
sprangb4a1ae52015-12-03 08:10:08 -08001984 encoder_config->content_type =
1985 screenshare_ ? VideoEncoderConfig::ContentType::kScreen
1986 : VideoEncoderConfig::ContentType::kRealtimeVideo;
Åsa Persson3c391cb2015-04-27 10:09:49 +02001987 }
1988
1989 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
1990 sender_call_ = sender_call;
1991 receiver_call_ = receiver_call;
1992 }
1993
Åsa Persson3c391cb2015-04-27 10:09:49 +02001994 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001995 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Åsa Persson3c391cb2015-04-27 10:09:49 +02001996 }
1997
sprangb4a1ae52015-12-03 08:10:08 -08001998 const bool use_rtx_;
1999 const bool use_red_;
2000 const bool screenshare_;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002001 Call* sender_call_;
2002 Call* receiver_call_;
2003 int64_t start_runtime_ms_;
sprangb4a1ae52015-12-03 08:10:08 -08002004 } test(use_rtx, use_red, screenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002005
2006 test::ClearHistograms();
stefane74eef12016-01-08 06:47:13 -08002007 RunBaseTest(&test);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002008
stefan91d92602015-11-11 10:13:02 -08002009 // Delete the call for Call stats to be reported.
stefan18adf0a2015-11-17 06:24:56 -08002010 sender_call_.reset();
stefan91d92602015-11-11 10:13:02 -08002011 receiver_call_.reset();
2012
sprangb4a1ae52015-12-03 08:10:08 -08002013 std::string video_prefix =
2014 screenshare ? "WebRTC.Video.Screenshare." : "WebRTC.Video.";
2015
Åsa Persson3c391cb2015-04-27 10:09:49 +02002016 // Verify that stats have been updated once.
stefan91d92602015-11-11 10:13:02 -08002017 EXPECT_EQ(
2018 1, test::NumHistogramSamples("WebRTC.Call.VideoBitrateReceivedInKbps"));
2019 EXPECT_EQ(1,
2020 test::NumHistogramSamples("WebRTC.Call.RtcpBitrateReceivedInBps"));
2021 EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Call.BitrateReceivedInKbps"));
stefan18adf0a2015-11-17 06:24:56 -08002022 EXPECT_EQ(
2023 1, test::NumHistogramSamples("WebRTC.Call.EstimatedSendBitrateInKbps"));
2024 EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Call.PacerBitrateInKbps"));
stefan91d92602015-11-11 10:13:02 -08002025
Åsa Persson3c391cb2015-04-27 10:09:49 +02002026 EXPECT_EQ(1, test::NumHistogramSamples(
2027 "WebRTC.Video.NackPacketsSentPerMinute"));
2028 EXPECT_EQ(1, test::NumHistogramSamples(
2029 "WebRTC.Video.NackPacketsReceivedPerMinute"));
2030 EXPECT_EQ(1, test::NumHistogramSamples(
2031 "WebRTC.Video.FirPacketsSentPerMinute"));
2032 EXPECT_EQ(1, test::NumHistogramSamples(
2033 "WebRTC.Video.FirPacketsReceivedPerMinute"));
2034 EXPECT_EQ(1, test::NumHistogramSamples(
2035 "WebRTC.Video.PliPacketsSentPerMinute"));
2036 EXPECT_EQ(1, test::NumHistogramSamples(
2037 "WebRTC.Video.PliPacketsReceivedPerMinute"));
2038
sprangb4a1ae52015-12-03 08:10:08 -08002039 EXPECT_EQ(
2040 1, test::NumHistogramSamples(video_prefix + "KeyFramesSentInPermille"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002041 EXPECT_EQ(1, test::NumHistogramSamples(
2042 "WebRTC.Video.KeyFramesReceivedInPermille"));
2043
2044 EXPECT_EQ(1, test::NumHistogramSamples(
2045 "WebRTC.Video.SentPacketsLostInPercent"));
2046 EXPECT_EQ(1, test::NumHistogramSamples(
2047 "WebRTC.Video.ReceivedPacketsLostInPercent"));
2048
sprangb4a1ae52015-12-03 08:10:08 -08002049 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "InputWidthInPixels"));
2050 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "InputHeightInPixels"));
2051 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "SentWidthInPixels"));
2052 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "SentHeightInPixels"));
asaperssond89920b2015-07-22 06:52:00 -07002053 EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.ReceivedWidthInPixels"));
2054 EXPECT_EQ(1,
2055 test::NumHistogramSamples("WebRTC.Video.ReceivedHeightInPixels"));
2056
stefanff483612015-12-21 03:14:00 -08002057 EXPECT_EQ(static_cast<int>(video_encoder_config_.streams[0].width),
sprangb4a1ae52015-12-03 08:10:08 -08002058 test::LastHistogramSample(video_prefix + "InputWidthInPixels"));
stefanff483612015-12-21 03:14:00 -08002059 EXPECT_EQ(static_cast<int>(video_encoder_config_.streams[0].height),
sprangb4a1ae52015-12-03 08:10:08 -08002060 test::LastHistogramSample(video_prefix + "InputHeightInPixels"));
stefanff483612015-12-21 03:14:00 -08002061 EXPECT_EQ(static_cast<int>(video_encoder_config_.streams[0].width),
sprangb4a1ae52015-12-03 08:10:08 -08002062 test::LastHistogramSample(video_prefix + "SentWidthInPixels"));
stefanff483612015-12-21 03:14:00 -08002063 EXPECT_EQ(static_cast<int>(video_encoder_config_.streams[0].height),
sprangb4a1ae52015-12-03 08:10:08 -08002064 test::LastHistogramSample(video_prefix + "SentHeightInPixels"));
stefanff483612015-12-21 03:14:00 -08002065 EXPECT_EQ(static_cast<int>(video_encoder_config_.streams[0].width),
asaperssond89920b2015-07-22 06:52:00 -07002066 test::LastHistogramSample("WebRTC.Video.ReceivedWidthInPixels"));
stefanff483612015-12-21 03:14:00 -08002067 EXPECT_EQ(static_cast<int>(video_encoder_config_.streams[0].height),
asaperssond89920b2015-07-22 06:52:00 -07002068 test::LastHistogramSample("WebRTC.Video.ReceivedHeightInPixels"));
2069
sprangb4a1ae52015-12-03 08:10:08 -08002070 EXPECT_EQ(1,
2071 test::NumHistogramSamples(video_prefix + "InputFramesPerSecond"));
2072 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "SentFramesPerSecond"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002073 EXPECT_EQ(1, test::NumHistogramSamples(
2074 "WebRTC.Video.DecodedFramesPerSecond"));
asaperssond89920b2015-07-22 06:52:00 -07002075 EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.RenderFramesPerSecond"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002076
asapersson6f14be82015-11-16 00:40:49 -08002077 EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.OnewayDelayInMs"));
2078 EXPECT_EQ(
2079 1, test::NumHistogramSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
2080
sprangb4a1ae52015-12-03 08:10:08 -08002081 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "EncodeTimeInMs"));
asapersson6718e972015-07-24 00:20:58 -07002082 EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.DecodeTimeInMs"));
2083
Åsa Persson3c391cb2015-04-27 10:09:49 +02002084 EXPECT_EQ(1, test::NumHistogramSamples(
2085 "WebRTC.Video.BitrateSentInKbps"));
2086 EXPECT_EQ(1, test::NumHistogramSamples(
2087 "WebRTC.Video.BitrateReceivedInKbps"));
2088 EXPECT_EQ(1, test::NumHistogramSamples(
2089 "WebRTC.Video.MediaBitrateSentInKbps"));
2090 EXPECT_EQ(1, test::NumHistogramSamples(
2091 "WebRTC.Video.MediaBitrateReceivedInKbps"));
2092 EXPECT_EQ(1, test::NumHistogramSamples(
2093 "WebRTC.Video.PaddingBitrateSentInKbps"));
2094 EXPECT_EQ(1, test::NumHistogramSamples(
2095 "WebRTC.Video.PaddingBitrateReceivedInKbps"));
2096 EXPECT_EQ(1, test::NumHistogramSamples(
2097 "WebRTC.Video.RetransmittedBitrateSentInKbps"));
2098 EXPECT_EQ(1, test::NumHistogramSamples(
2099 "WebRTC.Video.RetransmittedBitrateReceivedInKbps"));
2100
sprangb4a1ae52015-12-03 08:10:08 -08002101 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "SendSideDelayInMs"));
2102 EXPECT_EQ(1,
2103 test::NumHistogramSamples(video_prefix + "SendSideDelayMaxInMs"));
asapersson6f14be82015-11-16 00:40:49 -08002104
Åsa Persson3c391cb2015-04-27 10:09:49 +02002105 int num_rtx_samples = use_rtx ? 1 : 0;
2106 EXPECT_EQ(num_rtx_samples, test::NumHistogramSamples(
2107 "WebRTC.Video.RtxBitrateSentInKbps"));
2108 EXPECT_EQ(num_rtx_samples, test::NumHistogramSamples(
2109 "WebRTC.Video.RtxBitrateReceivedInKbps"));
2110
2111 int num_red_samples = use_red ? 1 : 0;
2112 EXPECT_EQ(num_red_samples, test::NumHistogramSamples(
2113 "WebRTC.Video.FecBitrateSentInKbps"));
2114 EXPECT_EQ(num_red_samples, test::NumHistogramSamples(
2115 "WebRTC.Video.FecBitrateReceivedInKbps"));
2116 EXPECT_EQ(num_red_samples, test::NumHistogramSamples(
2117 "WebRTC.Video.ReceivedFecPacketsInPercent"));
2118}
2119
2120TEST_F(EndToEndTest, VerifyHistogramStatsWithRtx) {
2121 const bool kEnabledRtx = true;
2122 const bool kEnabledRed = false;
sprangb4a1ae52015-12-03 08:10:08 -08002123 const bool kScreenshare = false;
2124 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002125}
2126
2127TEST_F(EndToEndTest, VerifyHistogramStatsWithRed) {
2128 const bool kEnabledRtx = false;
2129 const bool kEnabledRed = true;
sprangb4a1ae52015-12-03 08:10:08 -08002130 const bool kScreenshare = false;
2131 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
2132}
2133
2134TEST_F(EndToEndTest, VerifyHistogramStatsWithScreenshare) {
2135 const bool kEnabledRtx = false;
2136 const bool kEnabledRed = false;
2137 const bool kScreenshare = true;
2138 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002139}
2140
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002141void EndToEndTest::TestXrReceiverReferenceTimeReport(bool enable_rrtr) {
2142 static const int kNumRtcpReportPacketsToObserve = 5;
2143 class RtcpXrObserver : public test::EndToEndTest {
2144 public:
2145 explicit RtcpXrObserver(bool enable_rrtr)
2146 : EndToEndTest(kDefaultTimeoutMs),
2147 enable_rrtr_(enable_rrtr),
2148 sent_rtcp_sr_(0),
2149 sent_rtcp_rr_(0),
2150 sent_rtcp_rrtr_(0),
2151 sent_rtcp_dlrr_(0) {}
2152
2153 private:
2154 // Receive stream should send RR packets (and RRTR packets if enabled).
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002155 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002156 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002157 RTCPUtility::RTCPParserV2 parser(packet, length, true);
2158 EXPECT_TRUE(parser.IsValid());
2159
2160 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02002161 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
2162 if (packet_type == RTCPUtility::RTCPPacketTypes::kRr) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002163 ++sent_rtcp_rr_;
2164 } else if (packet_type ==
Erik Språng242e22b2015-05-11 10:17:43 +02002165 RTCPUtility::RTCPPacketTypes::kXrReceiverReferenceTime) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002166 ++sent_rtcp_rrtr_;
2167 }
Erik Språng242e22b2015-05-11 10:17:43 +02002168 EXPECT_NE(packet_type, RTCPUtility::RTCPPacketTypes::kSr);
2169 EXPECT_NE(packet_type,
2170 RTCPUtility::RTCPPacketTypes::kXrDlrrReportBlockItem);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002171 packet_type = parser.Iterate();
2172 }
2173 return SEND_PACKET;
2174 }
2175 // Send stream should send SR packets (and DLRR packets if enabled).
2176 virtual Action OnSendRtcp(const uint8_t* packet, size_t length) {
stefan608213e2015-11-01 14:56:10 -08002177 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002178 RTCPUtility::RTCPParserV2 parser(packet, length, true);
2179 EXPECT_TRUE(parser.IsValid());
2180
2181 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02002182 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
2183 if (packet_type == RTCPUtility::RTCPPacketTypes::kSr) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002184 ++sent_rtcp_sr_;
Erik Språng242e22b2015-05-11 10:17:43 +02002185 } else if (packet_type ==
2186 RTCPUtility::RTCPPacketTypes::kXrDlrrReportBlockItem) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002187 ++sent_rtcp_dlrr_;
2188 }
Erik Språng242e22b2015-05-11 10:17:43 +02002189 EXPECT_NE(packet_type,
2190 RTCPUtility::RTCPPacketTypes::kXrReceiverReferenceTime);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002191 packet_type = parser.Iterate();
2192 }
2193 if (sent_rtcp_sr_ > kNumRtcpReportPacketsToObserve &&
2194 sent_rtcp_rr_ > kNumRtcpReportPacketsToObserve) {
2195 if (enable_rrtr_) {
2196 EXPECT_GT(sent_rtcp_rrtr_, 0);
2197 EXPECT_GT(sent_rtcp_dlrr_, 0);
2198 } else {
2199 EXPECT_EQ(0, sent_rtcp_rrtr_);
2200 EXPECT_EQ(0, sent_rtcp_dlrr_);
2201 }
Peter Boström5811a392015-12-10 13:02:50 +01002202 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002203 }
2204 return SEND_PACKET;
2205 }
2206
stefanff483612015-12-21 03:14:00 -08002207 void ModifyVideoConfigs(
2208 VideoSendStream::Config* send_config,
2209 std::vector<VideoReceiveStream::Config>* receive_configs,
2210 VideoEncoderConfig* encoder_config) override {
pbosda903ea2015-10-02 02:36:56 -07002211 (*receive_configs)[0].rtp.rtcp_mode = RtcpMode::kReducedSize;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002212 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report =
2213 enable_rrtr_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002214 }
2215
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002216 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002217 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002218 << "Timed out while waiting for RTCP SR/RR packets to be sent.";
2219 }
2220
stefan608213e2015-11-01 14:56:10 -08002221 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002222 bool enable_rrtr_;
2223 int sent_rtcp_sr_;
stefan608213e2015-11-01 14:56:10 -08002224 int sent_rtcp_rr_ GUARDED_BY(&crit_);
2225 int sent_rtcp_rrtr_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002226 int sent_rtcp_dlrr_;
2227 } test(enable_rrtr);
2228
stefane74eef12016-01-08 06:47:13 -08002229 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002230}
2231
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002232void EndToEndTest::TestSendsSetSsrcs(size_t num_ssrcs,
2233 bool send_single_ssrc_first) {
2234 class SendsSetSsrcs : public test::EndToEndTest {
2235 public:
2236 SendsSetSsrcs(const uint32_t* ssrcs,
2237 size_t num_ssrcs,
2238 bool send_single_ssrc_first)
2239 : EndToEndTest(kDefaultTimeoutMs),
2240 num_ssrcs_(num_ssrcs),
2241 send_single_ssrc_first_(send_single_ssrc_first),
2242 ssrcs_to_observe_(num_ssrcs),
sprang867fb522015-08-03 04:38:41 -07002243 expect_single_ssrc_(send_single_ssrc_first),
2244 send_stream_(nullptr) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002245 for (size_t i = 0; i < num_ssrcs; ++i)
2246 valid_ssrcs_[ssrcs[i]] = true;
2247 }
2248
2249 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002250 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002251 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002252 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002253
2254 EXPECT_TRUE(valid_ssrcs_[header.ssrc])
2255 << "Received unknown SSRC: " << header.ssrc;
2256
2257 if (!valid_ssrcs_[header.ssrc])
Peter Boström5811a392015-12-10 13:02:50 +01002258 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002259
2260 if (!is_observed_[header.ssrc]) {
2261 is_observed_[header.ssrc] = true;
2262 --ssrcs_to_observe_;
2263 if (expect_single_ssrc_) {
2264 expect_single_ssrc_ = false;
Peter Boström5811a392015-12-10 13:02:50 +01002265 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002266 }
2267 }
2268
2269 if (ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01002270 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002271
2272 return SEND_PACKET;
2273 }
2274
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002275 size_t GetNumVideoStreams() const override { return num_ssrcs_; }
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002276
stefanff483612015-12-21 03:14:00 -08002277 void ModifyVideoConfigs(
2278 VideoSendStream::Config* send_config,
2279 std::vector<VideoReceiveStream::Config>* receive_configs,
2280 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002281 if (num_ssrcs_ > 1) {
2282 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002283 for (size_t i = 0; i < encoder_config->streams.size(); ++i) {
2284 encoder_config->streams[i].min_bitrate_bps = 10000;
2285 encoder_config->streams[i].target_bitrate_bps = 15000;
2286 encoder_config->streams[i].max_bitrate_bps = 20000;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002287 }
2288 }
2289
stefanff483612015-12-21 03:14:00 -08002290 video_encoder_config_all_streams_ = *encoder_config;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002291 if (send_single_ssrc_first_)
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002292 encoder_config->streams.resize(1);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002293 }
2294
stefanff483612015-12-21 03:14:00 -08002295 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002296 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002297 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002298 send_stream_ = send_stream;
2299 }
2300
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002301 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002302 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
2303 << (send_single_ssrc_first_ ? "first SSRC."
2304 : "SSRCs.");
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002305
2306 if (send_single_ssrc_first_) {
2307 // Set full simulcast and continue with the rest of the SSRCs.
stefanff483612015-12-21 03:14:00 -08002308 send_stream_->ReconfigureVideoEncoder(
2309 video_encoder_config_all_streams_);
Peter Boström5811a392015-12-10 13:02:50 +01002310 EXPECT_TRUE(Wait()) << "Timed out while waiting on additional SSRCs.";
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002311 }
2312 }
2313
2314 private:
2315 std::map<uint32_t, bool> valid_ssrcs_;
2316 std::map<uint32_t, bool> is_observed_;
2317
2318 const size_t num_ssrcs_;
2319 const bool send_single_ssrc_first_;
2320
2321 size_t ssrcs_to_observe_;
2322 bool expect_single_ssrc_;
2323
2324 VideoSendStream* send_stream_;
stefanff483612015-12-21 03:14:00 -08002325 VideoEncoderConfig video_encoder_config_all_streams_;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002326 } test(kVideoSendSsrcs, num_ssrcs, send_single_ssrc_first);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002327
stefane74eef12016-01-08 06:47:13 -08002328 RunBaseTest(&test);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002329}
2330
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002331TEST_F(EndToEndTest, ReportsSetEncoderRates) {
2332 class EncoderRateStatsTest : public test::EndToEndTest,
2333 public test::FakeEncoder {
2334 public:
2335 EncoderRateStatsTest()
2336 : EndToEndTest(kDefaultTimeoutMs),
sprang867fb522015-08-03 04:38:41 -07002337 FakeEncoder(Clock::GetRealTimeClock()),
2338 send_stream_(nullptr),
2339 bitrate_kbps_(0) {}
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002340
stefanff483612015-12-21 03:14:00 -08002341 void OnVideoStreamsCreated(
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002342 VideoSendStream* send_stream,
2343 const std::vector<VideoReceiveStream*>& receive_streams) override {
2344 send_stream_ = send_stream;
2345 }
2346
stefanff483612015-12-21 03:14:00 -08002347 void ModifyVideoConfigs(
2348 VideoSendStream::Config* send_config,
2349 std::vector<VideoReceiveStream::Config>* receive_configs,
2350 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002351 send_config->encoder_settings.encoder = this;
2352 }
2353
2354 int32_t SetRates(uint32_t new_target_bitrate, uint32_t framerate) override {
2355 // Make sure not to trigger on any default zero bitrates.
2356 if (new_target_bitrate == 0)
2357 return 0;
Peter Boströmf2f82832015-05-01 13:00:41 +02002358 rtc::CritScope lock(&crit_);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002359 bitrate_kbps_ = new_target_bitrate;
Peter Boström5811a392015-12-10 13:02:50 +01002360 observation_complete_.Set();
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002361 return 0;
2362 }
2363
2364 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002365 ASSERT_TRUE(Wait())
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002366 << "Timed out while waiting for encoder SetRates() call.";
2367 // Wait for GetStats to report a corresponding bitrate.
Peter Boström5811a392015-12-10 13:02:50 +01002368 for (int i = 0; i < kDefaultTimeoutMs; ++i) {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002369 VideoSendStream::Stats stats = send_stream_->GetStats();
2370 {
Peter Boströmf2f82832015-05-01 13:00:41 +02002371 rtc::CritScope lock(&crit_);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002372 if ((stats.target_media_bitrate_bps + 500) / 1000 ==
2373 static_cast<int>(bitrate_kbps_)) {
2374 return;
2375 }
2376 }
2377 SleepMs(1);
2378 }
2379 FAIL()
2380 << "Timed out waiting for stats reporting the currently set bitrate.";
2381 }
2382
2383 private:
stefanf116bd02015-10-27 08:29:42 -07002384 rtc::CriticalSection crit_;
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002385 VideoSendStream* send_stream_;
2386 uint32_t bitrate_kbps_ GUARDED_BY(crit_);
2387 } test;
2388
stefane74eef12016-01-08 06:47:13 -08002389 RunBaseTest(&test);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002390}
2391
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002392TEST_F(EndToEndTest, GetStats) {
2393 static const int kStartBitrateBps = 3000000;
Peter Boströmdef398832015-05-27 17:59:11 +02002394 static const int kExpectedRenderDelayMs = 20;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002395 class StatsObserver : public test::EndToEndTest, public I420FrameCallback {
2396 public:
stefanf116bd02015-10-27 08:29:42 -07002397 StatsObserver()
2398 : EndToEndTest(kLongTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00002399 send_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002400 expected_send_ssrcs_(),
Peter Boström5811a392015-12-10 13:02:50 +01002401 check_stats_event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002402
2403 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002404 Action OnSendRtp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002405 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002406 return SEND_PACKET;
2407 }
2408
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002409 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002410 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002411 return SEND_PACKET;
2412 }
2413
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002414 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002415 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002416 return SEND_PACKET;
2417 }
2418
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002419 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002420 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002421 return SEND_PACKET;
2422 }
2423
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07002424 void FrameCallback(VideoFrame* video_frame) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002425 // Ensure that we have at least 5ms send side delay.
2426 int64_t render_time = video_frame->render_time_ms();
2427 if (render_time > 0)
2428 video_frame->set_render_time_ms(render_time - 5);
2429 }
2430
2431 bool CheckReceiveStats() {
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002432 for (size_t i = 0; i < receive_streams_.size(); ++i) {
2433 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
2434 EXPECT_EQ(expected_receive_ssrcs_[i], stats.ssrc);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002435
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002436 // Make sure all fields have been populated.
2437 // TODO(pbos): Use CompoundKey if/when we ever know that all stats are
2438 // always filled for all receivers.
2439 receive_stats_filled_["IncomingRate"] |=
2440 stats.network_frame_rate != 0 || stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002441
Peter Boströmb7d9a972015-12-18 16:01:11 +01002442 send_stats_filled_["DecoderImplementationName"] |=
2443 stats.decoder_implementation_name ==
2444 test::FakeDecoder::kImplementationName;
Peter Boströmdef398832015-05-27 17:59:11 +02002445 receive_stats_filled_["RenderDelayAsHighAsExpected"] |=
2446 stats.render_delay_ms >= kExpectedRenderDelayMs;
2447
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002448 receive_stats_filled_["FrameCallback"] |= stats.decode_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002449
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002450 receive_stats_filled_["FrameRendered"] |= stats.render_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002451
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002452 receive_stats_filled_["StatisticsUpdated"] |=
2453 stats.rtcp_stats.cumulative_lost != 0 ||
2454 stats.rtcp_stats.extended_max_sequence_number != 0 ||
2455 stats.rtcp_stats.fraction_lost != 0 || stats.rtcp_stats.jitter != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002456
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002457 receive_stats_filled_["DataCountersUpdated"] |=
2458 stats.rtp_stats.transmitted.payload_bytes != 0 ||
2459 stats.rtp_stats.fec.packets != 0 ||
2460 stats.rtp_stats.transmitted.header_bytes != 0 ||
2461 stats.rtp_stats.transmitted.packets != 0 ||
2462 stats.rtp_stats.transmitted.padding_bytes != 0 ||
2463 stats.rtp_stats.retransmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002464
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002465 receive_stats_filled_["CodecStats"] |=
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002466 stats.target_delay_ms != 0 || stats.discarded_packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002467
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002468 receive_stats_filled_["FrameCounts"] |=
2469 stats.frame_counts.key_frames != 0 ||
2470 stats.frame_counts.delta_frames != 0;
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002471
pbosbb36fdf2015-07-09 07:48:14 -07002472 receive_stats_filled_["CName"] |= !stats.c_name.empty();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002473
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002474 receive_stats_filled_["RtcpPacketTypeCount"] |=
2475 stats.rtcp_packet_type_counts.fir_packets != 0 ||
2476 stats.rtcp_packet_type_counts.nack_packets != 0 ||
2477 stats.rtcp_packet_type_counts.pli_packets != 0 ||
2478 stats.rtcp_packet_type_counts.nack_requests != 0 ||
2479 stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbosf42376c2015-08-28 07:35:32 -07002480
2481 assert(stats.current_payload_type == -1 ||
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002482 stats.current_payload_type == kFakeVideoSendPayloadType);
pbosf42376c2015-08-28 07:35:32 -07002483 receive_stats_filled_["IncomingPayloadType"] |=
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002484 stats.current_payload_type == kFakeVideoSendPayloadType;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002485 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002486
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002487 return AllStatsFilled(receive_stats_filled_);
2488 }
2489
2490 bool CheckSendStats() {
henrikg91d6ede2015-09-17 00:24:34 -07002491 RTC_DCHECK(send_stream_ != nullptr);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002492 VideoSendStream::Stats stats = send_stream_->GetStats();
2493
2494 send_stats_filled_["NumStreams"] |=
2495 stats.substreams.size() == expected_send_ssrcs_.size();
2496
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00002497 send_stats_filled_["CpuOveruseMetrics"] |=
2498 stats.avg_encode_time_ms != 0 || stats.encode_usage_percent != 0;
2499
Peter Boströmb7d9a972015-12-18 16:01:11 +01002500 send_stats_filled_["EncoderImplementationName"] |=
2501 stats.encoder_implementation_name ==
2502 test::FakeEncoder::kImplementationName;
2503
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002504 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002505 stats.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002506 it != stats.substreams.end(); ++it) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002507 EXPECT_TRUE(expected_send_ssrcs_.find(it->first) !=
2508 expected_send_ssrcs_.end());
2509
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002510 send_stats_filled_[CompoundKey("CapturedFrameRate", it->first)] |=
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002511 stats.input_frame_rate != 0;
2512
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002513 const VideoSendStream::StreamStats& stream_stats = it->second;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002514
2515 send_stats_filled_[CompoundKey("StatisticsUpdated", it->first)] |=
2516 stream_stats.rtcp_stats.cumulative_lost != 0 ||
2517 stream_stats.rtcp_stats.extended_max_sequence_number != 0 ||
2518 stream_stats.rtcp_stats.fraction_lost != 0;
2519
2520 send_stats_filled_[CompoundKey("DataCountersUpdated", it->first)] |=
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00002521 stream_stats.rtp_stats.fec.packets != 0 ||
2522 stream_stats.rtp_stats.transmitted.padding_bytes != 0 ||
2523 stream_stats.rtp_stats.retransmitted.packets != 0 ||
2524 stream_stats.rtp_stats.transmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002525
2526 send_stats_filled_[CompoundKey("BitrateStatisticsObserver",
2527 it->first)] |=
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002528 stream_stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002529
2530 send_stats_filled_[CompoundKey("FrameCountObserver", it->first)] |=
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002531 stream_stats.frame_counts.delta_frames != 0 ||
2532 stream_stats.frame_counts.key_frames != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002533
2534 send_stats_filled_[CompoundKey("OutgoingRate", it->first)] |=
2535 stats.encode_frame_rate != 0;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +00002536
2537 send_stats_filled_[CompoundKey("Delay", it->first)] |=
2538 stream_stats.avg_delay_ms != 0 || stream_stats.max_delay_ms != 0;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002539
2540 // TODO(pbos): Use CompoundKey when the test makes sure that all SSRCs
2541 // report dropped packets.
2542 send_stats_filled_["RtcpPacketTypeCount"] |=
2543 stream_stats.rtcp_packet_type_counts.fir_packets != 0 ||
2544 stream_stats.rtcp_packet_type_counts.nack_packets != 0 ||
2545 stream_stats.rtcp_packet_type_counts.pli_packets != 0 ||
2546 stream_stats.rtcp_packet_type_counts.nack_requests != 0 ||
2547 stream_stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002548 }
2549
2550 return AllStatsFilled(send_stats_filled_);
2551 }
2552
2553 std::string CompoundKey(const char* name, uint32_t ssrc) {
2554 std::ostringstream oss;
2555 oss << name << "_" << ssrc;
2556 return oss.str();
2557 }
2558
2559 bool AllStatsFilled(const std::map<std::string, bool>& stats_map) {
2560 for (std::map<std::string, bool>::const_iterator it = stats_map.begin();
2561 it != stats_map.end();
2562 ++it) {
2563 if (!it->second)
2564 return false;
2565 }
2566 return true;
2567 }
2568
stefane74eef12016-01-08 06:47:13 -08002569 test::PacketTransport* CreateSendTransport(Call* sender_call) override {
2570 FakeNetworkPipe::Config network_config;
2571 network_config.loss_percent = 5;
2572 return new test::PacketTransport(
2573 sender_call, this, test::PacketTransport::kSender, network_config);
2574 }
2575
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002576 Call::Config GetSenderCallConfig() override {
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002577 Call::Config config = EndToEndTest::GetSenderCallConfig();
Stefan Holmere5904162015-03-26 11:11:06 +01002578 config.bitrate_config.start_bitrate_bps = kStartBitrateBps;
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002579 return config;
2580 }
2581
stefanff483612015-12-21 03:14:00 -08002582 void ModifyVideoConfigs(
2583 VideoSendStream::Config* send_config,
2584 std::vector<VideoReceiveStream::Config>* receive_configs,
2585 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002586 send_config->pre_encode_callback = this; // Used to inject delay.
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002587 expected_cname_ = send_config->rtp.c_name = "SomeCName";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002588
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002589 const std::vector<uint32_t>& ssrcs = send_config->rtp.ssrcs;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002590 for (size_t i = 0; i < ssrcs.size(); ++i) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002591 expected_send_ssrcs_.insert(ssrcs[i]);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002592 expected_receive_ssrcs_.push_back(
2593 (*receive_configs)[i].rtp.remote_ssrc);
Peter Boströmdef398832015-05-27 17:59:11 +02002594 (*receive_configs)[i].render_delay_ms = kExpectedRenderDelayMs;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002595 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002596 }
2597
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002598 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.orgece38902014-11-14 11:52:04 +00002599
stefanff483612015-12-21 03:14:00 -08002600 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002601 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002602 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002603 send_stream_ = send_stream;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002604 receive_streams_ = receive_streams;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002605 }
2606
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002607 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002608 Clock* clock = Clock::GetRealTimeClock();
2609 int64_t now = clock->TimeInMilliseconds();
2610 int64_t stop_time = now + test::CallTest::kLongTimeoutMs;
2611 bool receive_ok = false;
2612 bool send_ok = false;
2613
2614 while (now < stop_time) {
2615 if (!receive_ok)
2616 receive_ok = CheckReceiveStats();
2617 if (!send_ok)
2618 send_ok = CheckSendStats();
2619
2620 if (receive_ok && send_ok)
2621 return;
2622
2623 int64_t time_until_timout_ = stop_time - now;
2624 if (time_until_timout_ > 0)
Peter Boström5811a392015-12-10 13:02:50 +01002625 check_stats_event_.Wait(time_until_timout_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002626 now = clock->TimeInMilliseconds();
2627 }
2628
2629 ADD_FAILURE() << "Timed out waiting for filled stats.";
2630 for (std::map<std::string, bool>::const_iterator it =
2631 receive_stats_filled_.begin();
2632 it != receive_stats_filled_.end();
2633 ++it) {
2634 if (!it->second) {
2635 ADD_FAILURE() << "Missing receive stats: " << it->first;
2636 }
2637 }
2638
2639 for (std::map<std::string, bool>::const_iterator it =
2640 send_stats_filled_.begin();
2641 it != send_stats_filled_.end();
2642 ++it) {
2643 if (!it->second) {
2644 ADD_FAILURE() << "Missing send stats: " << it->first;
2645 }
2646 }
2647 }
2648
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002649 std::vector<VideoReceiveStream*> receive_streams_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002650 std::map<std::string, bool> receive_stats_filled_;
2651
2652 VideoSendStream* send_stream_;
2653 std::map<std::string, bool> send_stats_filled_;
2654
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002655 std::vector<uint32_t> expected_receive_ssrcs_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002656 std::set<uint32_t> expected_send_ssrcs_;
2657 std::string expected_cname_;
2658
Peter Boström5811a392015-12-10 13:02:50 +01002659 rtc::Event check_stats_event_;
stefanf116bd02015-10-27 08:29:42 -07002660 } test;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002661
stefane74eef12016-01-08 06:47:13 -08002662 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002663}
2664
2665TEST_F(EndToEndTest, ReceiverReferenceTimeReportEnabled) {
2666 TestXrReceiverReferenceTimeReport(true);
2667}
2668
2669TEST_F(EndToEndTest, ReceiverReferenceTimeReportDisabled) {
2670 TestXrReceiverReferenceTimeReport(false);
2671}
2672
2673TEST_F(EndToEndTest, TestReceivedRtpPacketStats) {
2674 static const size_t kNumRtpPacketsToSend = 5;
2675 class ReceivedRtpStatsObserver : public test::EndToEndTest {
2676 public:
2677 ReceivedRtpStatsObserver()
2678 : EndToEndTest(kDefaultTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00002679 receive_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002680 sent_rtp_(0) {}
2681
2682 private:
stefanff483612015-12-21 03:14:00 -08002683 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002684 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002685 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002686 receive_stream_ = receive_streams[0];
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002687 }
2688
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002689 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002690 if (sent_rtp_ >= kNumRtpPacketsToSend) {
2691 VideoReceiveStream::Stats stats = receive_stream_->GetStats();
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00002692 if (kNumRtpPacketsToSend == stats.rtp_stats.transmitted.packets) {
Peter Boström5811a392015-12-10 13:02:50 +01002693 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002694 }
2695 return DROP_PACKET;
2696 }
2697 ++sent_rtp_;
2698 return SEND_PACKET;
2699 }
2700
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002701 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002702 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002703 << "Timed out while verifying number of received RTP packets.";
2704 }
2705
2706 VideoReceiveStream* receive_stream_;
2707 uint32_t sent_rtp_;
2708 } test;
2709
stefane74eef12016-01-08 06:47:13 -08002710 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002711}
2712
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002713TEST_F(EndToEndTest, SendsSetSsrc) { TestSendsSetSsrcs(1, false); }
2714
2715TEST_F(EndToEndTest, SendsSetSimulcastSsrcs) {
2716 TestSendsSetSsrcs(kNumSsrcs, false);
2717}
2718
2719TEST_F(EndToEndTest, CanSwitchToUseAllSsrcs) {
2720 TestSendsSetSsrcs(kNumSsrcs, true);
2721}
2722
mflodman@webrtc.orgf9460682014-07-24 16:41:25 +00002723TEST_F(EndToEndTest, DISABLED_RedundantPayloadsTransmittedOnAllSsrcs) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002724 class ObserveRedundantPayloads: public test::EndToEndTest {
2725 public:
2726 ObserveRedundantPayloads()
2727 : EndToEndTest(kDefaultTimeoutMs), ssrcs_to_observe_(kNumSsrcs) {
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00002728 for (size_t i = 0; i < kNumSsrcs; ++i) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002729 registered_rtx_ssrc_[kSendRtxSsrcs[i]] = true;
2730 }
2731 }
2732
2733 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002734 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002735 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002736 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002737
2738 if (!registered_rtx_ssrc_[header.ssrc])
2739 return SEND_PACKET;
2740
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00002741 EXPECT_LE(header.headerLength + header.paddingLength, length);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002742 const bool packet_is_redundant_payload =
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00002743 header.headerLength + header.paddingLength < length;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002744
2745 if (!packet_is_redundant_payload)
2746 return SEND_PACKET;
2747
2748 if (!observed_redundant_retransmission_[header.ssrc]) {
2749 observed_redundant_retransmission_[header.ssrc] = true;
2750 if (--ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01002751 observation_complete_.Set();
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002752 }
2753
2754 return SEND_PACKET;
2755 }
2756
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002757 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002758
stefanff483612015-12-21 03:14:00 -08002759 void ModifyVideoConfigs(
2760 VideoSendStream::Config* send_config,
2761 std::vector<VideoReceiveStream::Config>* receive_configs,
2762 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002763 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002764 for (size_t i = 0; i < encoder_config->streams.size(); ++i) {
2765 encoder_config->streams[i].min_bitrate_bps = 10000;
2766 encoder_config->streams[i].target_bitrate_bps = 15000;
2767 encoder_config->streams[i].max_bitrate_bps = 20000;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002768 }
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002769
2770 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002771
2772 for (size_t i = 0; i < kNumSsrcs; ++i)
2773 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.orgad3b5a52014-10-24 09:23:21 +00002774
2775 // Significantly higher than max bitrates for all video streams -> forcing
2776 // padding to trigger redundant padding on all RTX SSRCs.
2777 encoder_config->min_transmit_bitrate_bps = 100000;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002778 }
2779
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002780 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002781 EXPECT_TRUE(Wait())
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002782 << "Timed out while waiting for redundant payloads on all SSRCs.";
2783 }
2784
2785 private:
2786 size_t ssrcs_to_observe_;
2787 std::map<uint32_t, bool> observed_redundant_retransmission_;
2788 std::map<uint32_t, bool> registered_rtx_ssrc_;
2789 } test;
2790
stefane74eef12016-01-08 06:47:13 -08002791 RunBaseTest(&test);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002792}
2793
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002794void EndToEndTest::TestRtpStatePreservation(bool use_rtx) {
2795 static const uint32_t kMaxSequenceNumberGap = 100;
2796 static const uint64_t kMaxTimestampGap = kDefaultTimeoutMs * 90;
2797 class RtpSequenceObserver : public test::RtpRtcpObserver {
2798 public:
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00002799 explicit RtpSequenceObserver(bool use_rtx)
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002800 : test::RtpRtcpObserver(kDefaultTimeoutMs),
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002801 ssrcs_to_observe_(kNumSsrcs) {
2802 for (size_t i = 0; i < kNumSsrcs; ++i) {
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002803 configured_ssrcs_[kVideoSendSsrcs[i]] = true;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002804 if (use_rtx)
2805 configured_ssrcs_[kSendRtxSsrcs[i]] = true;
2806 }
2807 }
2808
2809 void ResetExpectedSsrcs(size_t num_expected_ssrcs) {
Peter Boströmf2f82832015-05-01 13:00:41 +02002810 rtc::CritScope lock(&crit_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002811 ssrc_observed_.clear();
2812 ssrcs_to_observe_ = num_expected_ssrcs;
2813 }
2814
2815 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002816 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002817 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002818 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002819 const uint32_t ssrc = header.ssrc;
2820 const uint16_t sequence_number = header.sequenceNumber;
2821 const uint32_t timestamp = header.timestamp;
2822 const bool only_padding =
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00002823 header.headerLength + header.paddingLength == length;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002824
2825 EXPECT_TRUE(configured_ssrcs_[ssrc])
2826 << "Received SSRC that wasn't configured: " << ssrc;
2827
2828 std::map<uint32_t, uint16_t>::iterator it =
2829 last_observed_sequence_number_.find(header.ssrc);
2830 if (it == last_observed_sequence_number_.end()) {
2831 last_observed_sequence_number_[ssrc] = sequence_number;
2832 last_observed_timestamp_[ssrc] = timestamp;
2833 } else {
2834 // Verify sequence numbers are reasonably close.
2835 uint32_t extended_sequence_number = sequence_number;
2836 // Check for roll-over.
2837 if (sequence_number < last_observed_sequence_number_[ssrc])
2838 extended_sequence_number += 0xFFFFu + 1;
2839 EXPECT_LE(
2840 extended_sequence_number - last_observed_sequence_number_[ssrc],
2841 kMaxSequenceNumberGap)
2842 << "Gap in sequence numbers ("
2843 << last_observed_sequence_number_[ssrc] << " -> " << sequence_number
2844 << ") too large for SSRC: " << ssrc << ".";
2845 last_observed_sequence_number_[ssrc] = sequence_number;
2846
2847 // TODO(pbos): Remove this check if we ever have monotonically
2848 // increasing timestamps. Right now padding packets add a delta which
2849 // can cause reordering between padding packets and regular packets,
2850 // hence we drop padding-only packets to not flake.
2851 if (only_padding) {
2852 // Verify that timestamps are reasonably close.
2853 uint64_t extended_timestamp = timestamp;
2854 // Check for roll-over.
2855 if (timestamp < last_observed_timestamp_[ssrc])
2856 extended_timestamp += static_cast<uint64_t>(0xFFFFFFFFu) + 1;
2857 EXPECT_LE(extended_timestamp - last_observed_timestamp_[ssrc],
2858 kMaxTimestampGap)
2859 << "Gap in timestamps (" << last_observed_timestamp_[ssrc]
2860 << " -> " << timestamp << ") too large for SSRC: " << ssrc << ".";
2861 }
2862 last_observed_timestamp_[ssrc] = timestamp;
2863 }
2864
Peter Boströmf2f82832015-05-01 13:00:41 +02002865 rtc::CritScope lock(&crit_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002866 // Wait for media packets on all ssrcs.
2867 if (!ssrc_observed_[ssrc] && !only_padding) {
2868 ssrc_observed_[ssrc] = true;
2869 if (--ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01002870 observation_complete_.Set();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002871 }
2872
2873 return SEND_PACKET;
2874 }
2875
2876 std::map<uint32_t, uint16_t> last_observed_sequence_number_;
2877 std::map<uint32_t, uint32_t> last_observed_timestamp_;
2878 std::map<uint32_t, bool> configured_ssrcs_;
2879
Peter Boströmf2f82832015-05-01 13:00:41 +02002880 rtc::CriticalSection crit_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002881 size_t ssrcs_to_observe_ GUARDED_BY(crit_);
2882 std::map<uint32_t, bool> ssrc_observed_ GUARDED_BY(crit_);
2883 } observer(use_rtx);
2884
solenberg4fbae2b2015-08-28 04:07:10 -07002885 CreateCalls(Call::Config(), Call::Config());
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002886
stefanf116bd02015-10-27 08:29:42 -07002887 test::PacketTransport send_transport(sender_call_.get(), &observer,
2888 test::PacketTransport::kSender,
2889 FakeNetworkPipe::Config());
2890 test::PacketTransport receive_transport(nullptr, &observer,
2891 test::PacketTransport::kReceiver,
2892 FakeNetworkPipe::Config());
2893 send_transport.SetReceiver(receiver_call_->Receiver());
2894 receive_transport.SetReceiver(sender_call_->Receiver());
2895
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002896 CreateSendConfig(kNumSsrcs, 0, &send_transport);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002897
2898 if (use_rtx) {
2899 for (size_t i = 0; i < kNumSsrcs; ++i) {
stefanff483612015-12-21 03:14:00 -08002900 video_send_config_.rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002901 }
stefanff483612015-12-21 03:14:00 -08002902 video_send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002903 }
2904
2905 // Lower bitrates so that all streams send initially.
stefanff483612015-12-21 03:14:00 -08002906 for (size_t i = 0; i < video_encoder_config_.streams.size(); ++i) {
2907 video_encoder_config_.streams[i].min_bitrate_bps = 10000;
2908 video_encoder_config_.streams[i].target_bitrate_bps = 15000;
2909 video_encoder_config_.streams[i].max_bitrate_bps = 20000;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002910 }
2911
pbos@webrtc.org32452b22014-10-22 12:15:24 +00002912 // Use the same total bitrates when sending a single stream to avoid lowering
2913 // the bitrate estimate and requiring a subsequent rampup.
stefanff483612015-12-21 03:14:00 -08002914 VideoEncoderConfig one_stream = video_encoder_config_;
pbos@webrtc.org32452b22014-10-22 12:15:24 +00002915 one_stream.streams.resize(1);
stefanff483612015-12-21 03:14:00 -08002916 for (size_t i = 1; i < video_encoder_config_.streams.size(); ++i) {
pbos@webrtc.org32452b22014-10-22 12:15:24 +00002917 one_stream.streams.front().min_bitrate_bps +=
stefanff483612015-12-21 03:14:00 -08002918 video_encoder_config_.streams[i].min_bitrate_bps;
pbos@webrtc.org32452b22014-10-22 12:15:24 +00002919 one_stream.streams.front().target_bitrate_bps +=
stefanff483612015-12-21 03:14:00 -08002920 video_encoder_config_.streams[i].target_bitrate_bps;
pbos@webrtc.org32452b22014-10-22 12:15:24 +00002921 one_stream.streams.front().max_bitrate_bps +=
stefanff483612015-12-21 03:14:00 -08002922 video_encoder_config_.streams[i].max_bitrate_bps;
pbos@webrtc.org32452b22014-10-22 12:15:24 +00002923 }
2924
stefanf116bd02015-10-27 08:29:42 -07002925 CreateMatchingReceiveConfigs(&receive_transport);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002926
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002927 CreateVideoStreams();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002928 CreateFrameGeneratorCapturer();
2929
2930 Start();
Peter Boström5811a392015-12-10 13:02:50 +01002931 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002932 << "Timed out waiting for all SSRCs to send packets.";
2933
2934 // Test stream resetting more than once to make sure that the state doesn't
2935 // get set once (this could be due to using std::map::insert for instance).
2936 for (size_t i = 0; i < 3; ++i) {
2937 frame_generator_capturer_->Stop();
stefanff483612015-12-21 03:14:00 -08002938 sender_call_->DestroyVideoSendStream(video_send_stream_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002939
2940 // Re-create VideoSendStream with only one stream.
stefanff483612015-12-21 03:14:00 -08002941 video_send_stream_ =
2942 sender_call_->CreateVideoSendStream(video_send_config_, one_stream);
2943 video_send_stream_->Start();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002944 CreateFrameGeneratorCapturer();
2945 frame_generator_capturer_->Start();
2946
2947 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01002948 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002949
2950 // Reconfigure back to use all streams.
stefanff483612015-12-21 03:14:00 -08002951 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002952 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01002953 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002954 << "Timed out waiting for all SSRCs to send packets.";
2955
2956 // Reconfigure down to one stream.
stefanff483612015-12-21 03:14:00 -08002957 video_send_stream_->ReconfigureVideoEncoder(one_stream);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002958 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01002959 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002960
2961 // Reconfigure back to use all streams.
stefanff483612015-12-21 03:14:00 -08002962 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002963 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01002964 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002965 << "Timed out waiting for all SSRCs to send packets.";
2966 }
2967
stefanf116bd02015-10-27 08:29:42 -07002968 send_transport.StopSending();
2969 receive_transport.StopSending();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002970
2971 Stop();
2972 DestroyStreams();
2973}
2974
aluebs@webrtc.orgb623c5c2014-08-26 14:22:51 +00002975TEST_F(EndToEndTest, DISABLED_RestartingSendStreamPreservesRtpState) {
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002976 TestRtpStatePreservation(false);
2977}
2978
2979TEST_F(EndToEndTest, RestartingSendStreamPreservesRtpStatesWithRtx) {
2980 TestRtpStatePreservation(true);
2981}
2982
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002983TEST_F(EndToEndTest, RespectsNetworkState) {
2984 // TODO(pbos): Remove accepted downtime packets etc. when signaling network
2985 // down blocks until no more packets will be sent.
2986
2987 // Pacer will send from its packet list and then send required padding before
2988 // checking paused_ again. This should be enough for one round of pacing,
2989 // otherwise increase.
2990 static const int kNumAcceptedDowntimeRtp = 5;
2991 // A single RTCP may be in the pipeline.
2992 static const int kNumAcceptedDowntimeRtcp = 1;
2993 class NetworkStateTest : public test::EndToEndTest, public test::FakeEncoder {
2994 public:
2995 NetworkStateTest()
2996 : EndToEndTest(kDefaultTimeoutMs),
2997 FakeEncoder(Clock::GetRealTimeClock()),
Peter Boström5811a392015-12-10 13:02:50 +01002998 encoded_frames_(false, false),
2999 packet_event_(false, false),
sprang867fb522015-08-03 04:38:41 -07003000 sender_call_(nullptr),
3001 receiver_call_(nullptr),
Jelena Marusiccd670222015-07-16 09:30:09 +02003002 sender_state_(kNetworkUp),
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003003 sender_rtp_(0),
3004 sender_rtcp_(0),
3005 receiver_rtcp_(0),
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003006 down_frames_(0) {}
3007
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003008 Action OnSendRtp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003009 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003010 ++sender_rtp_;
Peter Boström5811a392015-12-10 13:02:50 +01003011 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003012 return SEND_PACKET;
3013 }
3014
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003015 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003016 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003017 ++sender_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01003018 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003019 return SEND_PACKET;
3020 }
3021
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003022 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003023 ADD_FAILURE() << "Unexpected receiver RTP, should not be sending.";
3024 return SEND_PACKET;
3025 }
3026
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003027 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003028 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003029 ++receiver_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01003030 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003031 return SEND_PACKET;
3032 }
3033
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003034 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003035 sender_call_ = sender_call;
3036 receiver_call_ = receiver_call;
3037 }
3038
stefanff483612015-12-21 03:14:00 -08003039 void ModifyVideoConfigs(
3040 VideoSendStream::Config* send_config,
3041 std::vector<VideoReceiveStream::Config>* receive_configs,
3042 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003043 send_config->encoder_settings.encoder = this;
3044 }
3045
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003046 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003047 EXPECT_TRUE(encoded_frames_.Wait(kDefaultTimeoutMs))
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003048 << "No frames received by the encoder.";
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003049 // Wait for packets from both sender/receiver.
3050 WaitForPacketsOrSilence(false, false);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003051
3052 // Sender-side network down.
Jelena Marusiccd670222015-07-16 09:30:09 +02003053 sender_call_->SignalNetworkState(kNetworkDown);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003054 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003055 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003056 // After network goes down we shouldn't be encoding more frames.
Jelena Marusiccd670222015-07-16 09:30:09 +02003057 sender_state_ = kNetworkDown;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003058 }
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003059 // Wait for receiver-packets and no sender packets.
3060 WaitForPacketsOrSilence(true, false);
3061
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003062 // Receiver-side network down.
Jelena Marusiccd670222015-07-16 09:30:09 +02003063 receiver_call_->SignalNetworkState(kNetworkDown);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003064 WaitForPacketsOrSilence(true, true);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003065
3066 // Network back up again for both.
3067 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003068 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003069 // It's OK to encode frames again, as we're about to bring up the
3070 // network.
Jelena Marusiccd670222015-07-16 09:30:09 +02003071 sender_state_ = kNetworkUp;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003072 }
Jelena Marusiccd670222015-07-16 09:30:09 +02003073 sender_call_->SignalNetworkState(kNetworkUp);
3074 receiver_call_->SignalNetworkState(kNetworkUp);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003075 WaitForPacketsOrSilence(false, false);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003076 }
3077
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07003078 int32_t Encode(const VideoFrame& input_image,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003079 const CodecSpecificInfo* codec_specific_info,
pbos22993e12015-10-19 02:39:06 -07003080 const std::vector<FrameType>* frame_types) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003081 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003082 rtc::CritScope lock(&test_crit_);
Jelena Marusiccd670222015-07-16 09:30:09 +02003083 if (sender_state_ == kNetworkDown) {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003084 ++down_frames_;
3085 EXPECT_LE(down_frames_, 1)
3086 << "Encoding more than one frame while network is down.";
3087 if (down_frames_ > 1)
Peter Boström5811a392015-12-10 13:02:50 +01003088 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003089 } else {
Peter Boström5811a392015-12-10 13:02:50 +01003090 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003091 }
3092 }
3093 return test::FakeEncoder::Encode(
3094 input_image, codec_specific_info, frame_types);
3095 }
3096
3097 private:
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003098 void WaitForPacketsOrSilence(bool sender_down, bool receiver_down) {
3099 int64_t initial_time_ms = clock_->TimeInMilliseconds();
3100 int initial_sender_rtp;
3101 int initial_sender_rtcp;
3102 int initial_receiver_rtcp;
3103 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003104 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003105 initial_sender_rtp = sender_rtp_;
3106 initial_sender_rtcp = sender_rtcp_;
3107 initial_receiver_rtcp = receiver_rtcp_;
3108 }
3109 bool sender_done = false;
3110 bool receiver_done = false;
mflodmand1590b22015-12-09 07:07:59 -08003111 while (!sender_done || !receiver_done) {
Peter Boström5811a392015-12-10 13:02:50 +01003112 packet_event_.Wait(kSilenceTimeoutMs);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003113 int64_t time_now_ms = clock_->TimeInMilliseconds();
Peter Boströmf2f82832015-05-01 13:00:41 +02003114 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003115 if (sender_down) {
3116 ASSERT_LE(sender_rtp_ - initial_sender_rtp, kNumAcceptedDowntimeRtp)
3117 << "RTP sent during sender-side downtime.";
3118 ASSERT_LE(sender_rtcp_ - initial_sender_rtcp,
3119 kNumAcceptedDowntimeRtcp)
3120 << "RTCP sent during sender-side downtime.";
3121 if (time_now_ms - initial_time_ms >=
3122 static_cast<int64_t>(kSilenceTimeoutMs)) {
3123 sender_done = true;
3124 }
3125 } else {
3126 if (sender_rtp_ > initial_sender_rtp)
3127 sender_done = true;
3128 }
3129 if (receiver_down) {
3130 ASSERT_LE(receiver_rtcp_ - initial_receiver_rtcp,
3131 kNumAcceptedDowntimeRtcp)
3132 << "RTCP sent during receiver-side downtime.";
3133 if (time_now_ms - initial_time_ms >=
3134 static_cast<int64_t>(kSilenceTimeoutMs)) {
3135 receiver_done = true;
3136 }
3137 } else {
3138 if (receiver_rtcp_ > initial_receiver_rtcp)
3139 receiver_done = true;
3140 }
3141 }
3142 }
3143
Peter Boströmf2f82832015-05-01 13:00:41 +02003144 rtc::CriticalSection test_crit_;
Peter Boström5811a392015-12-10 13:02:50 +01003145 rtc::Event encoded_frames_;
3146 rtc::Event packet_event_;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003147 Call* sender_call_;
3148 Call* receiver_call_;
Jelena Marusiccd670222015-07-16 09:30:09 +02003149 NetworkState sender_state_ GUARDED_BY(test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003150 int sender_rtp_ GUARDED_BY(test_crit_);
3151 int sender_rtcp_ GUARDED_BY(test_crit_);
3152 int receiver_rtcp_ GUARDED_BY(test_crit_);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003153 int down_frames_ GUARDED_BY(test_crit_);
3154 } test;
3155
stefane74eef12016-01-08 06:47:13 -08003156 RunBaseTest(&test);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003157}
3158
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003159TEST_F(EndToEndTest, CallReportsRttForSender) {
3160 static const int kSendDelayMs = 30;
3161 static const int kReceiveDelayMs = 70;
3162
solenberg4fbae2b2015-08-28 04:07:10 -07003163 CreateCalls(Call::Config(), Call::Config());
3164
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003165 FakeNetworkPipe::Config config;
3166 config.queue_delay_ms = kSendDelayMs;
stefanf116bd02015-10-27 08:29:42 -07003167 test::DirectTransport sender_transport(config, sender_call_.get());
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003168 config.queue_delay_ms = kReceiveDelayMs;
stefanf116bd02015-10-27 08:29:42 -07003169 test::DirectTransport receiver_transport(config, receiver_call_.get());
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003170 sender_transport.SetReceiver(receiver_call_->Receiver());
3171 receiver_transport.SetReceiver(sender_call_->Receiver());
3172
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003173 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07003174 CreateMatchingReceiveConfigs(&receiver_transport);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003175
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003176 CreateVideoStreams();
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003177 CreateFrameGeneratorCapturer();
3178 Start();
3179
3180 int64_t start_time_ms = clock_->TimeInMilliseconds();
3181 while (true) {
3182 Call::Stats stats = sender_call_->GetStats();
3183 ASSERT_GE(start_time_ms + kDefaultTimeoutMs,
3184 clock_->TimeInMilliseconds())
3185 << "No RTT stats before timeout!";
3186 if (stats.rtt_ms != -1) {
3187 EXPECT_GE(stats.rtt_ms, kSendDelayMs + kReceiveDelayMs);
3188 break;
3189 }
3190 SleepMs(10);
3191 }
3192
3193 Stop();
3194 DestroyStreams();
3195}
3196
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003197TEST_F(EndToEndTest, NewSendStreamsRespectNetworkDown) {
3198 class UnusedEncoder : public test::FakeEncoder {
mflodmand1590b22015-12-09 07:07:59 -08003199 public:
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003200 UnusedEncoder() : FakeEncoder(Clock::GetRealTimeClock()) {}
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07003201 int32_t Encode(const VideoFrame& input_image,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003202 const CodecSpecificInfo* codec_specific_info,
pbos22993e12015-10-19 02:39:06 -07003203 const std::vector<FrameType>* frame_types) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003204 ADD_FAILURE() << "Unexpected frame encode.";
3205 return test::FakeEncoder::Encode(
3206 input_image, codec_specific_info, frame_types);
3207 }
3208 };
3209
solenberg4fbae2b2015-08-28 04:07:10 -07003210 CreateSenderCall(Call::Config());
Jelena Marusiccd670222015-07-16 09:30:09 +02003211 sender_call_->SignalNetworkState(kNetworkDown);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003212
solenberg4fbae2b2015-08-28 04:07:10 -07003213 UnusedTransport transport;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003214 CreateSendConfig(1, 0, &transport);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003215 UnusedEncoder unused_encoder;
stefanff483612015-12-21 03:14:00 -08003216 video_send_config_.encoder_settings.encoder = &unused_encoder;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003217 CreateVideoStreams();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003218 CreateFrameGeneratorCapturer();
3219
3220 Start();
3221 SleepMs(kSilenceTimeoutMs);
3222 Stop();
3223
3224 DestroyStreams();
3225}
3226
3227TEST_F(EndToEndTest, NewReceiveStreamsRespectNetworkDown) {
solenberg4fbae2b2015-08-28 04:07:10 -07003228 CreateCalls(Call::Config(), Call::Config());
Jelena Marusiccd670222015-07-16 09:30:09 +02003229 receiver_call_->SignalNetworkState(kNetworkDown);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003230
stefanf116bd02015-10-27 08:29:42 -07003231 test::DirectTransport sender_transport(sender_call_.get());
solenberg4fbae2b2015-08-28 04:07:10 -07003232 sender_transport.SetReceiver(receiver_call_->Receiver());
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003233 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07003234 UnusedTransport transport;
3235 CreateMatchingReceiveConfigs(&transport);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003236 CreateVideoStreams();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003237 CreateFrameGeneratorCapturer();
3238
3239 Start();
3240 SleepMs(kSilenceTimeoutMs);
3241 Stop();
3242
3243 sender_transport.StopSending();
3244
3245 DestroyStreams();
3246}
pbos@webrtc.org09cc6862014-11-04 13:48:15 +00003247
Peter Boströmd7da1202015-06-05 14:09:38 +02003248void VerifyEmptyNackConfig(const NackConfig& config) {
3249 EXPECT_EQ(0, config.rtp_history_ms)
3250 << "Enabling NACK requires rtcp-fb: nack negotiation.";
3251}
3252
3253void VerifyEmptyFecConfig(const FecConfig& config) {
3254 EXPECT_EQ(-1, config.ulpfec_payload_type)
3255 << "Enabling FEC requires rtpmap: ulpfec negotiation.";
3256 EXPECT_EQ(-1, config.red_payload_type)
3257 << "Enabling FEC requires rtpmap: red negotiation.";
3258 EXPECT_EQ(-1, config.red_rtx_payload_type)
3259 << "Enabling RTX in FEC requires rtpmap: rtx negotiation.";
3260}
3261
3262TEST_F(EndToEndTest, VerifyDefaultSendConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07003263 VideoSendStream::Config default_send_config(nullptr);
Peter Boströmd7da1202015-06-05 14:09:38 +02003264 EXPECT_EQ(0, default_send_config.rtp.nack.rtp_history_ms)
3265 << "Enabling NACK require rtcp-fb: nack negotiation.";
3266 EXPECT_TRUE(default_send_config.rtp.rtx.ssrcs.empty())
3267 << "Enabling RTX requires rtpmap: rtx negotiation.";
3268 EXPECT_TRUE(default_send_config.rtp.extensions.empty())
3269 << "Enabling RTP extensions require negotiation.";
3270
3271 VerifyEmptyNackConfig(default_send_config.rtp.nack);
3272 VerifyEmptyFecConfig(default_send_config.rtp.fec);
3273}
3274
3275TEST_F(EndToEndTest, VerifyDefaultReceiveConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07003276 VideoReceiveStream::Config default_receive_config(nullptr);
pbosda903ea2015-10-02 02:36:56 -07003277 EXPECT_EQ(RtcpMode::kCompound, default_receive_config.rtp.rtcp_mode)
Peter Boströmd7da1202015-06-05 14:09:38 +02003278 << "Reduced-size RTCP require rtcp-rsize to be negotiated.";
3279 EXPECT_FALSE(default_receive_config.rtp.remb)
3280 << "REMB require rtcp-fb: goog-remb to be negotiated.";
3281 EXPECT_FALSE(
3282 default_receive_config.rtp.rtcp_xr.receiver_reference_time_report)
3283 << "RTCP XR settings require rtcp-xr to be negotiated.";
3284 EXPECT_TRUE(default_receive_config.rtp.rtx.empty())
3285 << "Enabling RTX requires rtpmap: rtx negotiation.";
3286 EXPECT_TRUE(default_receive_config.rtp.extensions.empty())
3287 << "Enabling RTP extensions require negotiation.";
3288
3289 VerifyEmptyNackConfig(default_receive_config.rtp.nack);
3290 VerifyEmptyFecConfig(default_receive_config.rtp.fec);
3291}
3292
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003293TEST_F(EndToEndTest, TransportSeqNumOnAudioAndVideo) {
3294 static const int kExtensionId = 8;
3295 class TransportSequenceNumberTest : public test::EndToEndTest {
3296 public:
3297 TransportSequenceNumberTest()
3298 : EndToEndTest(kDefaultTimeoutMs),
3299 video_observed_(false),
3300 audio_observed_(false) {
3301 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
3302 kExtensionId);
3303 }
3304
3305 size_t GetNumVideoStreams() const override { return 1; }
3306 size_t GetNumAudioStreams() const override { return 1; }
3307
3308 void ModifyVideoConfigs(
3309 VideoSendStream::Config* send_config,
3310 std::vector<VideoReceiveStream::Config>* receive_configs,
3311 VideoEncoderConfig* encoder_config) override {
3312 send_config->rtp.extensions.clear();
3313 send_config->rtp.extensions.push_back(
3314 RtpExtension(RtpExtension::kTransportSequenceNumber, kExtensionId));
3315 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
3316 }
3317
3318 void ModifyAudioConfigs(
3319 AudioSendStream::Config* send_config,
3320 std::vector<AudioReceiveStream::Config>* receive_configs) override {
3321 send_config->rtp.extensions.clear();
3322 send_config->rtp.extensions.push_back(
3323 RtpExtension(RtpExtension::kTransportSequenceNumber, kExtensionId));
3324 (*receive_configs)[0].rtp.extensions.clear();
3325 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
3326 }
3327
3328 Action OnSendRtp(const uint8_t* packet, size_t length) override {
3329 RTPHeader header;
3330 EXPECT_TRUE(parser_->Parse(packet, length, &header));
3331 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
3332 // Unwrap packet id and verify uniqueness.
3333 int64_t packet_id =
3334 unwrapper_.Unwrap(header.extension.transportSequenceNumber);
3335 EXPECT_TRUE(received_packet_ids_.insert(packet_id).second);
3336
3337 if (header.ssrc == kVideoSendSsrcs[0])
3338 video_observed_ = true;
3339 if (header.ssrc == kAudioSendSsrc)
3340 audio_observed_ = true;
3341 if (audio_observed_ && video_observed_ &&
3342 received_packet_ids_.size() == 50) {
3343 size_t packet_id_range =
3344 *received_packet_ids_.rbegin() - *received_packet_ids_.begin() + 1;
3345 EXPECT_EQ(received_packet_ids_.size(), packet_id_range);
3346 observation_complete_.Set();
3347 }
3348 return SEND_PACKET;
3349 }
3350
3351 void PerformTest() override {
3352 EXPECT_TRUE(Wait()) << "Timed out while waiting for audio and video "
3353 "packets with transport sequence number.";
3354 }
3355
3356 private:
3357 bool video_observed_;
3358 bool audio_observed_;
3359 SequenceNumberUnwrapper unwrapper_;
3360 std::set<int64_t> received_packet_ids_;
3361 } test;
3362
stefane74eef12016-01-08 06:47:13 -08003363 RunBaseTest(&test);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003364}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003365} // namespace webrtc