blob: 3c774abdff540f7264289caf0ff204eeba0e26ac [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
stefanf116bd02015-10-27 08:29:42 -0700286 RunBaseTest(&test, FakeNetworkPipe::Config());
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
stefanf116bd02015-10-27 08:29:42 -0700339 RunBaseTest(&test, FakeNetworkPipe::Config());
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
stefanf116bd02015-10-27 08:29:42 -0700367 RunBaseTest(&test, FakeNetworkPipe::Config());
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
stefanf116bd02015-10-27 08:29:42 -0700457 RunBaseTest(&test, FakeNetworkPipe::Config());
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
stefanf116bd02015-10-27 08:29:42 -0700558 RunBaseTest(&test, FakeNetworkPipe::Config());
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
Stefan Holmere5904162015-03-26 11:11:06 +0100640 // TODO(holmer): Investigate why we don't send FEC packets when the bitrate
641 // is 10 kbps.
642 Call::Config GetSenderCallConfig() override {
solenberg4fbae2b2015-08-28 04:07:10 -0700643 Call::Config config;
Stefan Holmere5904162015-03-26 11:11:06 +0100644 const int kMinBitrateBps = 30000;
645 config.bitrate_config.min_bitrate_bps = kMinBitrateBps;
646 return config;
647 }
648
stefanff483612015-12-21 03:14:00 -0800649 void ModifyVideoConfigs(
650 VideoSendStream::Config* send_config,
651 std::vector<VideoReceiveStream::Config>* receive_configs,
652 VideoEncoderConfig* encoder_config) override {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000653 // Configure hybrid NACK/FEC.
654 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
655 send_config->rtp.fec.red_payload_type = kRedPayloadType;
656 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
657 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
658 (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
659 (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
660 }
661
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000662 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100663 EXPECT_TRUE(Wait())
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000664 << "Timed out while waiting for FEC packets to be received.";
665 }
666
667 enum {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000668 kFirstPacket,
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000669 kDropEveryOtherPacketUntilFec,
670 kDropAllMediaPacketsUntilFec,
671 kVerifyFecPacketNotInNackList,
672 } state_;
673
stefan608213e2015-11-01 14:56:10 -0800674 rtc::CriticalSection crit_;
675 uint16_t fec_sequence_number_ GUARDED_BY(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000676 bool has_last_sequence_number_;
677 uint16_t last_sequence_number_;
stefanf116bd02015-10-27 08:29:42 -0700678 } test;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000679
stefanf116bd02015-10-27 08:29:42 -0700680 // At low RTT (< kLowRttNackMs) -> NACK only, no FEC.
681 // Configure some network delay.
682 const int kNetworkDelayMs = 50;
683 FakeNetworkPipe::Config config;
684 config.queue_delay_ms = kNetworkDelayMs;
685 RunBaseTest(&test, config);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000686}
687
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000688// This test drops second RTP packet with a marker bit set, makes sure it's
689// retransmitted and renders. Retransmission SSRCs are also checked.
Shao Changbine62202f2015-04-21 20:24:50 +0800690void EndToEndTest::DecodesRetransmittedFrame(bool use_rtx, bool use_red) {
Stefan Holmer586b19b2015-09-18 11:14:31 +0200691 // Must be set high enough to allow the bitrate probing to finish.
692 static const int kMinProbePackets = 30;
693 static const int kDroppedFrameNumber = kMinProbePackets + 1;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000694 class RetransmissionObserver : public test::EndToEndTest,
695 public I420FrameCallback {
696 public:
Shao Changbine62202f2015-04-21 20:24:50 +0800697 explicit RetransmissionObserver(bool use_rtx, bool use_red)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000698 : EndToEndTest(kDefaultTimeoutMs),
Shao Changbine62202f2015-04-21 20:24:50 +0800699 payload_type_(GetPayloadType(false, use_red)),
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100700 retransmission_ssrc_(use_rtx ? kSendRtxSsrcs[0] : kVideoSendSsrcs[0]),
Shao Changbine62202f2015-04-21 20:24:50 +0800701 retransmission_payload_type_(GetPayloadType(use_rtx, use_red)),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000702 marker_bits_observed_(0),
Stefan Holmer586b19b2015-09-18 11:14:31 +0200703 num_packets_observed_(0),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000704 retransmitted_timestamp_(0),
705 frame_retransmitted_(false) {}
706
707 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000708 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700709 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000710 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000711 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000712
Stefan Holmer586b19b2015-09-18 11:14:31 +0200713 // We accept some padding or RTX packets in the beginning to enable
714 // bitrate probing.
715 if (num_packets_observed_++ < kMinProbePackets &&
716 header.payloadType != payload_type_) {
717 EXPECT_TRUE(retransmission_payload_type_ == header.payloadType ||
718 length == header.headerLength + header.paddingLength);
719 return SEND_PACKET;
720 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000721 if (header.timestamp == retransmitted_timestamp_) {
722 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
723 EXPECT_EQ(retransmission_payload_type_, header.payloadType);
724 frame_retransmitted_ = true;
725 return SEND_PACKET;
726 }
727
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100728 EXPECT_EQ(kVideoSendSsrcs[0], header.ssrc);
Shao Changbine62202f2015-04-21 20:24:50 +0800729 EXPECT_EQ(payload_type_, header.payloadType);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000730
Stefan Holmer586b19b2015-09-18 11:14:31 +0200731 // Found the final packet of the frame to inflict loss to, drop this and
732 // expect a retransmission.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000733 if (header.markerBit && ++marker_bits_observed_ == kDroppedFrameNumber) {
734 retransmitted_timestamp_ = header.timestamp;
735 return DROP_PACKET;
736 }
737
738 return SEND_PACKET;
739 }
740
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700741 void FrameCallback(VideoFrame* frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200742 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000743 if (frame->timestamp() == retransmitted_timestamp_) {
744 EXPECT_TRUE(frame_retransmitted_);
Peter Boström5811a392015-12-10 13:02:50 +0100745 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000746 }
747 }
748
stefanff483612015-12-21 03:14:00 -0800749 void ModifyVideoConfigs(
750 VideoSendStream::Config* send_config,
751 std::vector<VideoReceiveStream::Config>* receive_configs,
752 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000753 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000754 (*receive_configs)[0].pre_render_callback = this;
755 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
Shao Changbine62202f2015-04-21 20:24:50 +0800756
757 if (payload_type_ == kRedPayloadType) {
758 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
759 send_config->rtp.fec.red_payload_type = kRedPayloadType;
760 (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
761 (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
762 }
763
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000764 if (retransmission_ssrc_ == kSendRtxSsrcs[0]) {
765 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000766 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100767 (*receive_configs)[0].rtp.rtx[kFakeVideoSendPayloadType].ssrc =
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000768 kSendRtxSsrcs[0];
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100769 (*receive_configs)[0].rtp.rtx[kFakeVideoSendPayloadType].payload_type =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000770 kSendRtxPayloadType;
771 }
772 }
773
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000774 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100775 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000776 << "Timed out while waiting for retransmission to render.";
777 }
778
Shao Changbine62202f2015-04-21 20:24:50 +0800779 int GetPayloadType(bool use_rtx, bool use_red) {
780 return use_rtx ? kSendRtxPayloadType
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100781 : (use_red ? kRedPayloadType : kFakeVideoSendPayloadType);
Shao Changbine62202f2015-04-21 20:24:50 +0800782 }
783
stefanf116bd02015-10-27 08:29:42 -0700784 rtc::CriticalSection crit_;
Shao Changbine62202f2015-04-21 20:24:50 +0800785 const int payload_type_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000786 const uint32_t retransmission_ssrc_;
787 const int retransmission_payload_type_;
788 int marker_bits_observed_;
Stefan Holmer586b19b2015-09-18 11:14:31 +0200789 int num_packets_observed_;
stefanf116bd02015-10-27 08:29:42 -0700790 uint32_t retransmitted_timestamp_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000791 bool frame_retransmitted_;
Shao Changbine62202f2015-04-21 20:24:50 +0800792 } test(use_rtx, use_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000793
stefanf116bd02015-10-27 08:29:42 -0700794 RunBaseTest(&test, FakeNetworkPipe::Config());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000795}
796
797TEST_F(EndToEndTest, DecodesRetransmittedFrame) {
Shao Changbine62202f2015-04-21 20:24:50 +0800798 DecodesRetransmittedFrame(false, false);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000799}
800
801TEST_F(EndToEndTest, DecodesRetransmittedFrameOverRtx) {
Shao Changbine62202f2015-04-21 20:24:50 +0800802 DecodesRetransmittedFrame(true, false);
803}
804
805TEST_F(EndToEndTest, DecodesRetransmittedFrameByRed) {
806 DecodesRetransmittedFrame(false, true);
807}
808
809TEST_F(EndToEndTest, DecodesRetransmittedFrameByRedOverRtx) {
810 DecodesRetransmittedFrame(true, true);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000811}
812
andresp@webrtc.org02686112014-09-19 08:24:19 +0000813TEST_F(EndToEndTest, UsesFrameCallbacks) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000814 static const int kWidth = 320;
815 static const int kHeight = 240;
816
817 class Renderer : public VideoRenderer {
818 public:
Peter Boström5811a392015-12-10 13:02:50 +0100819 Renderer() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000820
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700821 void RenderFrame(const VideoFrame& video_frame,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000822 int /*time_to_render_ms*/) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000823 EXPECT_EQ(0, *video_frame.buffer(kYPlane))
824 << "Rendered frame should have zero luma which is applied by the "
825 "pre-render callback.";
Peter Boström5811a392015-12-10 13:02:50 +0100826 event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000827 }
828
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000829 bool IsTextureSupported() const override { return false; }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000830
Peter Boström5811a392015-12-10 13:02:50 +0100831 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
832 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000833 } renderer;
834
835 class TestFrameCallback : public I420FrameCallback {
836 public:
837 TestFrameCallback(int expected_luma_byte, int next_luma_byte)
Peter Boström5811a392015-12-10 13:02:50 +0100838 : event_(false, false),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000839 expected_luma_byte_(expected_luma_byte),
840 next_luma_byte_(next_luma_byte) {}
841
Peter Boström5811a392015-12-10 13:02:50 +0100842 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000843
844 private:
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700845 virtual void FrameCallback(VideoFrame* frame) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000846 EXPECT_EQ(kWidth, frame->width())
847 << "Width not as expected, callback done before resize?";
848 EXPECT_EQ(kHeight, frame->height())
849 << "Height not as expected, callback done before resize?";
850
851 // Previous luma specified, observed luma should be fairly close.
852 if (expected_luma_byte_ != -1) {
853 EXPECT_NEAR(expected_luma_byte_, *frame->buffer(kYPlane), 10);
854 }
855
856 memset(frame->buffer(kYPlane),
857 next_luma_byte_,
858 frame->allocated_size(kYPlane));
859
Peter Boström5811a392015-12-10 13:02:50 +0100860 event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000861 }
862
Peter Boström5811a392015-12-10 13:02:50 +0100863 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000864 int expected_luma_byte_;
865 int next_luma_byte_;
866 };
867
868 TestFrameCallback pre_encode_callback(-1, 255); // Changes luma to 255.
869 TestFrameCallback pre_render_callback(255, 0); // Changes luma from 255 to 0.
870
solenberg4fbae2b2015-08-28 04:07:10 -0700871 CreateCalls(Call::Config(), Call::Config());
872
stefanf116bd02015-10-27 08:29:42 -0700873 test::DirectTransport sender_transport(sender_call_.get());
874 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000875 sender_transport.SetReceiver(receiver_call_->Receiver());
876 receiver_transport.SetReceiver(sender_call_->Receiver());
877
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100878 CreateSendConfig(1, 0, &sender_transport);
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000879 rtc::scoped_ptr<VideoEncoder> encoder(
pbos@webrtc.orgab990ae2014-09-17 09:02:25 +0000880 VideoEncoder::Create(VideoEncoder::kVp8));
stefanff483612015-12-21 03:14:00 -0800881 video_send_config_.encoder_settings.encoder = encoder.get();
882 video_send_config_.encoder_settings.payload_name = "VP8";
883 ASSERT_EQ(1u, video_encoder_config_.streams.size()) << "Test setup error.";
884 video_encoder_config_.streams[0].width = kWidth;
885 video_encoder_config_.streams[0].height = kHeight;
886 video_send_config_.pre_encode_callback = &pre_encode_callback;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000887
solenberg4fbae2b2015-08-28 04:07:10 -0700888 CreateMatchingReceiveConfigs(&receiver_transport);
stefanff483612015-12-21 03:14:00 -0800889 video_receive_configs_[0].pre_render_callback = &pre_render_callback;
890 video_receive_configs_[0].renderer = &renderer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000891
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100892 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000893 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000894
895 // Create frames that are smaller than the send width/height, this is done to
896 // check that the callbacks are done after processing video.
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000897 rtc::scoped_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +0000898 test::FrameGenerator::CreateChromaGenerator(kWidth / 2, kHeight / 2));
stefanff483612015-12-21 03:14:00 -0800899 video_send_stream_->Input()->IncomingCapturedFrame(
900 *frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000901
Peter Boström5811a392015-12-10 13:02:50 +0100902 EXPECT_TRUE(pre_encode_callback.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000903 << "Timed out while waiting for pre-encode callback.";
Peter Boström5811a392015-12-10 13:02:50 +0100904 EXPECT_TRUE(pre_render_callback.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000905 << "Timed out while waiting for pre-render callback.";
Peter Boström5811a392015-12-10 13:02:50 +0100906 EXPECT_TRUE(renderer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000907 << "Timed out while waiting for the frame to render.";
908
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000909 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000910
911 sender_transport.StopSending();
912 receiver_transport.StopSending();
913
914 DestroyStreams();
915}
916
917void EndToEndTest::ReceivesPliAndRecovers(int rtp_history_ms) {
918 static const int kPacketsToDrop = 1;
919
920 class PliObserver : public test::EndToEndTest, public VideoRenderer {
921 public:
922 explicit PliObserver(int rtp_history_ms)
923 : EndToEndTest(kLongTimeoutMs),
924 rtp_history_ms_(rtp_history_ms),
925 nack_enabled_(rtp_history_ms > 0),
926 highest_dropped_timestamp_(0),
927 frames_to_drop_(0),
928 received_pli_(false) {}
929
930 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000931 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700932 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000933 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000934 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000935
936 // Drop all retransmitted packets to force a PLI.
937 if (header.timestamp <= highest_dropped_timestamp_)
938 return DROP_PACKET;
939
940 if (frames_to_drop_ > 0) {
941 highest_dropped_timestamp_ = header.timestamp;
942 --frames_to_drop_;
943 return DROP_PACKET;
944 }
945
946 return SEND_PACKET;
947 }
948
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000949 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700950 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000951 RTCPUtility::RTCPParserV2 parser(packet, length, true);
952 EXPECT_TRUE(parser.IsValid());
953
954 for (RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +0200955 packet_type != RTCPUtility::RTCPPacketTypes::kInvalid;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000956 packet_type = parser.Iterate()) {
957 if (!nack_enabled_)
Erik Språng242e22b2015-05-11 10:17:43 +0200958 EXPECT_NE(packet_type, RTCPUtility::RTCPPacketTypes::kRtpfbNack);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000959
Erik Språng242e22b2015-05-11 10:17:43 +0200960 if (packet_type == RTCPUtility::RTCPPacketTypes::kPsfbPli) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000961 received_pli_ = true;
962 break;
963 }
964 }
965 return SEND_PACKET;
966 }
967
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700968 void RenderFrame(const VideoFrame& video_frame,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000969 int time_to_render_ms) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200970 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000971 if (received_pli_ &&
972 video_frame.timestamp() > highest_dropped_timestamp_) {
Peter Boström5811a392015-12-10 13:02:50 +0100973 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000974 }
975 if (!received_pli_)
976 frames_to_drop_ = kPacketsToDrop;
977 }
978
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000979 bool IsTextureSupported() const override { return false; }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000980
stefanff483612015-12-21 03:14:00 -0800981 void ModifyVideoConfigs(
982 VideoSendStream::Config* send_config,
983 std::vector<VideoReceiveStream::Config>* receive_configs,
984 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000985 send_config->rtp.nack.rtp_history_ms = rtp_history_ms_;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000986 (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms_;
987 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000988 }
989
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000990 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100991 EXPECT_TRUE(Wait()) << "Timed out waiting for PLI to be "
992 "received and a frame to be "
993 "rendered afterwards.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000994 }
995
stefanf116bd02015-10-27 08:29:42 -0700996 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000997 int rtp_history_ms_;
998 bool nack_enabled_;
stefanf116bd02015-10-27 08:29:42 -0700999 uint32_t highest_dropped_timestamp_ GUARDED_BY(&crit_);
1000 int frames_to_drop_ GUARDED_BY(&crit_);
1001 bool received_pli_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001002 } test(rtp_history_ms);
1003
stefanf116bd02015-10-27 08:29:42 -07001004 RunBaseTest(&test, FakeNetworkPipe::Config());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001005}
1006
1007TEST_F(EndToEndTest, ReceivesPliAndRecoversWithNack) {
1008 ReceivesPliAndRecovers(1000);
1009}
1010
jbauchdb81ffd2015-11-23 03:59:02 -08001011TEST_F(EndToEndTest, ReceivesPliAndRecoversWithoutNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001012 ReceivesPliAndRecovers(0);
1013}
1014
1015TEST_F(EndToEndTest, UnknownRtpPacketGivesUnknownSsrcReturnCode) {
1016 class PacketInputObserver : public PacketReceiver {
1017 public:
1018 explicit PacketInputObserver(PacketReceiver* receiver)
Peter Boström5811a392015-12-10 13:02:50 +01001019 : receiver_(receiver), delivered_packet_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001020
Peter Boström5811a392015-12-10 13:02:50 +01001021 bool Wait() { return delivered_packet_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001022
1023 private:
stefan68786d22015-09-08 05:36:15 -07001024 DeliveryStatus DeliverPacket(MediaType media_type,
1025 const uint8_t* packet,
1026 size_t length,
1027 const PacketTime& packet_time) override {
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001028 if (RtpHeaderParser::IsRtcp(packet, length)) {
stefan68786d22015-09-08 05:36:15 -07001029 return receiver_->DeliverPacket(media_type, packet, length,
1030 packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001031 } else {
1032 DeliveryStatus delivery_status =
stefan68786d22015-09-08 05:36:15 -07001033 receiver_->DeliverPacket(media_type, packet, length, packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001034 EXPECT_EQ(DELIVERY_UNKNOWN_SSRC, delivery_status);
Peter Boström5811a392015-12-10 13:02:50 +01001035 delivered_packet_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001036 return delivery_status;
1037 }
1038 }
1039
1040 PacketReceiver* receiver_;
Peter Boström5811a392015-12-10 13:02:50 +01001041 rtc::Event delivered_packet_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001042 };
1043
solenberg4fbae2b2015-08-28 04:07:10 -07001044 CreateCalls(Call::Config(), Call::Config());
1045
stefanf116bd02015-10-27 08:29:42 -07001046 test::DirectTransport send_transport(sender_call_.get());
1047 test::DirectTransport receive_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001048 PacketInputObserver input_observer(receiver_call_->Receiver());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001049 send_transport.SetReceiver(&input_observer);
1050 receive_transport.SetReceiver(sender_call_->Receiver());
1051
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001052 CreateSendConfig(1, 0, &send_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07001053 CreateMatchingReceiveConfigs(&receive_transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001054
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001055 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001056 CreateFrameGeneratorCapturer();
1057 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001058
stefanff483612015-12-21 03:14:00 -08001059 receiver_call_->DestroyVideoReceiveStream(video_receive_streams_[0]);
1060 video_receive_streams_.clear();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001061
1062 // Wait() waits for a received packet.
Peter Boström5811a392015-12-10 13:02:50 +01001063 EXPECT_TRUE(input_observer.Wait());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001064
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001065 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001066
1067 DestroyStreams();
1068
1069 send_transport.StopSending();
1070 receive_transport.StopSending();
1071}
1072
pbosda903ea2015-10-02 02:36:56 -07001073void EndToEndTest::RespectsRtcpMode(RtcpMode rtcp_mode) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001074 static const int kNumCompoundRtcpPacketsToObserve = 10;
1075 class RtcpModeObserver : public test::EndToEndTest {
1076 public:
pbosda903ea2015-10-02 02:36:56 -07001077 explicit RtcpModeObserver(RtcpMode rtcp_mode)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001078 : EndToEndTest(kDefaultTimeoutMs),
1079 rtcp_mode_(rtcp_mode),
1080 sent_rtp_(0),
1081 sent_rtcp_(0) {}
1082
1083 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001084 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001085 if (++sent_rtp_ % 3 == 0)
1086 return DROP_PACKET;
1087
1088 return SEND_PACKET;
1089 }
1090
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001091 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001092 ++sent_rtcp_;
1093 RTCPUtility::RTCPParserV2 parser(packet, length, true);
1094 EXPECT_TRUE(parser.IsValid());
1095
1096 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
1097 bool has_report_block = false;
Erik Språng242e22b2015-05-11 10:17:43 +02001098 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
1099 EXPECT_NE(RTCPUtility::RTCPPacketTypes::kSr, packet_type);
1100 if (packet_type == RTCPUtility::RTCPPacketTypes::kRr) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001101 has_report_block = true;
1102 break;
1103 }
1104 packet_type = parser.Iterate();
1105 }
1106
1107 switch (rtcp_mode_) {
pbosda903ea2015-10-02 02:36:56 -07001108 case RtcpMode::kCompound:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001109 if (!has_report_block) {
1110 ADD_FAILURE() << "Received RTCP packet without receiver report for "
pbosda903ea2015-10-02 02:36:56 -07001111 "RtcpMode::kCompound.";
Peter Boström5811a392015-12-10 13:02:50 +01001112 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001113 }
1114
1115 if (sent_rtcp_ >= kNumCompoundRtcpPacketsToObserve)
Peter Boström5811a392015-12-10 13:02:50 +01001116 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001117
1118 break;
pbosda903ea2015-10-02 02:36:56 -07001119 case RtcpMode::kReducedSize:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001120 if (!has_report_block)
Peter Boström5811a392015-12-10 13:02:50 +01001121 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001122 break;
pbosda903ea2015-10-02 02:36:56 -07001123 case RtcpMode::kOff:
1124 RTC_NOTREACHED();
1125 break;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001126 }
1127
1128 return SEND_PACKET;
1129 }
1130
stefanff483612015-12-21 03:14:00 -08001131 void ModifyVideoConfigs(
1132 VideoSendStream::Config* send_config,
1133 std::vector<VideoReceiveStream::Config>* receive_configs,
1134 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001135 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001136 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
1137 (*receive_configs)[0].rtp.rtcp_mode = rtcp_mode_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001138 }
1139
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001140 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001141 EXPECT_TRUE(Wait())
pbosda903ea2015-10-02 02:36:56 -07001142 << (rtcp_mode_ == RtcpMode::kCompound
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001143 ? "Timed out before observing enough compound packets."
1144 : "Timed out before receiving a non-compound RTCP packet.");
1145 }
1146
pbosda903ea2015-10-02 02:36:56 -07001147 RtcpMode rtcp_mode_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001148 int sent_rtp_;
1149 int sent_rtcp_;
1150 } test(rtcp_mode);
1151
stefanf116bd02015-10-27 08:29:42 -07001152 RunBaseTest(&test, FakeNetworkPipe::Config());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001153}
1154
1155TEST_F(EndToEndTest, UsesRtcpCompoundMode) {
pbosda903ea2015-10-02 02:36:56 -07001156 RespectsRtcpMode(RtcpMode::kCompound);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001157}
1158
1159TEST_F(EndToEndTest, UsesRtcpReducedSizeMode) {
pbosda903ea2015-10-02 02:36:56 -07001160 RespectsRtcpMode(RtcpMode::kReducedSize);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001161}
1162
1163// Test sets up a Call multiple senders with different resolutions and SSRCs.
1164// Another is set up to receive all three of these with different renderers.
sprang867fb522015-08-03 04:38:41 -07001165class MultiStreamTest {
1166 public:
1167 static const size_t kNumStreams = 3;
1168 struct CodecSettings {
1169 uint32_t ssrc;
1170 int width;
1171 int height;
1172 } codec_settings[kNumStreams];
1173
1174 MultiStreamTest() {
1175 // TODO(sprang): Cleanup when msvc supports explicit initializers for array.
1176 codec_settings[0] = {1, 640, 480};
1177 codec_settings[1] = {2, 320, 240};
1178 codec_settings[2] = {3, 240, 160};
1179 }
1180
1181 virtual ~MultiStreamTest() {}
1182
1183 void RunTest() {
solenberg4fbae2b2015-08-28 04:07:10 -07001184 rtc::scoped_ptr<Call> sender_call(Call::Create(Call::Config()));
1185 rtc::scoped_ptr<Call> receiver_call(Call::Create(Call::Config()));
stefanf116bd02015-10-27 08:29:42 -07001186 rtc::scoped_ptr<test::DirectTransport> sender_transport(
1187 CreateSendTransport(sender_call.get()));
1188 rtc::scoped_ptr<test::DirectTransport> receiver_transport(
1189 CreateReceiveTransport(receiver_call.get()));
sprang867fb522015-08-03 04:38:41 -07001190 sender_transport->SetReceiver(receiver_call->Receiver());
1191 receiver_transport->SetReceiver(sender_call->Receiver());
1192
1193 rtc::scoped_ptr<VideoEncoder> encoders[kNumStreams];
1194 for (size_t i = 0; i < kNumStreams; ++i)
1195 encoders[i].reset(VideoEncoder::Create(VideoEncoder::kVp8));
1196
1197 VideoSendStream* send_streams[kNumStreams];
1198 VideoReceiveStream* receive_streams[kNumStreams];
1199
1200 test::FrameGeneratorCapturer* frame_generators[kNumStreams];
1201 ScopedVector<VideoDecoder> allocated_decoders;
1202 for (size_t i = 0; i < kNumStreams; ++i) {
1203 uint32_t ssrc = codec_settings[i].ssrc;
1204 int width = codec_settings[i].width;
1205 int height = codec_settings[i].height;
1206
solenberg4fbae2b2015-08-28 04:07:10 -07001207 VideoSendStream::Config send_config(sender_transport.get());
sprang867fb522015-08-03 04:38:41 -07001208 send_config.rtp.ssrcs.push_back(ssrc);
1209 send_config.encoder_settings.encoder = encoders[i].get();
1210 send_config.encoder_settings.payload_name = "VP8";
1211 send_config.encoder_settings.payload_type = 124;
1212 VideoEncoderConfig encoder_config;
1213 encoder_config.streams = test::CreateVideoStreams(1);
1214 VideoStream* stream = &encoder_config.streams[0];
1215 stream->width = width;
1216 stream->height = height;
1217 stream->max_framerate = 5;
1218 stream->min_bitrate_bps = stream->target_bitrate_bps =
1219 stream->max_bitrate_bps = 100000;
1220
1221 UpdateSendConfig(i, &send_config, &encoder_config, &frame_generators[i]);
1222
1223 send_streams[i] =
1224 sender_call->CreateVideoSendStream(send_config, encoder_config);
1225 send_streams[i]->Start();
1226
solenberg4fbae2b2015-08-28 04:07:10 -07001227 VideoReceiveStream::Config receive_config(receiver_transport.get());
sprang867fb522015-08-03 04:38:41 -07001228 receive_config.rtp.remote_ssrc = ssrc;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001229 receive_config.rtp.local_ssrc = test::CallTest::kReceiverLocalVideoSsrc;
sprang867fb522015-08-03 04:38:41 -07001230 VideoReceiveStream::Decoder decoder =
1231 test::CreateMatchingDecoder(send_config.encoder_settings);
1232 allocated_decoders.push_back(decoder.decoder);
1233 receive_config.decoders.push_back(decoder);
1234
1235 UpdateReceiveConfig(i, &receive_config);
1236
1237 receive_streams[i] =
1238 receiver_call->CreateVideoReceiveStream(receive_config);
1239 receive_streams[i]->Start();
1240
1241 frame_generators[i] = test::FrameGeneratorCapturer::Create(
1242 send_streams[i]->Input(), width, height, 30,
1243 Clock::GetRealTimeClock());
1244 frame_generators[i]->Start();
1245 }
1246
1247 Wait();
1248
1249 for (size_t i = 0; i < kNumStreams; ++i) {
1250 frame_generators[i]->Stop();
1251 sender_call->DestroyVideoSendStream(send_streams[i]);
1252 receiver_call->DestroyVideoReceiveStream(receive_streams[i]);
1253 delete frame_generators[i];
1254 }
1255
1256 sender_transport->StopSending();
1257 receiver_transport->StopSending();
1258 }
1259
1260 protected:
1261 virtual void Wait() = 0;
1262 // Note: frame_generator is a point-to-pointer, since the actual instance
1263 // hasn't been created at the time of this call. Only when packets/frames
1264 // start flowing should this be dereferenced.
1265 virtual void UpdateSendConfig(
1266 size_t stream_index,
1267 VideoSendStream::Config* send_config,
1268 VideoEncoderConfig* encoder_config,
1269 test::FrameGeneratorCapturer** frame_generator) {}
1270 virtual void UpdateReceiveConfig(size_t stream_index,
1271 VideoReceiveStream::Config* receive_config) {
1272 }
stefanf116bd02015-10-27 08:29:42 -07001273 virtual test::DirectTransport* CreateSendTransport(Call* sender_call) {
1274 return new test::DirectTransport(sender_call);
sprang867fb522015-08-03 04:38:41 -07001275 }
stefanf116bd02015-10-27 08:29:42 -07001276 virtual test::DirectTransport* CreateReceiveTransport(Call* receiver_call) {
1277 return new test::DirectTransport(receiver_call);
sprang867fb522015-08-03 04:38:41 -07001278 }
1279};
1280
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001281// Each renderer verifies that it receives the expected resolution, and as soon
1282// as every renderer has received a frame, the test finishes.
andresp@webrtc.org02686112014-09-19 08:24:19 +00001283TEST_F(EndToEndTest, SendsAndReceivesMultipleStreams) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001284 class VideoOutputObserver : public VideoRenderer {
1285 public:
sprang867fb522015-08-03 04:38:41 -07001286 VideoOutputObserver(const MultiStreamTest::CodecSettings& settings,
1287 uint32_t ssrc,
1288 test::FrameGeneratorCapturer** frame_generator)
1289 : settings_(settings),
1290 ssrc_(ssrc),
1291 frame_generator_(frame_generator),
Peter Boström5811a392015-12-10 13:02:50 +01001292 done_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001293
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001294 void RenderFrame(const VideoFrame& video_frame,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001295 int time_to_render_ms) override {
sprang867fb522015-08-03 04:38:41 -07001296 EXPECT_EQ(settings_.width, video_frame.width());
1297 EXPECT_EQ(settings_.height, video_frame.height());
1298 (*frame_generator_)->Stop();
Peter Boström5811a392015-12-10 13:02:50 +01001299 done_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001300 }
1301
sprang867fb522015-08-03 04:38:41 -07001302 uint32_t Ssrc() { return ssrc_; }
1303
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001304 bool IsTextureSupported() const override { return false; }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00001305
Peter Boström5811a392015-12-10 13:02:50 +01001306 bool Wait() { return done_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001307
1308 private:
sprang867fb522015-08-03 04:38:41 -07001309 const MultiStreamTest::CodecSettings& settings_;
1310 const uint32_t ssrc_;
1311 test::FrameGeneratorCapturer** const frame_generator_;
Peter Boström5811a392015-12-10 13:02:50 +01001312 rtc::Event done_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001313 };
1314
sprang867fb522015-08-03 04:38:41 -07001315 class Tester : public MultiStreamTest {
1316 public:
1317 Tester() {}
1318 virtual ~Tester() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001319
sprang867fb522015-08-03 04:38:41 -07001320 protected:
1321 void Wait() override {
1322 for (const auto& observer : observers_) {
Peter Boström5811a392015-12-10 13:02:50 +01001323 EXPECT_TRUE(observer->Wait()) << "Time out waiting for from on ssrc "
1324 << observer->Ssrc();
sprang867fb522015-08-03 04:38:41 -07001325 }
1326 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001327
sprang867fb522015-08-03 04:38:41 -07001328 void UpdateSendConfig(
1329 size_t stream_index,
1330 VideoSendStream::Config* send_config,
1331 VideoEncoderConfig* encoder_config,
1332 test::FrameGeneratorCapturer** frame_generator) override {
1333 observers_[stream_index].reset(new VideoOutputObserver(
1334 codec_settings[stream_index], send_config->rtp.ssrcs.front(),
1335 frame_generator));
1336 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001337
sprang867fb522015-08-03 04:38:41 -07001338 void UpdateReceiveConfig(
1339 size_t stream_index,
1340 VideoReceiveStream::Config* receive_config) override {
1341 receive_config->renderer = observers_[stream_index].get();
1342 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001343
sprang867fb522015-08-03 04:38:41 -07001344 private:
1345 rtc::scoped_ptr<VideoOutputObserver> observers_[kNumStreams];
1346 } tester;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001347
sprang867fb522015-08-03 04:38:41 -07001348 tester.RunTest();
1349}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001350
sprang867fb522015-08-03 04:38:41 -07001351TEST_F(EndToEndTest, AssignsTransportSequenceNumbers) {
sprang867fb522015-08-03 04:38:41 -07001352 static const int kExtensionId = 5;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001353
sprang867fb522015-08-03 04:38:41 -07001354 class RtpExtensionHeaderObserver : public test::DirectTransport {
1355 public:
stefanf116bd02015-10-27 08:29:42 -07001356 RtpExtensionHeaderObserver(Call* sender_call,
1357 const uint32_t& first_media_ssrc,
sprang861c55e2015-10-16 10:01:21 -07001358 const std::map<uint32_t, uint32_t>& ssrc_map)
stefanf116bd02015-10-27 08:29:42 -07001359 : DirectTransport(sender_call),
Peter Boström5811a392015-12-10 13:02:50 +01001360 done_(false, false),
sprang867fb522015-08-03 04:38:41 -07001361 parser_(RtpHeaderParser::Create()),
sprang861c55e2015-10-16 10:01:21 -07001362 first_media_ssrc_(first_media_ssrc),
1363 rtx_to_media_ssrcs_(ssrc_map),
sprang867fb522015-08-03 04:38:41 -07001364 padding_observed_(false),
sprang861c55e2015-10-16 10:01:21 -07001365 rtx_padding_observed_(false),
1366 retransmit_observed_(false),
1367 started_(false) {
sprang867fb522015-08-03 04:38:41 -07001368 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
1369 kExtensionId);
1370 }
1371 virtual ~RtpExtensionHeaderObserver() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001372
stefan1d8a5062015-10-02 03:39:33 -07001373 bool SendRtp(const uint8_t* data,
1374 size_t length,
1375 const PacketOptions& options) override {
sprang861c55e2015-10-16 10:01:21 -07001376 {
1377 rtc::CritScope cs(&lock_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001378
Erik Språng8d629712015-08-04 16:24:03 +02001379 if (IsDone())
sprang861c55e2015-10-16 10:01:21 -07001380 return false;
1381
1382 if (started_) {
1383 RTPHeader header;
1384 EXPECT_TRUE(parser_->Parse(data, length, &header));
1385 bool drop_packet = false;
1386
1387 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
1388 EXPECT_EQ(options.packet_id,
1389 header.extension.transportSequenceNumber);
1390 if (!streams_observed_.empty()) {
1391 // Unwrap packet id and verify uniqueness.
1392 int64_t packet_id = unwrapper_.Unwrap(options.packet_id);
1393 EXPECT_TRUE(received_packed_ids_.insert(packet_id).second);
1394 }
1395
1396 // Drop (up to) every 17th packet, so we get retransmits.
1397 // Only drop media, and not on the first stream (otherwise it will be
1398 // hard to distinguish from padding, which is always sent on the first
1399 // stream).
1400 if (header.payloadType != kSendRtxPayloadType &&
1401 header.ssrc != first_media_ssrc_ &&
1402 header.extension.transportSequenceNumber % 17 == 0) {
1403 dropped_seq_[header.ssrc].insert(header.sequenceNumber);
1404 drop_packet = true;
1405 }
1406
1407 size_t payload_length =
1408 length - (header.headerLength + header.paddingLength);
1409 if (payload_length == 0) {
1410 padding_observed_ = true;
1411 } else if (header.payloadType == kSendRtxPayloadType) {
1412 uint16_t original_sequence_number =
1413 ByteReader<uint16_t>::ReadBigEndian(&data[header.headerLength]);
1414 uint32_t original_ssrc =
1415 rtx_to_media_ssrcs_.find(header.ssrc)->second;
1416 std::set<uint16_t>* seq_no_map = &dropped_seq_[original_ssrc];
1417 auto it = seq_no_map->find(original_sequence_number);
1418 if (it != seq_no_map->end()) {
1419 retransmit_observed_ = true;
1420 seq_no_map->erase(it);
1421 } else {
1422 rtx_padding_observed_ = true;
1423 }
1424 } else {
1425 streams_observed_.insert(header.ssrc);
1426 }
1427
1428 if (IsDone())
Peter Boström5811a392015-12-10 13:02:50 +01001429 done_.Set();
sprang861c55e2015-10-16 10:01:21 -07001430
1431 if (drop_packet)
1432 return true;
1433 }
sprang867fb522015-08-03 04:38:41 -07001434 }
sprang861c55e2015-10-16 10:01:21 -07001435
stefan1d8a5062015-10-02 03:39:33 -07001436 return test::DirectTransport::SendRtp(data, length, options);
sprang867fb522015-08-03 04:38:41 -07001437 }
1438
Erik Språng8d629712015-08-04 16:24:03 +02001439 bool IsDone() {
sprang861c55e2015-10-16 10:01:21 -07001440 bool observed_types_ok =
1441 streams_observed_.size() == MultiStreamTest::kNumStreams &&
1442 padding_observed_ && retransmit_observed_ && rtx_padding_observed_;
1443 if (!observed_types_ok)
1444 return false;
1445 // We should not have any gaps in the sequence number range.
1446 size_t seqno_range =
1447 *received_packed_ids_.rbegin() - *received_packed_ids_.begin() + 1;
1448 return seqno_range == received_packed_ids_.size();
Erik Språng8d629712015-08-04 16:24:03 +02001449 }
1450
Peter Boström5811a392015-12-10 13:02:50 +01001451 bool Wait() {
sprang861c55e2015-10-16 10:01:21 -07001452 {
1453 // Can't be sure until this point that rtx_to_media_ssrcs_ etc have
1454 // been initialized and are OK to read.
1455 rtc::CritScope cs(&lock_);
1456 started_ = true;
1457 }
Peter Boström5811a392015-12-10 13:02:50 +01001458 return done_.Wait(kDefaultTimeoutMs);
sprang861c55e2015-10-16 10:01:21 -07001459 }
sprang867fb522015-08-03 04:38:41 -07001460
sprang861c55e2015-10-16 10:01:21 -07001461 rtc::CriticalSection lock_;
Peter Boström5811a392015-12-10 13:02:50 +01001462 rtc::Event done_;
sprang867fb522015-08-03 04:38:41 -07001463 rtc::scoped_ptr<RtpHeaderParser> parser_;
sprang861c55e2015-10-16 10:01:21 -07001464 SequenceNumberUnwrapper unwrapper_;
1465 std::set<int64_t> received_packed_ids_;
sprang867fb522015-08-03 04:38:41 -07001466 std::set<uint32_t> streams_observed_;
sprang861c55e2015-10-16 10:01:21 -07001467 std::map<uint32_t, std::set<uint16_t>> dropped_seq_;
1468 const uint32_t& first_media_ssrc_;
1469 const std::map<uint32_t, uint32_t>& rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001470 bool padding_observed_;
1471 bool rtx_padding_observed_;
sprang861c55e2015-10-16 10:01:21 -07001472 bool retransmit_observed_;
1473 bool started_;
sprang867fb522015-08-03 04:38:41 -07001474 };
1475
1476 class TransportSequenceNumberTester : public MultiStreamTest {
1477 public:
sprang861c55e2015-10-16 10:01:21 -07001478 TransportSequenceNumberTester()
1479 : first_media_ssrc_(0), observer_(nullptr) {}
sprang867fb522015-08-03 04:38:41 -07001480 virtual ~TransportSequenceNumberTester() {}
1481
1482 protected:
1483 void Wait() override {
henrikg91d6ede2015-09-17 00:24:34 -07001484 RTC_DCHECK(observer_ != nullptr);
Peter Boström5811a392015-12-10 13:02:50 +01001485 EXPECT_TRUE(observer_->Wait());
sprang867fb522015-08-03 04:38:41 -07001486 }
1487
1488 void UpdateSendConfig(
1489 size_t stream_index,
1490 VideoSendStream::Config* send_config,
1491 VideoEncoderConfig* encoder_config,
1492 test::FrameGeneratorCapturer** frame_generator) override {
1493 send_config->rtp.extensions.clear();
1494 send_config->rtp.extensions.push_back(
1495 RtpExtension(RtpExtension::kTransportSequenceNumber, kExtensionId));
1496
1497 // Force some padding to be sent.
1498 const int kPaddingBitrateBps = 50000;
1499 int total_target_bitrate = 0;
1500 for (const VideoStream& stream : encoder_config->streams)
1501 total_target_bitrate += stream.target_bitrate_bps;
1502 encoder_config->min_transmit_bitrate_bps =
1503 total_target_bitrate + kPaddingBitrateBps;
1504
1505 // Configure RTX for redundant payload padding.
1506 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang861c55e2015-10-16 10:01:21 -07001507 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[stream_index]);
sprang867fb522015-08-03 04:38:41 -07001508 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
sprang861c55e2015-10-16 10:01:21 -07001509 rtx_to_media_ssrcs_[kSendRtxSsrcs[stream_index]] =
1510 send_config->rtp.ssrcs[0];
1511
1512 if (stream_index == 0)
1513 first_media_ssrc_ = send_config->rtp.ssrcs[0];
sprang867fb522015-08-03 04:38:41 -07001514 }
1515
1516 void UpdateReceiveConfig(
1517 size_t stream_index,
1518 VideoReceiveStream::Config* receive_config) override {
sprang861c55e2015-10-16 10:01:21 -07001519 receive_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang867fb522015-08-03 04:38:41 -07001520 receive_config->rtp.extensions.clear();
1521 receive_config->rtp.extensions.push_back(
1522 RtpExtension(RtpExtension::kTransportSequenceNumber, kExtensionId));
1523 }
1524
stefanf116bd02015-10-27 08:29:42 -07001525 test::DirectTransport* CreateSendTransport(Call* sender_call) override {
1526 observer_ = new RtpExtensionHeaderObserver(sender_call, first_media_ssrc_,
sprang861c55e2015-10-16 10:01:21 -07001527 rtx_to_media_ssrcs_);
sprang867fb522015-08-03 04:38:41 -07001528 return observer_;
1529 }
1530
1531 private:
sprang861c55e2015-10-16 10:01:21 -07001532 uint32_t first_media_ssrc_;
1533 std::map<uint32_t, uint32_t> rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001534 RtpExtensionHeaderObserver* observer_;
1535 } tester;
1536
1537 tester.RunTest();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001538}
1539
stefan43edf0f2015-11-20 18:05:48 -08001540void TransportFeedbackTest(bool feedback_enabled) {
Erik Språng6b8d3552015-09-24 15:06:57 +02001541 static const int kExtensionId = 5;
Erik Språng6b8d3552015-09-24 15:06:57 +02001542 class TransportFeedbackObserver : public test::DirectTransport {
1543 public:
stefanf116bd02015-10-27 08:29:42 -07001544 TransportFeedbackObserver(Call* receiver_call, rtc::Event* done_event)
1545 : DirectTransport(receiver_call), done_(done_event) {}
Erik Språng6b8d3552015-09-24 15:06:57 +02001546 virtual ~TransportFeedbackObserver() {}
1547
1548 bool SendRtcp(const uint8_t* data, size_t length) override {
1549 RTCPUtility::RTCPParserV2 parser(data, length, true);
1550 EXPECT_TRUE(parser.IsValid());
1551
1552 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
1553 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
1554 if (packet_type == RTCPUtility::RTCPPacketTypes::kTransportFeedback) {
1555 done_->Set();
1556 break;
1557 }
1558 packet_type = parser.Iterate();
1559 }
1560
1561 return test::DirectTransport::SendRtcp(data, length);
1562 }
1563
1564 rtc::Event* done_;
1565 };
1566
1567 class TransportFeedbackTester : public MultiStreamTest {
1568 public:
stefan43edf0f2015-11-20 18:05:48 -08001569 explicit TransportFeedbackTester(bool feedback_enabled)
1570 : feedback_enabled_(feedback_enabled), done_(false, false) {}
Erik Språng6b8d3552015-09-24 15:06:57 +02001571 virtual ~TransportFeedbackTester() {}
1572
1573 protected:
1574 void Wait() override {
stefan43edf0f2015-11-20 18:05:48 -08001575 const int64_t kDisabledFeedbackTimeoutMs = 5000;
1576 EXPECT_EQ(feedback_enabled_, done_.Wait(feedback_enabled_
1577 ? test::CallTest::kDefaultTimeoutMs
1578 : kDisabledFeedbackTimeoutMs));
Erik Språng6b8d3552015-09-24 15:06:57 +02001579 }
1580
1581 void UpdateSendConfig(
1582 size_t stream_index,
1583 VideoSendStream::Config* send_config,
1584 VideoEncoderConfig* encoder_config,
1585 test::FrameGeneratorCapturer** frame_generator) override {
1586 send_config->rtp.extensions.push_back(
1587 RtpExtension(RtpExtension::kTransportSequenceNumber, kExtensionId));
1588 }
1589
1590 void UpdateReceiveConfig(
1591 size_t stream_index,
1592 VideoReceiveStream::Config* receive_config) override {
1593 receive_config->rtp.extensions.push_back(
1594 RtpExtension(RtpExtension::kTransportSequenceNumber, kExtensionId));
stefan43edf0f2015-11-20 18:05:48 -08001595 receive_config->rtp.transport_cc = feedback_enabled_;
Erik Språng6b8d3552015-09-24 15:06:57 +02001596 }
1597
stefanf116bd02015-10-27 08:29:42 -07001598 test::DirectTransport* CreateReceiveTransport(
1599 Call* receiver_call) override {
1600 return new TransportFeedbackObserver(receiver_call, &done_);
Erik Språng6b8d3552015-09-24 15:06:57 +02001601 }
1602
1603 private:
stefan43edf0f2015-11-20 18:05:48 -08001604 const bool feedback_enabled_;
Erik Språng6b8d3552015-09-24 15:06:57 +02001605 rtc::Event done_;
stefan43edf0f2015-11-20 18:05:48 -08001606 } tester(feedback_enabled);
Erik Språng6b8d3552015-09-24 15:06:57 +02001607 tester.RunTest();
1608}
stefan43edf0f2015-11-20 18:05:48 -08001609
1610TEST_F(EndToEndTest, ReceivesTransportFeedback) {
1611 TransportFeedbackTest(true);
1612}
1613
1614TEST_F(EndToEndTest, TransportFeedbackNotConfigured) {
1615 TransportFeedbackTest(false);
1616}
1617
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001618TEST_F(EndToEndTest, ObserversEncodedFrames) {
1619 class EncodedFrameTestObserver : public EncodedFrameObserver {
1620 public:
1621 EncodedFrameTestObserver()
Peter Boström5811a392015-12-10 13:02:50 +01001622 : length_(0), frame_type_(kEmptyFrame), called_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001623 virtual ~EncodedFrameTestObserver() {}
1624
1625 virtual void EncodedFrameCallback(const EncodedFrame& encoded_frame) {
1626 frame_type_ = encoded_frame.frame_type_;
1627 length_ = encoded_frame.length_;
1628 buffer_.reset(new uint8_t[length_]);
1629 memcpy(buffer_.get(), encoded_frame.data_, length_);
Peter Boström5811a392015-12-10 13:02:50 +01001630 called_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001631 }
1632
Peter Boström5811a392015-12-10 13:02:50 +01001633 bool Wait() { return called_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001634
1635 void ExpectEqualFrames(const EncodedFrameTestObserver& observer) {
1636 ASSERT_EQ(length_, observer.length_)
1637 << "Observed frames are of different lengths.";
1638 EXPECT_EQ(frame_type_, observer.frame_type_)
1639 << "Observed frames have different frame types.";
1640 EXPECT_EQ(0, memcmp(buffer_.get(), observer.buffer_.get(), length_))
1641 << "Observed encoded frames have different content.";
1642 }
1643
1644 private:
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00001645 rtc::scoped_ptr<uint8_t[]> buffer_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001646 size_t length_;
1647 FrameType frame_type_;
Peter Boström5811a392015-12-10 13:02:50 +01001648 rtc::Event called_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001649 };
1650
1651 EncodedFrameTestObserver post_encode_observer;
1652 EncodedFrameTestObserver pre_decode_observer;
1653
solenberg4fbae2b2015-08-28 04:07:10 -07001654 CreateCalls(Call::Config(), Call::Config());
1655
stefanf116bd02015-10-27 08:29:42 -07001656 test::DirectTransport sender_transport(sender_call_.get());
1657 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001658 sender_transport.SetReceiver(receiver_call_->Receiver());
1659 receiver_transport.SetReceiver(sender_call_->Receiver());
1660
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001661 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07001662 CreateMatchingReceiveConfigs(&receiver_transport);
stefanff483612015-12-21 03:14:00 -08001663 video_send_config_.post_encode_callback = &post_encode_observer;
1664 video_receive_configs_[0].pre_decode_callback = &pre_decode_observer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001665
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001666 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001667 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001668
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00001669 rtc::scoped_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +00001670 test::FrameGenerator::CreateChromaGenerator(
stefanff483612015-12-21 03:14:00 -08001671 video_encoder_config_.streams[0].width,
1672 video_encoder_config_.streams[0].height));
1673 video_send_stream_->Input()->IncomingCapturedFrame(
1674 *frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001675
Peter Boström5811a392015-12-10 13:02:50 +01001676 EXPECT_TRUE(post_encode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001677 << "Timed out while waiting for send-side encoded-frame callback.";
1678
Peter Boström5811a392015-12-10 13:02:50 +01001679 EXPECT_TRUE(pre_decode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001680 << "Timed out while waiting for pre-decode encoded-frame callback.";
1681
1682 post_encode_observer.ExpectEqualFrames(pre_decode_observer);
1683
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001684 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001685
1686 sender_transport.StopSending();
1687 receiver_transport.StopSending();
1688
1689 DestroyStreams();
1690}
1691
1692TEST_F(EndToEndTest, ReceiveStreamSendsRemb) {
1693 class RembObserver : public test::EndToEndTest {
1694 public:
1695 RembObserver() : EndToEndTest(kDefaultTimeoutMs) {}
1696
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001697 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001698 RTCPUtility::RTCPParserV2 parser(packet, length, true);
1699 EXPECT_TRUE(parser.IsValid());
1700
1701 bool received_psfb = false;
1702 bool received_remb = false;
1703 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02001704 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
1705 if (packet_type == RTCPUtility::RTCPPacketTypes::kPsfbRemb) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001706 const RTCPUtility::RTCPPacket& packet = parser.Packet();
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001707 EXPECT_EQ(packet.PSFBAPP.SenderSSRC, kReceiverLocalVideoSsrc);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001708 received_psfb = true;
Erik Språng242e22b2015-05-11 10:17:43 +02001709 } else if (packet_type == RTCPUtility::RTCPPacketTypes::kPsfbRembItem) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001710 const RTCPUtility::RTCPPacket& packet = parser.Packet();
1711 EXPECT_GT(packet.REMBItem.BitRate, 0u);
1712 EXPECT_EQ(packet.REMBItem.NumberOfSSRCs, 1u);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001713 EXPECT_EQ(packet.REMBItem.SSRCs[0], kVideoSendSsrcs[0]);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001714 received_remb = true;
1715 }
1716 packet_type = parser.Iterate();
1717 }
1718 if (received_psfb && received_remb)
Peter Boström5811a392015-12-10 13:02:50 +01001719 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001720 return SEND_PACKET;
1721 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001722 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001723 EXPECT_TRUE(Wait()) << "Timed out while waiting for a "
1724 "receiver RTCP REMB packet to be "
1725 "sent.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001726 }
1727 } test;
1728
stefanf116bd02015-10-27 08:29:42 -07001729 RunBaseTest(&test, FakeNetworkPipe::Config());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001730}
1731
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001732TEST_F(EndToEndTest, VerifyBandwidthStats) {
stefanf116bd02015-10-27 08:29:42 -07001733 class RtcpObserver : public test::EndToEndTest {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001734 public:
1735 RtcpObserver()
1736 : EndToEndTest(kDefaultTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00001737 sender_call_(nullptr),
1738 receiver_call_(nullptr),
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001739 has_seen_pacer_delay_(false) {}
1740
stefanf116bd02015-10-27 08:29:42 -07001741 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001742 Call::Stats sender_stats = sender_call_->GetStats();
1743 Call::Stats receiver_stats = receiver_call_->GetStats();
1744 if (!has_seen_pacer_delay_)
1745 has_seen_pacer_delay_ = sender_stats.pacer_delay_ms > 0;
1746 if (sender_stats.send_bandwidth_bps > 0 &&
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00001747 receiver_stats.recv_bandwidth_bps > 0 && has_seen_pacer_delay_) {
Peter Boström5811a392015-12-10 13:02:50 +01001748 observation_complete_.Set();
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00001749 }
stefanf116bd02015-10-27 08:29:42 -07001750 return SEND_PACKET;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001751 }
1752
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001753 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001754 sender_call_ = sender_call;
1755 receiver_call_ = receiver_call;
1756 }
1757
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001758 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001759 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
1760 "non-zero bandwidth stats.";
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001761 }
1762
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001763 private:
1764 Call* sender_call_;
1765 Call* receiver_call_;
1766 bool has_seen_pacer_delay_;
1767 } test;
1768
stefanf116bd02015-10-27 08:29:42 -07001769 RunBaseTest(&test, FakeNetworkPipe::Config());
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001770}
1771
Åsa Persson352b2d72015-04-15 18:00:40 +02001772TEST_F(EndToEndTest, VerifyNackStats) {
1773 static const int kPacketNumberToDrop = 200;
1774 class NackObserver : public test::EndToEndTest {
1775 public:
1776 NackObserver()
1777 : EndToEndTest(kLongTimeoutMs),
1778 sent_rtp_packets_(0),
1779 dropped_rtp_packet_(0),
1780 dropped_rtp_packet_requested_(false),
1781 send_stream_(nullptr),
1782 start_runtime_ms_(-1) {}
1783
1784 private:
1785 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08001786 rtc::CritScope lock(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02001787 if (++sent_rtp_packets_ == kPacketNumberToDrop) {
1788 rtc::scoped_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
1789 RTPHeader header;
1790 EXPECT_TRUE(parser->Parse(packet, length, &header));
1791 dropped_rtp_packet_ = header.sequenceNumber;
1792 return DROP_PACKET;
1793 }
1794 VerifyStats();
1795 return SEND_PACKET;
1796 }
1797
1798 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08001799 rtc::CritScope lock(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02001800 test::RtcpPacketParser rtcp_parser;
1801 rtcp_parser.Parse(packet, length);
1802 std::vector<uint16_t> nacks = rtcp_parser.nack_item()->last_nack_list();
1803 if (!nacks.empty() && std::find(
1804 nacks.begin(), nacks.end(), dropped_rtp_packet_) != nacks.end()) {
1805 dropped_rtp_packet_requested_ = true;
1806 }
1807 return SEND_PACKET;
1808 }
1809
stefan608213e2015-11-01 14:56:10 -08001810 void VerifyStats() EXCLUSIVE_LOCKS_REQUIRED(&crit_) {
Åsa Persson352b2d72015-04-15 18:00:40 +02001811 if (!dropped_rtp_packet_requested_)
1812 return;
1813 int send_stream_nack_packets = 0;
1814 int receive_stream_nack_packets = 0;
1815 VideoSendStream::Stats stats = send_stream_->GetStats();
1816 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
1817 stats.substreams.begin(); it != stats.substreams.end(); ++it) {
1818 const VideoSendStream::StreamStats& stream_stats = it->second;
1819 send_stream_nack_packets +=
1820 stream_stats.rtcp_packet_type_counts.nack_packets;
1821 }
1822 for (size_t i = 0; i < receive_streams_.size(); ++i) {
1823 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
1824 receive_stream_nack_packets +=
1825 stats.rtcp_packet_type_counts.nack_packets;
1826 }
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001827 if (send_stream_nack_packets >= 1 && receive_stream_nack_packets >= 1) {
Åsa Persson352b2d72015-04-15 18:00:40 +02001828 // NACK packet sent on receive stream and received on sent stream.
1829 if (MinMetricRunTimePassed())
Peter Boström5811a392015-12-10 13:02:50 +01001830 observation_complete_.Set();
Åsa Persson352b2d72015-04-15 18:00:40 +02001831 }
1832 }
1833
1834 bool MinMetricRunTimePassed() {
1835 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
1836 if (start_runtime_ms_ == -1) {
1837 start_runtime_ms_ = now;
1838 return false;
1839 }
1840 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
1841 return elapsed_sec > metrics::kMinRunTimeInSeconds;
1842 }
1843
stefanff483612015-12-21 03:14:00 -08001844 void ModifyVideoConfigs(
1845 VideoSendStream::Config* send_config,
1846 std::vector<VideoReceiveStream::Config>* receive_configs,
1847 VideoEncoderConfig* encoder_config) override {
Åsa Persson352b2d72015-04-15 18:00:40 +02001848 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
1849 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
1850 }
1851
stefanff483612015-12-21 03:14:00 -08001852 void OnVideoStreamsCreated(
Åsa Persson352b2d72015-04-15 18:00:40 +02001853 VideoSendStream* send_stream,
1854 const std::vector<VideoReceiveStream*>& receive_streams) override {
1855 send_stream_ = send_stream;
1856 receive_streams_ = receive_streams;
1857 }
1858
1859 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001860 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Åsa Persson352b2d72015-04-15 18:00:40 +02001861 }
1862
stefan608213e2015-11-01 14:56:10 -08001863 rtc::CriticalSection crit_;
Åsa Persson352b2d72015-04-15 18:00:40 +02001864 uint64_t sent_rtp_packets_;
stefan608213e2015-11-01 14:56:10 -08001865 uint16_t dropped_rtp_packet_ GUARDED_BY(&crit_);
1866 bool dropped_rtp_packet_requested_ GUARDED_BY(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02001867 std::vector<VideoReceiveStream*> receive_streams_;
1868 VideoSendStream* send_stream_;
1869 int64_t start_runtime_ms_;
1870 } test;
1871
Åsa Persson3c391cb2015-04-27 10:09:49 +02001872 test::ClearHistograms();
stefanf116bd02015-10-27 08:29:42 -07001873 RunBaseTest(&test, FakeNetworkPipe::Config());
Åsa Persson352b2d72015-04-15 18:00:40 +02001874
Åsa Persson3c391cb2015-04-27 10:09:49 +02001875 EXPECT_EQ(1, test::NumHistogramSamples(
Åsa Persson352b2d72015-04-15 18:00:40 +02001876 "WebRTC.Video.UniqueNackRequestsSentInPercent"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02001877 EXPECT_EQ(1, test::NumHistogramSamples(
Åsa Persson352b2d72015-04-15 18:00:40 +02001878 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
1879 EXPECT_GT(test::LastHistogramSample(
1880 "WebRTC.Video.NackPacketsSentPerMinute"), 0);
1881 EXPECT_GT(test::LastHistogramSample(
1882 "WebRTC.Video.NackPacketsReceivedPerMinute"), 0);
1883}
1884
sprangb4a1ae52015-12-03 08:10:08 -08001885void EndToEndTest::VerifyHistogramStats(bool use_rtx,
1886 bool use_red,
1887 bool screenshare) {
stefanf116bd02015-10-27 08:29:42 -07001888 class StatsObserver : public test::EndToEndTest {
Åsa Persson3c391cb2015-04-27 10:09:49 +02001889 public:
sprangb4a1ae52015-12-03 08:10:08 -08001890 StatsObserver(bool use_rtx, bool use_red, bool screenshare)
Åsa Persson3c391cb2015-04-27 10:09:49 +02001891 : EndToEndTest(kLongTimeoutMs),
1892 use_rtx_(use_rtx),
1893 use_red_(use_red),
sprangb4a1ae52015-12-03 08:10:08 -08001894 screenshare_(screenshare),
Åsa Persson3c391cb2015-04-27 10:09:49 +02001895 sender_call_(nullptr),
1896 receiver_call_(nullptr),
1897 start_runtime_ms_(-1) {}
1898
1899 private:
1900 Action OnSendRtp(const uint8_t* packet, size_t length) override {
1901 if (MinMetricRunTimePassed())
Peter Boström5811a392015-12-10 13:02:50 +01001902 observation_complete_.Set();
Åsa Persson3c391cb2015-04-27 10:09:49 +02001903
Åsa Persson3c391cb2015-04-27 10:09:49 +02001904 // GetStats calls GetSendChannelRtcpStatistics
1905 // (via VideoSendStream::GetRtt) which updates ReportBlockStats used by
1906 // WebRTC.Video.SentPacketsLostInPercent.
1907 // TODO(asapersson): Remove dependency on calling GetStats.
1908 sender_call_->GetStats();
stefanf116bd02015-10-27 08:29:42 -07001909
1910 return SEND_PACKET;
Åsa Persson3c391cb2015-04-27 10:09:49 +02001911 }
1912
1913 bool MinMetricRunTimePassed() {
1914 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
1915 if (start_runtime_ms_ == -1) {
1916 start_runtime_ms_ = now;
1917 return false;
1918 }
1919 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
1920 return elapsed_sec > metrics::kMinRunTimeInSeconds * 2;
1921 }
1922
stefanff483612015-12-21 03:14:00 -08001923 void ModifyVideoConfigs(
1924 VideoSendStream::Config* send_config,
1925 std::vector<VideoReceiveStream::Config>* receive_configs,
1926 VideoEncoderConfig* encoder_config) override {
Åsa Persson3c391cb2015-04-27 10:09:49 +02001927 // NACK
1928 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
1929 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
1930 // FEC
1931 if (use_red_) {
1932 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
1933 send_config->rtp.fec.red_payload_type = kRedPayloadType;
1934 (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
1935 (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
1936 }
1937 // RTX
1938 if (use_rtx_) {
1939 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
1940 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001941 (*receive_configs)[0].rtp.rtx[kFakeVideoSendPayloadType].ssrc =
Åsa Persson3c391cb2015-04-27 10:09:49 +02001942 kSendRtxSsrcs[0];
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001943 (*receive_configs)[0].rtp.rtx[kFakeVideoSendPayloadType].payload_type =
Åsa Persson3c391cb2015-04-27 10:09:49 +02001944 kSendRtxPayloadType;
1945 }
sprangb4a1ae52015-12-03 08:10:08 -08001946 encoder_config->content_type =
1947 screenshare_ ? VideoEncoderConfig::ContentType::kScreen
1948 : VideoEncoderConfig::ContentType::kRealtimeVideo;
Åsa Persson3c391cb2015-04-27 10:09:49 +02001949 }
1950
1951 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
1952 sender_call_ = sender_call;
1953 receiver_call_ = receiver_call;
1954 }
1955
Åsa Persson3c391cb2015-04-27 10:09:49 +02001956 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001957 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Åsa Persson3c391cb2015-04-27 10:09:49 +02001958 }
1959
sprangb4a1ae52015-12-03 08:10:08 -08001960 const bool use_rtx_;
1961 const bool use_red_;
1962 const bool screenshare_;
Åsa Persson3c391cb2015-04-27 10:09:49 +02001963 Call* sender_call_;
1964 Call* receiver_call_;
1965 int64_t start_runtime_ms_;
sprangb4a1ae52015-12-03 08:10:08 -08001966 } test(use_rtx, use_red, screenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02001967
1968 test::ClearHistograms();
stefanf116bd02015-10-27 08:29:42 -07001969 RunBaseTest(&test, FakeNetworkPipe::Config());
Åsa Persson3c391cb2015-04-27 10:09:49 +02001970
stefan91d92602015-11-11 10:13:02 -08001971 // Delete the call for Call stats to be reported.
stefan18adf0a2015-11-17 06:24:56 -08001972 sender_call_.reset();
stefan91d92602015-11-11 10:13:02 -08001973 receiver_call_.reset();
1974
sprangb4a1ae52015-12-03 08:10:08 -08001975 std::string video_prefix =
1976 screenshare ? "WebRTC.Video.Screenshare." : "WebRTC.Video.";
1977
Åsa Persson3c391cb2015-04-27 10:09:49 +02001978 // Verify that stats have been updated once.
stefan91d92602015-11-11 10:13:02 -08001979 EXPECT_EQ(
1980 1, test::NumHistogramSamples("WebRTC.Call.VideoBitrateReceivedInKbps"));
1981 EXPECT_EQ(1,
1982 test::NumHistogramSamples("WebRTC.Call.RtcpBitrateReceivedInBps"));
1983 EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Call.BitrateReceivedInKbps"));
stefan18adf0a2015-11-17 06:24:56 -08001984 EXPECT_EQ(
1985 1, test::NumHistogramSamples("WebRTC.Call.EstimatedSendBitrateInKbps"));
1986 EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Call.PacerBitrateInKbps"));
stefan91d92602015-11-11 10:13:02 -08001987
Åsa Persson3c391cb2015-04-27 10:09:49 +02001988 EXPECT_EQ(1, test::NumHistogramSamples(
1989 "WebRTC.Video.NackPacketsSentPerMinute"));
1990 EXPECT_EQ(1, test::NumHistogramSamples(
1991 "WebRTC.Video.NackPacketsReceivedPerMinute"));
1992 EXPECT_EQ(1, test::NumHistogramSamples(
1993 "WebRTC.Video.FirPacketsSentPerMinute"));
1994 EXPECT_EQ(1, test::NumHistogramSamples(
1995 "WebRTC.Video.FirPacketsReceivedPerMinute"));
1996 EXPECT_EQ(1, test::NumHistogramSamples(
1997 "WebRTC.Video.PliPacketsSentPerMinute"));
1998 EXPECT_EQ(1, test::NumHistogramSamples(
1999 "WebRTC.Video.PliPacketsReceivedPerMinute"));
2000
sprangb4a1ae52015-12-03 08:10:08 -08002001 EXPECT_EQ(
2002 1, test::NumHistogramSamples(video_prefix + "KeyFramesSentInPermille"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002003 EXPECT_EQ(1, test::NumHistogramSamples(
2004 "WebRTC.Video.KeyFramesReceivedInPermille"));
2005
2006 EXPECT_EQ(1, test::NumHistogramSamples(
2007 "WebRTC.Video.SentPacketsLostInPercent"));
2008 EXPECT_EQ(1, test::NumHistogramSamples(
2009 "WebRTC.Video.ReceivedPacketsLostInPercent"));
2010
sprangb4a1ae52015-12-03 08:10:08 -08002011 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "InputWidthInPixels"));
2012 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "InputHeightInPixels"));
2013 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "SentWidthInPixels"));
2014 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "SentHeightInPixels"));
asaperssond89920b2015-07-22 06:52:00 -07002015 EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.ReceivedWidthInPixels"));
2016 EXPECT_EQ(1,
2017 test::NumHistogramSamples("WebRTC.Video.ReceivedHeightInPixels"));
2018
stefanff483612015-12-21 03:14:00 -08002019 EXPECT_EQ(static_cast<int>(video_encoder_config_.streams[0].width),
sprangb4a1ae52015-12-03 08:10:08 -08002020 test::LastHistogramSample(video_prefix + "InputWidthInPixels"));
stefanff483612015-12-21 03:14:00 -08002021 EXPECT_EQ(static_cast<int>(video_encoder_config_.streams[0].height),
sprangb4a1ae52015-12-03 08:10:08 -08002022 test::LastHistogramSample(video_prefix + "InputHeightInPixels"));
stefanff483612015-12-21 03:14:00 -08002023 EXPECT_EQ(static_cast<int>(video_encoder_config_.streams[0].width),
sprangb4a1ae52015-12-03 08:10:08 -08002024 test::LastHistogramSample(video_prefix + "SentWidthInPixels"));
stefanff483612015-12-21 03:14:00 -08002025 EXPECT_EQ(static_cast<int>(video_encoder_config_.streams[0].height),
sprangb4a1ae52015-12-03 08:10:08 -08002026 test::LastHistogramSample(video_prefix + "SentHeightInPixels"));
stefanff483612015-12-21 03:14:00 -08002027 EXPECT_EQ(static_cast<int>(video_encoder_config_.streams[0].width),
asaperssond89920b2015-07-22 06:52:00 -07002028 test::LastHistogramSample("WebRTC.Video.ReceivedWidthInPixels"));
stefanff483612015-12-21 03:14:00 -08002029 EXPECT_EQ(static_cast<int>(video_encoder_config_.streams[0].height),
asaperssond89920b2015-07-22 06:52:00 -07002030 test::LastHistogramSample("WebRTC.Video.ReceivedHeightInPixels"));
2031
sprangb4a1ae52015-12-03 08:10:08 -08002032 EXPECT_EQ(1,
2033 test::NumHistogramSamples(video_prefix + "InputFramesPerSecond"));
2034 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "SentFramesPerSecond"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002035 EXPECT_EQ(1, test::NumHistogramSamples(
2036 "WebRTC.Video.DecodedFramesPerSecond"));
asaperssond89920b2015-07-22 06:52:00 -07002037 EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.RenderFramesPerSecond"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002038
asapersson6f14be82015-11-16 00:40:49 -08002039 EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.OnewayDelayInMs"));
2040 EXPECT_EQ(
2041 1, test::NumHistogramSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
2042
sprangb4a1ae52015-12-03 08:10:08 -08002043 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "EncodeTimeInMs"));
asapersson6718e972015-07-24 00:20:58 -07002044 EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.DecodeTimeInMs"));
2045
Åsa Persson3c391cb2015-04-27 10:09:49 +02002046 EXPECT_EQ(1, test::NumHistogramSamples(
2047 "WebRTC.Video.BitrateSentInKbps"));
2048 EXPECT_EQ(1, test::NumHistogramSamples(
2049 "WebRTC.Video.BitrateReceivedInKbps"));
2050 EXPECT_EQ(1, test::NumHistogramSamples(
2051 "WebRTC.Video.MediaBitrateSentInKbps"));
2052 EXPECT_EQ(1, test::NumHistogramSamples(
2053 "WebRTC.Video.MediaBitrateReceivedInKbps"));
2054 EXPECT_EQ(1, test::NumHistogramSamples(
2055 "WebRTC.Video.PaddingBitrateSentInKbps"));
2056 EXPECT_EQ(1, test::NumHistogramSamples(
2057 "WebRTC.Video.PaddingBitrateReceivedInKbps"));
2058 EXPECT_EQ(1, test::NumHistogramSamples(
2059 "WebRTC.Video.RetransmittedBitrateSentInKbps"));
2060 EXPECT_EQ(1, test::NumHistogramSamples(
2061 "WebRTC.Video.RetransmittedBitrateReceivedInKbps"));
2062
sprangb4a1ae52015-12-03 08:10:08 -08002063 EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "SendSideDelayInMs"));
2064 EXPECT_EQ(1,
2065 test::NumHistogramSamples(video_prefix + "SendSideDelayMaxInMs"));
asapersson6f14be82015-11-16 00:40:49 -08002066
Åsa Persson3c391cb2015-04-27 10:09:49 +02002067 int num_rtx_samples = use_rtx ? 1 : 0;
2068 EXPECT_EQ(num_rtx_samples, test::NumHistogramSamples(
2069 "WebRTC.Video.RtxBitrateSentInKbps"));
2070 EXPECT_EQ(num_rtx_samples, test::NumHistogramSamples(
2071 "WebRTC.Video.RtxBitrateReceivedInKbps"));
2072
2073 int num_red_samples = use_red ? 1 : 0;
2074 EXPECT_EQ(num_red_samples, test::NumHistogramSamples(
2075 "WebRTC.Video.FecBitrateSentInKbps"));
2076 EXPECT_EQ(num_red_samples, test::NumHistogramSamples(
2077 "WebRTC.Video.FecBitrateReceivedInKbps"));
2078 EXPECT_EQ(num_red_samples, test::NumHistogramSamples(
2079 "WebRTC.Video.ReceivedFecPacketsInPercent"));
2080}
2081
2082TEST_F(EndToEndTest, VerifyHistogramStatsWithRtx) {
2083 const bool kEnabledRtx = true;
2084 const bool kEnabledRed = false;
sprangb4a1ae52015-12-03 08:10:08 -08002085 const bool kScreenshare = false;
2086 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002087}
2088
2089TEST_F(EndToEndTest, VerifyHistogramStatsWithRed) {
2090 const bool kEnabledRtx = false;
2091 const bool kEnabledRed = true;
sprangb4a1ae52015-12-03 08:10:08 -08002092 const bool kScreenshare = false;
2093 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
2094}
2095
2096TEST_F(EndToEndTest, VerifyHistogramStatsWithScreenshare) {
2097 const bool kEnabledRtx = false;
2098 const bool kEnabledRed = false;
2099 const bool kScreenshare = true;
2100 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002101}
2102
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002103void EndToEndTest::TestXrReceiverReferenceTimeReport(bool enable_rrtr) {
2104 static const int kNumRtcpReportPacketsToObserve = 5;
2105 class RtcpXrObserver : public test::EndToEndTest {
2106 public:
2107 explicit RtcpXrObserver(bool enable_rrtr)
2108 : EndToEndTest(kDefaultTimeoutMs),
2109 enable_rrtr_(enable_rrtr),
2110 sent_rtcp_sr_(0),
2111 sent_rtcp_rr_(0),
2112 sent_rtcp_rrtr_(0),
2113 sent_rtcp_dlrr_(0) {}
2114
2115 private:
2116 // Receive stream should send RR packets (and RRTR packets if enabled).
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002117 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002118 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002119 RTCPUtility::RTCPParserV2 parser(packet, length, true);
2120 EXPECT_TRUE(parser.IsValid());
2121
2122 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02002123 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
2124 if (packet_type == RTCPUtility::RTCPPacketTypes::kRr) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002125 ++sent_rtcp_rr_;
2126 } else if (packet_type ==
Erik Språng242e22b2015-05-11 10:17:43 +02002127 RTCPUtility::RTCPPacketTypes::kXrReceiverReferenceTime) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002128 ++sent_rtcp_rrtr_;
2129 }
Erik Språng242e22b2015-05-11 10:17:43 +02002130 EXPECT_NE(packet_type, RTCPUtility::RTCPPacketTypes::kSr);
2131 EXPECT_NE(packet_type,
2132 RTCPUtility::RTCPPacketTypes::kXrDlrrReportBlockItem);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002133 packet_type = parser.Iterate();
2134 }
2135 return SEND_PACKET;
2136 }
2137 // Send stream should send SR packets (and DLRR packets if enabled).
2138 virtual Action OnSendRtcp(const uint8_t* packet, size_t length) {
stefan608213e2015-11-01 14:56:10 -08002139 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002140 RTCPUtility::RTCPParserV2 parser(packet, length, true);
2141 EXPECT_TRUE(parser.IsValid());
2142
2143 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02002144 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
2145 if (packet_type == RTCPUtility::RTCPPacketTypes::kSr) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002146 ++sent_rtcp_sr_;
Erik Språng242e22b2015-05-11 10:17:43 +02002147 } else if (packet_type ==
2148 RTCPUtility::RTCPPacketTypes::kXrDlrrReportBlockItem) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002149 ++sent_rtcp_dlrr_;
2150 }
Erik Språng242e22b2015-05-11 10:17:43 +02002151 EXPECT_NE(packet_type,
2152 RTCPUtility::RTCPPacketTypes::kXrReceiverReferenceTime);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002153 packet_type = parser.Iterate();
2154 }
2155 if (sent_rtcp_sr_ > kNumRtcpReportPacketsToObserve &&
2156 sent_rtcp_rr_ > kNumRtcpReportPacketsToObserve) {
2157 if (enable_rrtr_) {
2158 EXPECT_GT(sent_rtcp_rrtr_, 0);
2159 EXPECT_GT(sent_rtcp_dlrr_, 0);
2160 } else {
2161 EXPECT_EQ(0, sent_rtcp_rrtr_);
2162 EXPECT_EQ(0, sent_rtcp_dlrr_);
2163 }
Peter Boström5811a392015-12-10 13:02:50 +01002164 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002165 }
2166 return SEND_PACKET;
2167 }
2168
stefanff483612015-12-21 03:14:00 -08002169 void ModifyVideoConfigs(
2170 VideoSendStream::Config* send_config,
2171 std::vector<VideoReceiveStream::Config>* receive_configs,
2172 VideoEncoderConfig* encoder_config) override {
pbosda903ea2015-10-02 02:36:56 -07002173 (*receive_configs)[0].rtp.rtcp_mode = RtcpMode::kReducedSize;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002174 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report =
2175 enable_rrtr_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002176 }
2177
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002178 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002179 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002180 << "Timed out while waiting for RTCP SR/RR packets to be sent.";
2181 }
2182
stefan608213e2015-11-01 14:56:10 -08002183 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002184 bool enable_rrtr_;
2185 int sent_rtcp_sr_;
stefan608213e2015-11-01 14:56:10 -08002186 int sent_rtcp_rr_ GUARDED_BY(&crit_);
2187 int sent_rtcp_rrtr_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002188 int sent_rtcp_dlrr_;
2189 } test(enable_rrtr);
2190
stefanf116bd02015-10-27 08:29:42 -07002191 RunBaseTest(&test, FakeNetworkPipe::Config());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002192}
2193
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002194void EndToEndTest::TestSendsSetSsrcs(size_t num_ssrcs,
2195 bool send_single_ssrc_first) {
2196 class SendsSetSsrcs : public test::EndToEndTest {
2197 public:
2198 SendsSetSsrcs(const uint32_t* ssrcs,
2199 size_t num_ssrcs,
2200 bool send_single_ssrc_first)
2201 : EndToEndTest(kDefaultTimeoutMs),
2202 num_ssrcs_(num_ssrcs),
2203 send_single_ssrc_first_(send_single_ssrc_first),
2204 ssrcs_to_observe_(num_ssrcs),
sprang867fb522015-08-03 04:38:41 -07002205 expect_single_ssrc_(send_single_ssrc_first),
2206 send_stream_(nullptr) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002207 for (size_t i = 0; i < num_ssrcs; ++i)
2208 valid_ssrcs_[ssrcs[i]] = true;
2209 }
2210
2211 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002212 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002213 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002214 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002215
2216 EXPECT_TRUE(valid_ssrcs_[header.ssrc])
2217 << "Received unknown SSRC: " << header.ssrc;
2218
2219 if (!valid_ssrcs_[header.ssrc])
Peter Boström5811a392015-12-10 13:02:50 +01002220 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002221
2222 if (!is_observed_[header.ssrc]) {
2223 is_observed_[header.ssrc] = true;
2224 --ssrcs_to_observe_;
2225 if (expect_single_ssrc_) {
2226 expect_single_ssrc_ = false;
Peter Boström5811a392015-12-10 13:02:50 +01002227 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002228 }
2229 }
2230
2231 if (ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01002232 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002233
2234 return SEND_PACKET;
2235 }
2236
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002237 size_t GetNumVideoStreams() const override { return num_ssrcs_; }
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002238
stefanff483612015-12-21 03:14:00 -08002239 void ModifyVideoConfigs(
2240 VideoSendStream::Config* send_config,
2241 std::vector<VideoReceiveStream::Config>* receive_configs,
2242 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002243 if (num_ssrcs_ > 1) {
2244 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002245 for (size_t i = 0; i < encoder_config->streams.size(); ++i) {
2246 encoder_config->streams[i].min_bitrate_bps = 10000;
2247 encoder_config->streams[i].target_bitrate_bps = 15000;
2248 encoder_config->streams[i].max_bitrate_bps = 20000;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002249 }
2250 }
2251
stefanff483612015-12-21 03:14:00 -08002252 video_encoder_config_all_streams_ = *encoder_config;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002253 if (send_single_ssrc_first_)
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002254 encoder_config->streams.resize(1);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002255 }
2256
stefanff483612015-12-21 03:14:00 -08002257 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002258 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002259 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002260 send_stream_ = send_stream;
2261 }
2262
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002263 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002264 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
2265 << (send_single_ssrc_first_ ? "first SSRC."
2266 : "SSRCs.");
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002267
2268 if (send_single_ssrc_first_) {
2269 // Set full simulcast and continue with the rest of the SSRCs.
stefanff483612015-12-21 03:14:00 -08002270 send_stream_->ReconfigureVideoEncoder(
2271 video_encoder_config_all_streams_);
Peter Boström5811a392015-12-10 13:02:50 +01002272 EXPECT_TRUE(Wait()) << "Timed out while waiting on additional SSRCs.";
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002273 }
2274 }
2275
2276 private:
2277 std::map<uint32_t, bool> valid_ssrcs_;
2278 std::map<uint32_t, bool> is_observed_;
2279
2280 const size_t num_ssrcs_;
2281 const bool send_single_ssrc_first_;
2282
2283 size_t ssrcs_to_observe_;
2284 bool expect_single_ssrc_;
2285
2286 VideoSendStream* send_stream_;
stefanff483612015-12-21 03:14:00 -08002287 VideoEncoderConfig video_encoder_config_all_streams_;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002288 } test(kVideoSendSsrcs, num_ssrcs, send_single_ssrc_first);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002289
stefanf116bd02015-10-27 08:29:42 -07002290 RunBaseTest(&test, FakeNetworkPipe::Config());
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002291}
2292
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002293TEST_F(EndToEndTest, ReportsSetEncoderRates) {
2294 class EncoderRateStatsTest : public test::EndToEndTest,
2295 public test::FakeEncoder {
2296 public:
2297 EncoderRateStatsTest()
2298 : EndToEndTest(kDefaultTimeoutMs),
sprang867fb522015-08-03 04:38:41 -07002299 FakeEncoder(Clock::GetRealTimeClock()),
2300 send_stream_(nullptr),
2301 bitrate_kbps_(0) {}
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002302
stefanff483612015-12-21 03:14:00 -08002303 void OnVideoStreamsCreated(
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002304 VideoSendStream* send_stream,
2305 const std::vector<VideoReceiveStream*>& receive_streams) override {
2306 send_stream_ = send_stream;
2307 }
2308
stefanff483612015-12-21 03:14:00 -08002309 void ModifyVideoConfigs(
2310 VideoSendStream::Config* send_config,
2311 std::vector<VideoReceiveStream::Config>* receive_configs,
2312 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002313 send_config->encoder_settings.encoder = this;
2314 }
2315
2316 int32_t SetRates(uint32_t new_target_bitrate, uint32_t framerate) override {
2317 // Make sure not to trigger on any default zero bitrates.
2318 if (new_target_bitrate == 0)
2319 return 0;
Peter Boströmf2f82832015-05-01 13:00:41 +02002320 rtc::CritScope lock(&crit_);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002321 bitrate_kbps_ = new_target_bitrate;
Peter Boström5811a392015-12-10 13:02:50 +01002322 observation_complete_.Set();
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002323 return 0;
2324 }
2325
2326 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002327 ASSERT_TRUE(Wait())
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002328 << "Timed out while waiting for encoder SetRates() call.";
2329 // Wait for GetStats to report a corresponding bitrate.
Peter Boström5811a392015-12-10 13:02:50 +01002330 for (int i = 0; i < kDefaultTimeoutMs; ++i) {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002331 VideoSendStream::Stats stats = send_stream_->GetStats();
2332 {
Peter Boströmf2f82832015-05-01 13:00:41 +02002333 rtc::CritScope lock(&crit_);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002334 if ((stats.target_media_bitrate_bps + 500) / 1000 ==
2335 static_cast<int>(bitrate_kbps_)) {
2336 return;
2337 }
2338 }
2339 SleepMs(1);
2340 }
2341 FAIL()
2342 << "Timed out waiting for stats reporting the currently set bitrate.";
2343 }
2344
2345 private:
stefanf116bd02015-10-27 08:29:42 -07002346 rtc::CriticalSection crit_;
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002347 VideoSendStream* send_stream_;
2348 uint32_t bitrate_kbps_ GUARDED_BY(crit_);
2349 } test;
2350
stefanf116bd02015-10-27 08:29:42 -07002351 RunBaseTest(&test, FakeNetworkPipe::Config());
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002352}
2353
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002354TEST_F(EndToEndTest, GetStats) {
2355 static const int kStartBitrateBps = 3000000;
Peter Boströmdef398832015-05-27 17:59:11 +02002356 static const int kExpectedRenderDelayMs = 20;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002357 class StatsObserver : public test::EndToEndTest, public I420FrameCallback {
2358 public:
stefanf116bd02015-10-27 08:29:42 -07002359 StatsObserver()
2360 : EndToEndTest(kLongTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00002361 send_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002362 expected_send_ssrcs_(),
Peter Boström5811a392015-12-10 13:02:50 +01002363 check_stats_event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002364
2365 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002366 Action OnSendRtp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002367 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002368 return SEND_PACKET;
2369 }
2370
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002371 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002372 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002373 return SEND_PACKET;
2374 }
2375
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002376 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002377 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002378 return SEND_PACKET;
2379 }
2380
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002381 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002382 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002383 return SEND_PACKET;
2384 }
2385
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07002386 void FrameCallback(VideoFrame* video_frame) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002387 // Ensure that we have at least 5ms send side delay.
2388 int64_t render_time = video_frame->render_time_ms();
2389 if (render_time > 0)
2390 video_frame->set_render_time_ms(render_time - 5);
2391 }
2392
2393 bool CheckReceiveStats() {
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002394 for (size_t i = 0; i < receive_streams_.size(); ++i) {
2395 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
2396 EXPECT_EQ(expected_receive_ssrcs_[i], stats.ssrc);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002397
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002398 // Make sure all fields have been populated.
2399 // TODO(pbos): Use CompoundKey if/when we ever know that all stats are
2400 // always filled for all receivers.
2401 receive_stats_filled_["IncomingRate"] |=
2402 stats.network_frame_rate != 0 || stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002403
Peter Boströmb7d9a972015-12-18 16:01:11 +01002404 send_stats_filled_["DecoderImplementationName"] |=
2405 stats.decoder_implementation_name ==
2406 test::FakeDecoder::kImplementationName;
Peter Boströmdef398832015-05-27 17:59:11 +02002407 receive_stats_filled_["RenderDelayAsHighAsExpected"] |=
2408 stats.render_delay_ms >= kExpectedRenderDelayMs;
2409
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002410 receive_stats_filled_["FrameCallback"] |= stats.decode_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002411
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002412 receive_stats_filled_["FrameRendered"] |= stats.render_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002413
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002414 receive_stats_filled_["StatisticsUpdated"] |=
2415 stats.rtcp_stats.cumulative_lost != 0 ||
2416 stats.rtcp_stats.extended_max_sequence_number != 0 ||
2417 stats.rtcp_stats.fraction_lost != 0 || stats.rtcp_stats.jitter != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002418
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002419 receive_stats_filled_["DataCountersUpdated"] |=
2420 stats.rtp_stats.transmitted.payload_bytes != 0 ||
2421 stats.rtp_stats.fec.packets != 0 ||
2422 stats.rtp_stats.transmitted.header_bytes != 0 ||
2423 stats.rtp_stats.transmitted.packets != 0 ||
2424 stats.rtp_stats.transmitted.padding_bytes != 0 ||
2425 stats.rtp_stats.retransmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002426
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002427 receive_stats_filled_["CodecStats"] |=
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002428 stats.target_delay_ms != 0 || stats.discarded_packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002429
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002430 receive_stats_filled_["FrameCounts"] |=
2431 stats.frame_counts.key_frames != 0 ||
2432 stats.frame_counts.delta_frames != 0;
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002433
pbosbb36fdf2015-07-09 07:48:14 -07002434 receive_stats_filled_["CName"] |= !stats.c_name.empty();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002435
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002436 receive_stats_filled_["RtcpPacketTypeCount"] |=
2437 stats.rtcp_packet_type_counts.fir_packets != 0 ||
2438 stats.rtcp_packet_type_counts.nack_packets != 0 ||
2439 stats.rtcp_packet_type_counts.pli_packets != 0 ||
2440 stats.rtcp_packet_type_counts.nack_requests != 0 ||
2441 stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbosf42376c2015-08-28 07:35:32 -07002442
2443 assert(stats.current_payload_type == -1 ||
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002444 stats.current_payload_type == kFakeVideoSendPayloadType);
pbosf42376c2015-08-28 07:35:32 -07002445 receive_stats_filled_["IncomingPayloadType"] |=
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002446 stats.current_payload_type == kFakeVideoSendPayloadType;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002447 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002448
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002449 return AllStatsFilled(receive_stats_filled_);
2450 }
2451
2452 bool CheckSendStats() {
henrikg91d6ede2015-09-17 00:24:34 -07002453 RTC_DCHECK(send_stream_ != nullptr);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002454 VideoSendStream::Stats stats = send_stream_->GetStats();
2455
2456 send_stats_filled_["NumStreams"] |=
2457 stats.substreams.size() == expected_send_ssrcs_.size();
2458
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00002459 send_stats_filled_["CpuOveruseMetrics"] |=
2460 stats.avg_encode_time_ms != 0 || stats.encode_usage_percent != 0;
2461
Peter Boströmb7d9a972015-12-18 16:01:11 +01002462 send_stats_filled_["EncoderImplementationName"] |=
2463 stats.encoder_implementation_name ==
2464 test::FakeEncoder::kImplementationName;
2465
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002466 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002467 stats.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002468 it != stats.substreams.end(); ++it) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002469 EXPECT_TRUE(expected_send_ssrcs_.find(it->first) !=
2470 expected_send_ssrcs_.end());
2471
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002472 send_stats_filled_[CompoundKey("CapturedFrameRate", it->first)] |=
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002473 stats.input_frame_rate != 0;
2474
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002475 const VideoSendStream::StreamStats& stream_stats = it->second;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002476
2477 send_stats_filled_[CompoundKey("StatisticsUpdated", it->first)] |=
2478 stream_stats.rtcp_stats.cumulative_lost != 0 ||
2479 stream_stats.rtcp_stats.extended_max_sequence_number != 0 ||
2480 stream_stats.rtcp_stats.fraction_lost != 0;
2481
2482 send_stats_filled_[CompoundKey("DataCountersUpdated", it->first)] |=
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00002483 stream_stats.rtp_stats.fec.packets != 0 ||
2484 stream_stats.rtp_stats.transmitted.padding_bytes != 0 ||
2485 stream_stats.rtp_stats.retransmitted.packets != 0 ||
2486 stream_stats.rtp_stats.transmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002487
2488 send_stats_filled_[CompoundKey("BitrateStatisticsObserver",
2489 it->first)] |=
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002490 stream_stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002491
2492 send_stats_filled_[CompoundKey("FrameCountObserver", it->first)] |=
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002493 stream_stats.frame_counts.delta_frames != 0 ||
2494 stream_stats.frame_counts.key_frames != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002495
2496 send_stats_filled_[CompoundKey("OutgoingRate", it->first)] |=
2497 stats.encode_frame_rate != 0;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +00002498
2499 send_stats_filled_[CompoundKey("Delay", it->first)] |=
2500 stream_stats.avg_delay_ms != 0 || stream_stats.max_delay_ms != 0;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002501
2502 // TODO(pbos): Use CompoundKey when the test makes sure that all SSRCs
2503 // report dropped packets.
2504 send_stats_filled_["RtcpPacketTypeCount"] |=
2505 stream_stats.rtcp_packet_type_counts.fir_packets != 0 ||
2506 stream_stats.rtcp_packet_type_counts.nack_packets != 0 ||
2507 stream_stats.rtcp_packet_type_counts.pli_packets != 0 ||
2508 stream_stats.rtcp_packet_type_counts.nack_requests != 0 ||
2509 stream_stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002510 }
2511
2512 return AllStatsFilled(send_stats_filled_);
2513 }
2514
2515 std::string CompoundKey(const char* name, uint32_t ssrc) {
2516 std::ostringstream oss;
2517 oss << name << "_" << ssrc;
2518 return oss.str();
2519 }
2520
2521 bool AllStatsFilled(const std::map<std::string, bool>& stats_map) {
2522 for (std::map<std::string, bool>::const_iterator it = stats_map.begin();
2523 it != stats_map.end();
2524 ++it) {
2525 if (!it->second)
2526 return false;
2527 }
2528 return true;
2529 }
2530
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002531 Call::Config GetSenderCallConfig() override {
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002532 Call::Config config = EndToEndTest::GetSenderCallConfig();
Stefan Holmere5904162015-03-26 11:11:06 +01002533 config.bitrate_config.start_bitrate_bps = kStartBitrateBps;
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002534 return config;
2535 }
2536
stefanff483612015-12-21 03:14:00 -08002537 void ModifyVideoConfigs(
2538 VideoSendStream::Config* send_config,
2539 std::vector<VideoReceiveStream::Config>* receive_configs,
2540 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002541 send_config->pre_encode_callback = this; // Used to inject delay.
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002542 expected_cname_ = send_config->rtp.c_name = "SomeCName";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002543
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002544 const std::vector<uint32_t>& ssrcs = send_config->rtp.ssrcs;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002545 for (size_t i = 0; i < ssrcs.size(); ++i) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002546 expected_send_ssrcs_.insert(ssrcs[i]);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002547 expected_receive_ssrcs_.push_back(
2548 (*receive_configs)[i].rtp.remote_ssrc);
Peter Boströmdef398832015-05-27 17:59:11 +02002549 (*receive_configs)[i].render_delay_ms = kExpectedRenderDelayMs;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002550 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002551 }
2552
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002553 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.orgece38902014-11-14 11:52:04 +00002554
stefanff483612015-12-21 03:14:00 -08002555 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002556 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002557 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002558 send_stream_ = send_stream;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002559 receive_streams_ = receive_streams;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002560 }
2561
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002562 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002563 Clock* clock = Clock::GetRealTimeClock();
2564 int64_t now = clock->TimeInMilliseconds();
2565 int64_t stop_time = now + test::CallTest::kLongTimeoutMs;
2566 bool receive_ok = false;
2567 bool send_ok = false;
2568
2569 while (now < stop_time) {
2570 if (!receive_ok)
2571 receive_ok = CheckReceiveStats();
2572 if (!send_ok)
2573 send_ok = CheckSendStats();
2574
2575 if (receive_ok && send_ok)
2576 return;
2577
2578 int64_t time_until_timout_ = stop_time - now;
2579 if (time_until_timout_ > 0)
Peter Boström5811a392015-12-10 13:02:50 +01002580 check_stats_event_.Wait(time_until_timout_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002581 now = clock->TimeInMilliseconds();
2582 }
2583
2584 ADD_FAILURE() << "Timed out waiting for filled stats.";
2585 for (std::map<std::string, bool>::const_iterator it =
2586 receive_stats_filled_.begin();
2587 it != receive_stats_filled_.end();
2588 ++it) {
2589 if (!it->second) {
2590 ADD_FAILURE() << "Missing receive stats: " << it->first;
2591 }
2592 }
2593
2594 for (std::map<std::string, bool>::const_iterator it =
2595 send_stats_filled_.begin();
2596 it != send_stats_filled_.end();
2597 ++it) {
2598 if (!it->second) {
2599 ADD_FAILURE() << "Missing send stats: " << it->first;
2600 }
2601 }
2602 }
2603
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002604 std::vector<VideoReceiveStream*> receive_streams_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002605 std::map<std::string, bool> receive_stats_filled_;
2606
2607 VideoSendStream* send_stream_;
2608 std::map<std::string, bool> send_stats_filled_;
2609
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002610 std::vector<uint32_t> expected_receive_ssrcs_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002611 std::set<uint32_t> expected_send_ssrcs_;
2612 std::string expected_cname_;
2613
Peter Boström5811a392015-12-10 13:02:50 +01002614 rtc::Event check_stats_event_;
stefanf116bd02015-10-27 08:29:42 -07002615 } test;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002616
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002617 FakeNetworkPipe::Config network_config;
2618 network_config.loss_percent = 5;
stefanf116bd02015-10-27 08:29:42 -07002619 RunBaseTest(&test, network_config);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002620}
2621
2622TEST_F(EndToEndTest, ReceiverReferenceTimeReportEnabled) {
2623 TestXrReceiverReferenceTimeReport(true);
2624}
2625
2626TEST_F(EndToEndTest, ReceiverReferenceTimeReportDisabled) {
2627 TestXrReceiverReferenceTimeReport(false);
2628}
2629
2630TEST_F(EndToEndTest, TestReceivedRtpPacketStats) {
2631 static const size_t kNumRtpPacketsToSend = 5;
2632 class ReceivedRtpStatsObserver : public test::EndToEndTest {
2633 public:
2634 ReceivedRtpStatsObserver()
2635 : EndToEndTest(kDefaultTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00002636 receive_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002637 sent_rtp_(0) {}
2638
2639 private:
stefanff483612015-12-21 03:14:00 -08002640 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002641 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002642 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002643 receive_stream_ = receive_streams[0];
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002644 }
2645
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002646 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002647 if (sent_rtp_ >= kNumRtpPacketsToSend) {
2648 VideoReceiveStream::Stats stats = receive_stream_->GetStats();
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00002649 if (kNumRtpPacketsToSend == stats.rtp_stats.transmitted.packets) {
Peter Boström5811a392015-12-10 13:02:50 +01002650 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002651 }
2652 return DROP_PACKET;
2653 }
2654 ++sent_rtp_;
2655 return SEND_PACKET;
2656 }
2657
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002658 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002659 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002660 << "Timed out while verifying number of received RTP packets.";
2661 }
2662
2663 VideoReceiveStream* receive_stream_;
2664 uint32_t sent_rtp_;
2665 } test;
2666
stefanf116bd02015-10-27 08:29:42 -07002667 RunBaseTest(&test, FakeNetworkPipe::Config());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002668}
2669
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002670TEST_F(EndToEndTest, SendsSetSsrc) { TestSendsSetSsrcs(1, false); }
2671
2672TEST_F(EndToEndTest, SendsSetSimulcastSsrcs) {
2673 TestSendsSetSsrcs(kNumSsrcs, false);
2674}
2675
2676TEST_F(EndToEndTest, CanSwitchToUseAllSsrcs) {
2677 TestSendsSetSsrcs(kNumSsrcs, true);
2678}
2679
mflodman@webrtc.orgf9460682014-07-24 16:41:25 +00002680TEST_F(EndToEndTest, DISABLED_RedundantPayloadsTransmittedOnAllSsrcs) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002681 class ObserveRedundantPayloads: public test::EndToEndTest {
2682 public:
2683 ObserveRedundantPayloads()
2684 : EndToEndTest(kDefaultTimeoutMs), ssrcs_to_observe_(kNumSsrcs) {
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00002685 for (size_t i = 0; i < kNumSsrcs; ++i) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002686 registered_rtx_ssrc_[kSendRtxSsrcs[i]] = true;
2687 }
2688 }
2689
2690 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002691 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002692 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002693 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002694
2695 if (!registered_rtx_ssrc_[header.ssrc])
2696 return SEND_PACKET;
2697
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00002698 EXPECT_LE(header.headerLength + header.paddingLength, length);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002699 const bool packet_is_redundant_payload =
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00002700 header.headerLength + header.paddingLength < length;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002701
2702 if (!packet_is_redundant_payload)
2703 return SEND_PACKET;
2704
2705 if (!observed_redundant_retransmission_[header.ssrc]) {
2706 observed_redundant_retransmission_[header.ssrc] = true;
2707 if (--ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01002708 observation_complete_.Set();
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002709 }
2710
2711 return SEND_PACKET;
2712 }
2713
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002714 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002715
stefanff483612015-12-21 03:14:00 -08002716 void ModifyVideoConfigs(
2717 VideoSendStream::Config* send_config,
2718 std::vector<VideoReceiveStream::Config>* receive_configs,
2719 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002720 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002721 for (size_t i = 0; i < encoder_config->streams.size(); ++i) {
2722 encoder_config->streams[i].min_bitrate_bps = 10000;
2723 encoder_config->streams[i].target_bitrate_bps = 15000;
2724 encoder_config->streams[i].max_bitrate_bps = 20000;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002725 }
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002726
2727 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002728
2729 for (size_t i = 0; i < kNumSsrcs; ++i)
2730 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.orgad3b5a52014-10-24 09:23:21 +00002731
2732 // Significantly higher than max bitrates for all video streams -> forcing
2733 // padding to trigger redundant padding on all RTX SSRCs.
2734 encoder_config->min_transmit_bitrate_bps = 100000;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002735 }
2736
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002737 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002738 EXPECT_TRUE(Wait())
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002739 << "Timed out while waiting for redundant payloads on all SSRCs.";
2740 }
2741
2742 private:
2743 size_t ssrcs_to_observe_;
2744 std::map<uint32_t, bool> observed_redundant_retransmission_;
2745 std::map<uint32_t, bool> registered_rtx_ssrc_;
2746 } test;
2747
stefanf116bd02015-10-27 08:29:42 -07002748 RunBaseTest(&test, FakeNetworkPipe::Config());
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002749}
2750
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002751void EndToEndTest::TestRtpStatePreservation(bool use_rtx) {
2752 static const uint32_t kMaxSequenceNumberGap = 100;
2753 static const uint64_t kMaxTimestampGap = kDefaultTimeoutMs * 90;
2754 class RtpSequenceObserver : public test::RtpRtcpObserver {
2755 public:
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00002756 explicit RtpSequenceObserver(bool use_rtx)
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002757 : test::RtpRtcpObserver(kDefaultTimeoutMs),
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002758 ssrcs_to_observe_(kNumSsrcs) {
2759 for (size_t i = 0; i < kNumSsrcs; ++i) {
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002760 configured_ssrcs_[kVideoSendSsrcs[i]] = true;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002761 if (use_rtx)
2762 configured_ssrcs_[kSendRtxSsrcs[i]] = true;
2763 }
2764 }
2765
2766 void ResetExpectedSsrcs(size_t num_expected_ssrcs) {
Peter Boströmf2f82832015-05-01 13:00:41 +02002767 rtc::CritScope lock(&crit_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002768 ssrc_observed_.clear();
2769 ssrcs_to_observe_ = num_expected_ssrcs;
2770 }
2771
2772 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002773 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002774 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002775 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002776 const uint32_t ssrc = header.ssrc;
2777 const uint16_t sequence_number = header.sequenceNumber;
2778 const uint32_t timestamp = header.timestamp;
2779 const bool only_padding =
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00002780 header.headerLength + header.paddingLength == length;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002781
2782 EXPECT_TRUE(configured_ssrcs_[ssrc])
2783 << "Received SSRC that wasn't configured: " << ssrc;
2784
2785 std::map<uint32_t, uint16_t>::iterator it =
2786 last_observed_sequence_number_.find(header.ssrc);
2787 if (it == last_observed_sequence_number_.end()) {
2788 last_observed_sequence_number_[ssrc] = sequence_number;
2789 last_observed_timestamp_[ssrc] = timestamp;
2790 } else {
2791 // Verify sequence numbers are reasonably close.
2792 uint32_t extended_sequence_number = sequence_number;
2793 // Check for roll-over.
2794 if (sequence_number < last_observed_sequence_number_[ssrc])
2795 extended_sequence_number += 0xFFFFu + 1;
2796 EXPECT_LE(
2797 extended_sequence_number - last_observed_sequence_number_[ssrc],
2798 kMaxSequenceNumberGap)
2799 << "Gap in sequence numbers ("
2800 << last_observed_sequence_number_[ssrc] << " -> " << sequence_number
2801 << ") too large for SSRC: " << ssrc << ".";
2802 last_observed_sequence_number_[ssrc] = sequence_number;
2803
2804 // TODO(pbos): Remove this check if we ever have monotonically
2805 // increasing timestamps. Right now padding packets add a delta which
2806 // can cause reordering between padding packets and regular packets,
2807 // hence we drop padding-only packets to not flake.
2808 if (only_padding) {
2809 // Verify that timestamps are reasonably close.
2810 uint64_t extended_timestamp = timestamp;
2811 // Check for roll-over.
2812 if (timestamp < last_observed_timestamp_[ssrc])
2813 extended_timestamp += static_cast<uint64_t>(0xFFFFFFFFu) + 1;
2814 EXPECT_LE(extended_timestamp - last_observed_timestamp_[ssrc],
2815 kMaxTimestampGap)
2816 << "Gap in timestamps (" << last_observed_timestamp_[ssrc]
2817 << " -> " << timestamp << ") too large for SSRC: " << ssrc << ".";
2818 }
2819 last_observed_timestamp_[ssrc] = timestamp;
2820 }
2821
Peter Boströmf2f82832015-05-01 13:00:41 +02002822 rtc::CritScope lock(&crit_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002823 // Wait for media packets on all ssrcs.
2824 if (!ssrc_observed_[ssrc] && !only_padding) {
2825 ssrc_observed_[ssrc] = true;
2826 if (--ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01002827 observation_complete_.Set();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002828 }
2829
2830 return SEND_PACKET;
2831 }
2832
2833 std::map<uint32_t, uint16_t> last_observed_sequence_number_;
2834 std::map<uint32_t, uint32_t> last_observed_timestamp_;
2835 std::map<uint32_t, bool> configured_ssrcs_;
2836
Peter Boströmf2f82832015-05-01 13:00:41 +02002837 rtc::CriticalSection crit_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002838 size_t ssrcs_to_observe_ GUARDED_BY(crit_);
2839 std::map<uint32_t, bool> ssrc_observed_ GUARDED_BY(crit_);
2840 } observer(use_rtx);
2841
solenberg4fbae2b2015-08-28 04:07:10 -07002842 CreateCalls(Call::Config(), Call::Config());
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002843
stefanf116bd02015-10-27 08:29:42 -07002844 test::PacketTransport send_transport(sender_call_.get(), &observer,
2845 test::PacketTransport::kSender,
2846 FakeNetworkPipe::Config());
2847 test::PacketTransport receive_transport(nullptr, &observer,
2848 test::PacketTransport::kReceiver,
2849 FakeNetworkPipe::Config());
2850 send_transport.SetReceiver(receiver_call_->Receiver());
2851 receive_transport.SetReceiver(sender_call_->Receiver());
2852
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002853 CreateSendConfig(kNumSsrcs, 0, &send_transport);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002854
2855 if (use_rtx) {
2856 for (size_t i = 0; i < kNumSsrcs; ++i) {
stefanff483612015-12-21 03:14:00 -08002857 video_send_config_.rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002858 }
stefanff483612015-12-21 03:14:00 -08002859 video_send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002860 }
2861
2862 // Lower bitrates so that all streams send initially.
stefanff483612015-12-21 03:14:00 -08002863 for (size_t i = 0; i < video_encoder_config_.streams.size(); ++i) {
2864 video_encoder_config_.streams[i].min_bitrate_bps = 10000;
2865 video_encoder_config_.streams[i].target_bitrate_bps = 15000;
2866 video_encoder_config_.streams[i].max_bitrate_bps = 20000;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002867 }
2868
pbos@webrtc.org32452b22014-10-22 12:15:24 +00002869 // Use the same total bitrates when sending a single stream to avoid lowering
2870 // the bitrate estimate and requiring a subsequent rampup.
stefanff483612015-12-21 03:14:00 -08002871 VideoEncoderConfig one_stream = video_encoder_config_;
pbos@webrtc.org32452b22014-10-22 12:15:24 +00002872 one_stream.streams.resize(1);
stefanff483612015-12-21 03:14:00 -08002873 for (size_t i = 1; i < video_encoder_config_.streams.size(); ++i) {
pbos@webrtc.org32452b22014-10-22 12:15:24 +00002874 one_stream.streams.front().min_bitrate_bps +=
stefanff483612015-12-21 03:14:00 -08002875 video_encoder_config_.streams[i].min_bitrate_bps;
pbos@webrtc.org32452b22014-10-22 12:15:24 +00002876 one_stream.streams.front().target_bitrate_bps +=
stefanff483612015-12-21 03:14:00 -08002877 video_encoder_config_.streams[i].target_bitrate_bps;
pbos@webrtc.org32452b22014-10-22 12:15:24 +00002878 one_stream.streams.front().max_bitrate_bps +=
stefanff483612015-12-21 03:14:00 -08002879 video_encoder_config_.streams[i].max_bitrate_bps;
pbos@webrtc.org32452b22014-10-22 12:15:24 +00002880 }
2881
stefanf116bd02015-10-27 08:29:42 -07002882 CreateMatchingReceiveConfigs(&receive_transport);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002883
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002884 CreateVideoStreams();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002885 CreateFrameGeneratorCapturer();
2886
2887 Start();
Peter Boström5811a392015-12-10 13:02:50 +01002888 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002889 << "Timed out waiting for all SSRCs to send packets.";
2890
2891 // Test stream resetting more than once to make sure that the state doesn't
2892 // get set once (this could be due to using std::map::insert for instance).
2893 for (size_t i = 0; i < 3; ++i) {
2894 frame_generator_capturer_->Stop();
stefanff483612015-12-21 03:14:00 -08002895 sender_call_->DestroyVideoSendStream(video_send_stream_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002896
2897 // Re-create VideoSendStream with only one stream.
stefanff483612015-12-21 03:14:00 -08002898 video_send_stream_ =
2899 sender_call_->CreateVideoSendStream(video_send_config_, one_stream);
2900 video_send_stream_->Start();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002901 CreateFrameGeneratorCapturer();
2902 frame_generator_capturer_->Start();
2903
2904 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01002905 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002906
2907 // Reconfigure back to use all streams.
stefanff483612015-12-21 03:14:00 -08002908 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002909 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01002910 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002911 << "Timed out waiting for all SSRCs to send packets.";
2912
2913 // Reconfigure down to one stream.
stefanff483612015-12-21 03:14:00 -08002914 video_send_stream_->ReconfigureVideoEncoder(one_stream);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002915 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01002916 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002917
2918 // Reconfigure back to use all streams.
stefanff483612015-12-21 03:14:00 -08002919 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002920 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01002921 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002922 << "Timed out waiting for all SSRCs to send packets.";
2923 }
2924
stefanf116bd02015-10-27 08:29:42 -07002925 send_transport.StopSending();
2926 receive_transport.StopSending();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002927
2928 Stop();
2929 DestroyStreams();
2930}
2931
aluebs@webrtc.orgb623c5c2014-08-26 14:22:51 +00002932TEST_F(EndToEndTest, DISABLED_RestartingSendStreamPreservesRtpState) {
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002933 TestRtpStatePreservation(false);
2934}
2935
2936TEST_F(EndToEndTest, RestartingSendStreamPreservesRtpStatesWithRtx) {
2937 TestRtpStatePreservation(true);
2938}
2939
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002940TEST_F(EndToEndTest, RespectsNetworkState) {
2941 // TODO(pbos): Remove accepted downtime packets etc. when signaling network
2942 // down blocks until no more packets will be sent.
2943
2944 // Pacer will send from its packet list and then send required padding before
2945 // checking paused_ again. This should be enough for one round of pacing,
2946 // otherwise increase.
2947 static const int kNumAcceptedDowntimeRtp = 5;
2948 // A single RTCP may be in the pipeline.
2949 static const int kNumAcceptedDowntimeRtcp = 1;
2950 class NetworkStateTest : public test::EndToEndTest, public test::FakeEncoder {
2951 public:
2952 NetworkStateTest()
2953 : EndToEndTest(kDefaultTimeoutMs),
2954 FakeEncoder(Clock::GetRealTimeClock()),
Peter Boström5811a392015-12-10 13:02:50 +01002955 encoded_frames_(false, false),
2956 packet_event_(false, false),
sprang867fb522015-08-03 04:38:41 -07002957 sender_call_(nullptr),
2958 receiver_call_(nullptr),
Jelena Marusiccd670222015-07-16 09:30:09 +02002959 sender_state_(kNetworkUp),
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00002960 sender_rtp_(0),
2961 sender_rtcp_(0),
2962 receiver_rtcp_(0),
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002963 down_frames_(0) {}
2964
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002965 Action OnSendRtp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02002966 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00002967 ++sender_rtp_;
Peter Boström5811a392015-12-10 13:02:50 +01002968 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002969 return SEND_PACKET;
2970 }
2971
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002972 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02002973 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00002974 ++sender_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01002975 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002976 return SEND_PACKET;
2977 }
2978
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002979 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002980 ADD_FAILURE() << "Unexpected receiver RTP, should not be sending.";
2981 return SEND_PACKET;
2982 }
2983
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002984 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02002985 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00002986 ++receiver_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01002987 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002988 return SEND_PACKET;
2989 }
2990
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002991 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002992 sender_call_ = sender_call;
2993 receiver_call_ = receiver_call;
2994 }
2995
stefanff483612015-12-21 03:14:00 -08002996 void ModifyVideoConfigs(
2997 VideoSendStream::Config* send_config,
2998 std::vector<VideoReceiveStream::Config>* receive_configs,
2999 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003000 send_config->encoder_settings.encoder = this;
3001 }
3002
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003003 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003004 EXPECT_TRUE(encoded_frames_.Wait(kDefaultTimeoutMs))
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003005 << "No frames received by the encoder.";
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003006 // Wait for packets from both sender/receiver.
3007 WaitForPacketsOrSilence(false, false);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003008
3009 // Sender-side network down.
Jelena Marusiccd670222015-07-16 09:30:09 +02003010 sender_call_->SignalNetworkState(kNetworkDown);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003011 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003012 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003013 // After network goes down we shouldn't be encoding more frames.
Jelena Marusiccd670222015-07-16 09:30:09 +02003014 sender_state_ = kNetworkDown;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003015 }
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003016 // Wait for receiver-packets and no sender packets.
3017 WaitForPacketsOrSilence(true, false);
3018
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003019 // Receiver-side network down.
Jelena Marusiccd670222015-07-16 09:30:09 +02003020 receiver_call_->SignalNetworkState(kNetworkDown);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003021 WaitForPacketsOrSilence(true, true);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003022
3023 // Network back up again for both.
3024 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003025 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003026 // It's OK to encode frames again, as we're about to bring up the
3027 // network.
Jelena Marusiccd670222015-07-16 09:30:09 +02003028 sender_state_ = kNetworkUp;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003029 }
Jelena Marusiccd670222015-07-16 09:30:09 +02003030 sender_call_->SignalNetworkState(kNetworkUp);
3031 receiver_call_->SignalNetworkState(kNetworkUp);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003032 WaitForPacketsOrSilence(false, false);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003033 }
3034
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07003035 int32_t Encode(const VideoFrame& input_image,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003036 const CodecSpecificInfo* codec_specific_info,
pbos22993e12015-10-19 02:39:06 -07003037 const std::vector<FrameType>* frame_types) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003038 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003039 rtc::CritScope lock(&test_crit_);
Jelena Marusiccd670222015-07-16 09:30:09 +02003040 if (sender_state_ == kNetworkDown) {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003041 ++down_frames_;
3042 EXPECT_LE(down_frames_, 1)
3043 << "Encoding more than one frame while network is down.";
3044 if (down_frames_ > 1)
Peter Boström5811a392015-12-10 13:02:50 +01003045 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003046 } else {
Peter Boström5811a392015-12-10 13:02:50 +01003047 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003048 }
3049 }
3050 return test::FakeEncoder::Encode(
3051 input_image, codec_specific_info, frame_types);
3052 }
3053
3054 private:
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003055 void WaitForPacketsOrSilence(bool sender_down, bool receiver_down) {
3056 int64_t initial_time_ms = clock_->TimeInMilliseconds();
3057 int initial_sender_rtp;
3058 int initial_sender_rtcp;
3059 int initial_receiver_rtcp;
3060 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003061 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003062 initial_sender_rtp = sender_rtp_;
3063 initial_sender_rtcp = sender_rtcp_;
3064 initial_receiver_rtcp = receiver_rtcp_;
3065 }
3066 bool sender_done = false;
3067 bool receiver_done = false;
mflodmand1590b22015-12-09 07:07:59 -08003068 while (!sender_done || !receiver_done) {
Peter Boström5811a392015-12-10 13:02:50 +01003069 packet_event_.Wait(kSilenceTimeoutMs);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003070 int64_t time_now_ms = clock_->TimeInMilliseconds();
Peter Boströmf2f82832015-05-01 13:00:41 +02003071 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003072 if (sender_down) {
3073 ASSERT_LE(sender_rtp_ - initial_sender_rtp, kNumAcceptedDowntimeRtp)
3074 << "RTP sent during sender-side downtime.";
3075 ASSERT_LE(sender_rtcp_ - initial_sender_rtcp,
3076 kNumAcceptedDowntimeRtcp)
3077 << "RTCP sent during sender-side downtime.";
3078 if (time_now_ms - initial_time_ms >=
3079 static_cast<int64_t>(kSilenceTimeoutMs)) {
3080 sender_done = true;
3081 }
3082 } else {
3083 if (sender_rtp_ > initial_sender_rtp)
3084 sender_done = true;
3085 }
3086 if (receiver_down) {
3087 ASSERT_LE(receiver_rtcp_ - initial_receiver_rtcp,
3088 kNumAcceptedDowntimeRtcp)
3089 << "RTCP sent during receiver-side downtime.";
3090 if (time_now_ms - initial_time_ms >=
3091 static_cast<int64_t>(kSilenceTimeoutMs)) {
3092 receiver_done = true;
3093 }
3094 } else {
3095 if (receiver_rtcp_ > initial_receiver_rtcp)
3096 receiver_done = true;
3097 }
3098 }
3099 }
3100
Peter Boströmf2f82832015-05-01 13:00:41 +02003101 rtc::CriticalSection test_crit_;
Peter Boström5811a392015-12-10 13:02:50 +01003102 rtc::Event encoded_frames_;
3103 rtc::Event packet_event_;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003104 Call* sender_call_;
3105 Call* receiver_call_;
Jelena Marusiccd670222015-07-16 09:30:09 +02003106 NetworkState sender_state_ GUARDED_BY(test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003107 int sender_rtp_ GUARDED_BY(test_crit_);
3108 int sender_rtcp_ GUARDED_BY(test_crit_);
3109 int receiver_rtcp_ GUARDED_BY(test_crit_);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003110 int down_frames_ GUARDED_BY(test_crit_);
3111 } test;
3112
stefanf116bd02015-10-27 08:29:42 -07003113 RunBaseTest(&test, FakeNetworkPipe::Config());
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003114}
3115
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003116TEST_F(EndToEndTest, CallReportsRttForSender) {
3117 static const int kSendDelayMs = 30;
3118 static const int kReceiveDelayMs = 70;
3119
solenberg4fbae2b2015-08-28 04:07:10 -07003120 CreateCalls(Call::Config(), Call::Config());
3121
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003122 FakeNetworkPipe::Config config;
3123 config.queue_delay_ms = kSendDelayMs;
stefanf116bd02015-10-27 08:29:42 -07003124 test::DirectTransport sender_transport(config, sender_call_.get());
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003125 config.queue_delay_ms = kReceiveDelayMs;
stefanf116bd02015-10-27 08:29:42 -07003126 test::DirectTransport receiver_transport(config, receiver_call_.get());
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003127 sender_transport.SetReceiver(receiver_call_->Receiver());
3128 receiver_transport.SetReceiver(sender_call_->Receiver());
3129
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003130 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07003131 CreateMatchingReceiveConfigs(&receiver_transport);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003132
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003133 CreateVideoStreams();
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003134 CreateFrameGeneratorCapturer();
3135 Start();
3136
3137 int64_t start_time_ms = clock_->TimeInMilliseconds();
3138 while (true) {
3139 Call::Stats stats = sender_call_->GetStats();
3140 ASSERT_GE(start_time_ms + kDefaultTimeoutMs,
3141 clock_->TimeInMilliseconds())
3142 << "No RTT stats before timeout!";
3143 if (stats.rtt_ms != -1) {
3144 EXPECT_GE(stats.rtt_ms, kSendDelayMs + kReceiveDelayMs);
3145 break;
3146 }
3147 SleepMs(10);
3148 }
3149
3150 Stop();
3151 DestroyStreams();
3152}
3153
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003154TEST_F(EndToEndTest, NewSendStreamsRespectNetworkDown) {
3155 class UnusedEncoder : public test::FakeEncoder {
mflodmand1590b22015-12-09 07:07:59 -08003156 public:
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003157 UnusedEncoder() : FakeEncoder(Clock::GetRealTimeClock()) {}
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07003158 int32_t Encode(const VideoFrame& input_image,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003159 const CodecSpecificInfo* codec_specific_info,
pbos22993e12015-10-19 02:39:06 -07003160 const std::vector<FrameType>* frame_types) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003161 ADD_FAILURE() << "Unexpected frame encode.";
3162 return test::FakeEncoder::Encode(
3163 input_image, codec_specific_info, frame_types);
3164 }
3165 };
3166
solenberg4fbae2b2015-08-28 04:07:10 -07003167 CreateSenderCall(Call::Config());
Jelena Marusiccd670222015-07-16 09:30:09 +02003168 sender_call_->SignalNetworkState(kNetworkDown);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003169
solenberg4fbae2b2015-08-28 04:07:10 -07003170 UnusedTransport transport;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003171 CreateSendConfig(1, 0, &transport);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003172 UnusedEncoder unused_encoder;
stefanff483612015-12-21 03:14:00 -08003173 video_send_config_.encoder_settings.encoder = &unused_encoder;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003174 CreateVideoStreams();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003175 CreateFrameGeneratorCapturer();
3176
3177 Start();
3178 SleepMs(kSilenceTimeoutMs);
3179 Stop();
3180
3181 DestroyStreams();
3182}
3183
3184TEST_F(EndToEndTest, NewReceiveStreamsRespectNetworkDown) {
solenberg4fbae2b2015-08-28 04:07:10 -07003185 CreateCalls(Call::Config(), Call::Config());
Jelena Marusiccd670222015-07-16 09:30:09 +02003186 receiver_call_->SignalNetworkState(kNetworkDown);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003187
stefanf116bd02015-10-27 08:29:42 -07003188 test::DirectTransport sender_transport(sender_call_.get());
solenberg4fbae2b2015-08-28 04:07:10 -07003189 sender_transport.SetReceiver(receiver_call_->Receiver());
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003190 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07003191 UnusedTransport transport;
3192 CreateMatchingReceiveConfigs(&transport);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003193 CreateVideoStreams();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003194 CreateFrameGeneratorCapturer();
3195
3196 Start();
3197 SleepMs(kSilenceTimeoutMs);
3198 Stop();
3199
3200 sender_transport.StopSending();
3201
3202 DestroyStreams();
3203}
pbos@webrtc.org09cc6862014-11-04 13:48:15 +00003204
Peter Boströmd7da1202015-06-05 14:09:38 +02003205void VerifyEmptyNackConfig(const NackConfig& config) {
3206 EXPECT_EQ(0, config.rtp_history_ms)
3207 << "Enabling NACK requires rtcp-fb: nack negotiation.";
3208}
3209
3210void VerifyEmptyFecConfig(const FecConfig& config) {
3211 EXPECT_EQ(-1, config.ulpfec_payload_type)
3212 << "Enabling FEC requires rtpmap: ulpfec negotiation.";
3213 EXPECT_EQ(-1, config.red_payload_type)
3214 << "Enabling FEC requires rtpmap: red negotiation.";
3215 EXPECT_EQ(-1, config.red_rtx_payload_type)
3216 << "Enabling RTX in FEC requires rtpmap: rtx negotiation.";
3217}
3218
3219TEST_F(EndToEndTest, VerifyDefaultSendConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07003220 VideoSendStream::Config default_send_config(nullptr);
Peter Boströmd7da1202015-06-05 14:09:38 +02003221 EXPECT_EQ(0, default_send_config.rtp.nack.rtp_history_ms)
3222 << "Enabling NACK require rtcp-fb: nack negotiation.";
3223 EXPECT_TRUE(default_send_config.rtp.rtx.ssrcs.empty())
3224 << "Enabling RTX requires rtpmap: rtx negotiation.";
3225 EXPECT_TRUE(default_send_config.rtp.extensions.empty())
3226 << "Enabling RTP extensions require negotiation.";
3227
3228 VerifyEmptyNackConfig(default_send_config.rtp.nack);
3229 VerifyEmptyFecConfig(default_send_config.rtp.fec);
3230}
3231
3232TEST_F(EndToEndTest, VerifyDefaultReceiveConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07003233 VideoReceiveStream::Config default_receive_config(nullptr);
pbosda903ea2015-10-02 02:36:56 -07003234 EXPECT_EQ(RtcpMode::kCompound, default_receive_config.rtp.rtcp_mode)
Peter Boströmd7da1202015-06-05 14:09:38 +02003235 << "Reduced-size RTCP require rtcp-rsize to be negotiated.";
3236 EXPECT_FALSE(default_receive_config.rtp.remb)
3237 << "REMB require rtcp-fb: goog-remb to be negotiated.";
3238 EXPECT_FALSE(
3239 default_receive_config.rtp.rtcp_xr.receiver_reference_time_report)
3240 << "RTCP XR settings require rtcp-xr to be negotiated.";
3241 EXPECT_TRUE(default_receive_config.rtp.rtx.empty())
3242 << "Enabling RTX requires rtpmap: rtx negotiation.";
3243 EXPECT_TRUE(default_receive_config.rtp.extensions.empty())
3244 << "Enabling RTP extensions require negotiation.";
3245
3246 VerifyEmptyNackConfig(default_receive_config.rtp.nack);
3247 VerifyEmptyFecConfig(default_receive_config.rtp.fec);
3248}
3249
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003250TEST_F(EndToEndTest, TransportSeqNumOnAudioAndVideo) {
3251 static const int kExtensionId = 8;
3252 class TransportSequenceNumberTest : public test::EndToEndTest {
3253 public:
3254 TransportSequenceNumberTest()
3255 : EndToEndTest(kDefaultTimeoutMs),
3256 video_observed_(false),
3257 audio_observed_(false) {
3258 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
3259 kExtensionId);
3260 }
3261
3262 size_t GetNumVideoStreams() const override { return 1; }
3263 size_t GetNumAudioStreams() const override { return 1; }
3264
3265 void ModifyVideoConfigs(
3266 VideoSendStream::Config* send_config,
3267 std::vector<VideoReceiveStream::Config>* receive_configs,
3268 VideoEncoderConfig* encoder_config) override {
3269 send_config->rtp.extensions.clear();
3270 send_config->rtp.extensions.push_back(
3271 RtpExtension(RtpExtension::kTransportSequenceNumber, kExtensionId));
3272 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
3273 }
3274
3275 void ModifyAudioConfigs(
3276 AudioSendStream::Config* send_config,
3277 std::vector<AudioReceiveStream::Config>* receive_configs) override {
3278 send_config->rtp.extensions.clear();
3279 send_config->rtp.extensions.push_back(
3280 RtpExtension(RtpExtension::kTransportSequenceNumber, kExtensionId));
3281 (*receive_configs)[0].rtp.extensions.clear();
3282 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
3283 }
3284
3285 Action OnSendRtp(const uint8_t* packet, size_t length) override {
3286 RTPHeader header;
3287 EXPECT_TRUE(parser_->Parse(packet, length, &header));
3288 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
3289 // Unwrap packet id and verify uniqueness.
3290 int64_t packet_id =
3291 unwrapper_.Unwrap(header.extension.transportSequenceNumber);
3292 EXPECT_TRUE(received_packet_ids_.insert(packet_id).second);
3293
3294 if (header.ssrc == kVideoSendSsrcs[0])
3295 video_observed_ = true;
3296 if (header.ssrc == kAudioSendSsrc)
3297 audio_observed_ = true;
3298 if (audio_observed_ && video_observed_ &&
3299 received_packet_ids_.size() == 50) {
3300 size_t packet_id_range =
3301 *received_packet_ids_.rbegin() - *received_packet_ids_.begin() + 1;
3302 EXPECT_EQ(received_packet_ids_.size(), packet_id_range);
3303 observation_complete_.Set();
3304 }
3305 return SEND_PACKET;
3306 }
3307
3308 void PerformTest() override {
3309 EXPECT_TRUE(Wait()) << "Timed out while waiting for audio and video "
3310 "packets with transport sequence number.";
3311 }
3312
3313 private:
3314 bool video_observed_;
3315 bool audio_observed_;
3316 SequenceNumberUnwrapper unwrapper_;
3317 std::set<int64_t> received_packet_ids_;
3318 } test;
3319
3320 RunBaseTest(&test, FakeNetworkPipe::Config());
3321}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003322} // namespace webrtc