blob: 60063f49a35d705924837732f94027e14400d1eb [file] [log] [blame]
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001/*
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000010#include <algorithm>
danilchap5c35cf92016-02-03 14:14:49 -080011#include <list>
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000012#include <map>
kwiberg27f982b2016-03-01 11:52:33 -080013#include <memory>
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000014#include <sstream>
15#include <string>
kwiberg4a206a92016-03-31 10:24:26 -070016#include <vector>
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000017
18#include "testing/gtest/include/gtest/gtest.h"
19
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +000020#include "webrtc/base/checks.h"
Erik Språng6b8d3552015-09-24 15:06:57 +020021#include "webrtc/base/event.h"
Erik Språng737336d2016-07-29 12:59:36 +020022#include "webrtc/base/optional.h"
23#include "webrtc/base/rate_limiter.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000024#include "webrtc/call.h"
Peter Boström5c389d32015-09-25 13:58:30 +020025#include "webrtc/call/transport_adapter.h"
pbosa96b60b2016-04-18 21:12:48 -070026#include "webrtc/common_video/include/frame_callback.h"
danilchap5c35cf92016-02-03 14:14:49 -080027#include "webrtc/modules/include/module_common_types.h"
stefan32f81542016-01-20 07:13:58 -080028#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h"
sprang861c55e2015-10-16 10:01:21 -070029#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
Erik Språng737336d2016-07-29 12:59:36 +020030#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/nack.h"
Danil Chapovalov70ffead2016-07-20 15:26:59 +020031#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/rapid_resync_request.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000032#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
sprangcd349d92016-07-13 09:11:28 -070033#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
hbosbab934b2016-01-27 01:36:03 -080034#include "webrtc/modules/video_coding/codecs/h264/include/h264.h"
marpan@webrtc.org5b883172014-11-01 06:10:48 +000035#include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h"
36#include "webrtc/modules/video_coding/codecs/vp9/include/vp9.h"
Henrik Kjellander2557b862015-11-18 22:00:21 +010037#include "webrtc/modules/video_coding/include/video_coding_defines.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010038#include "webrtc/system_wrappers/include/metrics.h"
asapersson01d70a32016-05-20 06:29:46 -070039#include "webrtc/system_wrappers/include/metrics_default.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010040#include "webrtc/system_wrappers/include/sleep.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000041#include "webrtc/test/call_test.h"
42#include "webrtc/test/direct_transport.h"
43#include "webrtc/test/encoder_settings.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000044#include "webrtc/test/fake_decoder.h"
45#include "webrtc/test/fake_encoder.h"
46#include "webrtc/test/frame_generator.h"
47#include "webrtc/test/frame_generator_capturer.h"
48#include "webrtc/test/null_transport.h"
asapersson@webrtc.org37c05592015-01-28 13:58:27 +000049#include "webrtc/test/rtcp_packet_parser.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000050#include "webrtc/test/rtp_rtcp_observer.h"
51#include "webrtc/test/testsupport/fileutils.h"
52#include "webrtc/test/testsupport/perf_test.h"
pbos@webrtc.orgab990ae2014-09-17 09:02:25 +000053#include "webrtc/video_encoder.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000054
55namespace webrtc {
56
Peter Boström5811a392015-12-10 13:02:50 +010057static const int kSilenceTimeoutMs = 2000;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000058
59class EndToEndTest : public test::CallTest {
60 public:
61 EndToEndTest() {}
62
63 virtual ~EndToEndTest() {
stefanff483612015-12-21 03:14:00 -080064 EXPECT_EQ(nullptr, video_send_stream_);
65 EXPECT_TRUE(video_receive_streams_.empty());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000066 }
67
68 protected:
pbos2d566682015-09-28 09:59:31 -070069 class UnusedTransport : public Transport {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000070 private:
stefan1d8a5062015-10-02 03:39:33 -070071 bool SendRtp(const uint8_t* packet,
72 size_t length,
73 const PacketOptions& options) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000074 ADD_FAILURE() << "Unexpected RTP sent.";
75 return false;
76 }
77
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000078 bool SendRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000079 ADD_FAILURE() << "Unexpected RTCP sent.";
80 return false;
81 }
82 };
83
skvlad7a43d252016-03-22 15:32:27 -070084 class RequiredTransport : public Transport {
85 public:
86 RequiredTransport(bool rtp_required, bool rtcp_required)
87 : need_rtp_(rtp_required), need_rtcp_(rtcp_required) {}
88 ~RequiredTransport() {
89 if (need_rtp_) {
90 ADD_FAILURE() << "Expected RTP packet not sent.";
91 }
92 if (need_rtcp_) {
93 ADD_FAILURE() << "Expected RTCP packet not sent.";
94 }
95 }
96
97 private:
98 bool SendRtp(const uint8_t* packet,
99 size_t length,
100 const PacketOptions& options) override {
Taylor Brandstetter14cf12b2016-08-22 18:14:14 -0700101 rtc::CritScope lock(&crit_);
skvlad7a43d252016-03-22 15:32:27 -0700102 need_rtp_ = false;
103 return true;
104 }
105
106 bool SendRtcp(const uint8_t* packet, size_t length) override {
Taylor Brandstetter14cf12b2016-08-22 18:14:14 -0700107 rtc::CritScope lock(&crit_);
skvlad7a43d252016-03-22 15:32:27 -0700108 need_rtcp_ = false;
109 return true;
110 }
111 bool need_rtp_;
112 bool need_rtcp_;
Taylor Brandstetter14cf12b2016-08-22 18:14:14 -0700113 rtc::CriticalSection crit_;
skvlad7a43d252016-03-22 15:32:27 -0700114 };
115
Peter Boström39593972016-02-15 11:27:15 +0100116 void DecodesRetransmittedFrame(bool enable_rtx, bool enable_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000117 void ReceivesPliAndRecovers(int rtp_history_ms);
pbosda903ea2015-10-02 02:36:56 -0700118 void RespectsRtcpMode(RtcpMode rtcp_mode);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000119 void TestXrReceiverReferenceTimeReport(bool enable_rrtr);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000120 void TestSendsSetSsrcs(size_t num_ssrcs, bool send_single_ssrc_first);
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200121 void TestRtpStatePreservation(bool use_rtx, bool provoke_rtcpsr_before_rtp);
sprangb4a1ae52015-12-03 08:10:08 -0800122 void VerifyHistogramStats(bool use_rtx, bool use_red, bool screenshare);
skvlad7a43d252016-03-22 15:32:27 -0700123 void VerifyNewVideoSendStreamsRespectNetworkState(
124 MediaType network_to_bring_down,
125 VideoEncoder* encoder,
126 Transport* transport);
127 void VerifyNewVideoReceiveStreamsRespectNetworkState(
128 MediaType network_to_bring_down,
129 Transport* transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000130};
131
132TEST_F(EndToEndTest, ReceiverCanBeStartedTwice) {
solenberg4fbae2b2015-08-28 04:07:10 -0700133 CreateCalls(Call::Config(), Call::Config());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000134
solenberg4fbae2b2015-08-28 04:07:10 -0700135 test::NullTransport transport;
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100136 CreateSendConfig(1, 0, &transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700137 CreateMatchingReceiveConfigs(&transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000138
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100139 CreateVideoStreams();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000140
stefanff483612015-12-21 03:14:00 -0800141 video_receive_streams_[0]->Start();
142 video_receive_streams_[0]->Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000143
144 DestroyStreams();
145}
146
147TEST_F(EndToEndTest, ReceiverCanBeStoppedTwice) {
solenberg4fbae2b2015-08-28 04:07:10 -0700148 CreateCalls(Call::Config(), Call::Config());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000149
solenberg4fbae2b2015-08-28 04:07:10 -0700150 test::NullTransport transport;
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100151 CreateSendConfig(1, 0, &transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700152 CreateMatchingReceiveConfigs(&transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000153
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100154 CreateVideoStreams();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000155
stefanff483612015-12-21 03:14:00 -0800156 video_receive_streams_[0]->Stop();
157 video_receive_streams_[0]->Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000158
159 DestroyStreams();
160}
161
162TEST_F(EndToEndTest, RendersSingleDelayedFrame) {
163 static const int kWidth = 320;
164 static const int kHeight = 240;
165 // This constant is chosen to be higher than the timeout in the video_render
166 // module. This makes sure that frames aren't dropped if there are no other
167 // frames in the queue.
168 static const int kDelayRenderCallbackMs = 1000;
169
nisse7ade7b32016-03-23 04:48:10 -0700170 class Renderer : public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000171 public:
Peter Boström5811a392015-12-10 13:02:50 +0100172 Renderer() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000173
nisseeb83a1a2016-03-21 01:27:56 -0700174 void OnFrame(const VideoFrame& video_frame) override { event_.Set(); }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000175
Peter Boström5811a392015-12-10 13:02:50 +0100176 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000177
Peter Boström5811a392015-12-10 13:02:50 +0100178 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000179 } renderer;
180
181 class TestFrameCallback : public I420FrameCallback {
182 public:
Peter Boström5811a392015-12-10 13:02:50 +0100183 TestFrameCallback() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000184
Peter Boström5811a392015-12-10 13:02:50 +0100185 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000186
187 private:
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700188 void FrameCallback(VideoFrame* frame) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000189 SleepMs(kDelayRenderCallbackMs);
Peter Boström5811a392015-12-10 13:02:50 +0100190 event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000191 }
192
Peter Boström5811a392015-12-10 13:02:50 +0100193 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000194 };
195
solenberg4fbae2b2015-08-28 04:07:10 -0700196 CreateCalls(Call::Config(), Call::Config());
197
stefanf116bd02015-10-27 08:29:42 -0700198 test::DirectTransport sender_transport(sender_call_.get());
199 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000200 sender_transport.SetReceiver(receiver_call_->Receiver());
201 receiver_transport.SetReceiver(sender_call_->Receiver());
202
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100203 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700204 CreateMatchingReceiveConfigs(&receiver_transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000205
206 TestFrameCallback pre_render_callback;
stefanff483612015-12-21 03:14:00 -0800207 video_receive_configs_[0].pre_render_callback = &pre_render_callback;
208 video_receive_configs_[0].renderer = &renderer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000209
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100210 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000211 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000212
213 // Create frames that are smaller than the send width/height, this is done to
214 // check that the callbacks are done after processing video.
kwiberg27f982b2016-03-01 11:52:33 -0800215 std::unique_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +0000216 test::FrameGenerator::CreateChromaGenerator(kWidth, kHeight));
stefanff483612015-12-21 03:14:00 -0800217 video_send_stream_->Input()->IncomingCapturedFrame(
218 *frame_generator->NextFrame());
Peter Boström5811a392015-12-10 13:02:50 +0100219 EXPECT_TRUE(pre_render_callback.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000220 << "Timed out while waiting for pre-render callback.";
Peter Boström5811a392015-12-10 13:02:50 +0100221 EXPECT_TRUE(renderer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000222 << "Timed out while waiting for the frame to render.";
223
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000224 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000225
226 sender_transport.StopSending();
227 receiver_transport.StopSending();
228
229 DestroyStreams();
230}
231
232TEST_F(EndToEndTest, TransmitsFirstFrame) {
nisse7ade7b32016-03-23 04:48:10 -0700233 class Renderer : public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000234 public:
Peter Boström5811a392015-12-10 13:02:50 +0100235 Renderer() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000236
nisseeb83a1a2016-03-21 01:27:56 -0700237 void OnFrame(const VideoFrame& video_frame) override { event_.Set(); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000238
Peter Boström5811a392015-12-10 13:02:50 +0100239 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000240
Peter Boström5811a392015-12-10 13:02:50 +0100241 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000242 } renderer;
243
solenberg4fbae2b2015-08-28 04:07:10 -0700244 CreateCalls(Call::Config(), Call::Config());
245
stefanf116bd02015-10-27 08:29:42 -0700246 test::DirectTransport sender_transport(sender_call_.get());
247 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000248 sender_transport.SetReceiver(receiver_call_->Receiver());
249 receiver_transport.SetReceiver(sender_call_->Receiver());
250
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100251 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700252 CreateMatchingReceiveConfigs(&receiver_transport);
stefanff483612015-12-21 03:14:00 -0800253 video_receive_configs_[0].renderer = &renderer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000254
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100255 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000256 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000257
kwiberg27f982b2016-03-01 11:52:33 -0800258 std::unique_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +0000259 test::FrameGenerator::CreateChromaGenerator(
stefanff483612015-12-21 03:14:00 -0800260 video_encoder_config_.streams[0].width,
261 video_encoder_config_.streams[0].height));
262 video_send_stream_->Input()->IncomingCapturedFrame(
263 *frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000264
Peter Boström5811a392015-12-10 13:02:50 +0100265 EXPECT_TRUE(renderer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000266 << "Timed out while waiting for the frame to render.";
267
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000268 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000269
270 sender_transport.StopSending();
271 receiver_transport.StopSending();
272
273 DestroyStreams();
274}
275
Perba7dc722016-04-19 15:01:23 +0200276class CodecObserver : public test::EndToEndTest,
nisse7ade7b32016-03-23 04:48:10 -0700277 public rtc::VideoSinkInterface<VideoFrame> {
Perba7dc722016-04-19 15:01:23 +0200278 public:
279 CodecObserver(int no_frames_to_wait_for,
280 VideoRotation rotation_to_test,
281 const std::string& payload_name,
282 webrtc::VideoEncoder* encoder,
283 webrtc::VideoDecoder* decoder)
284 : EndToEndTest(2 * webrtc::EndToEndTest::kDefaultTimeoutMs),
285 no_frames_to_wait_for_(no_frames_to_wait_for),
286 expected_rotation_(rotation_to_test),
287 payload_name_(payload_name),
288 encoder_(encoder),
289 decoder_(decoder),
290 frame_counter_(0) {}
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000291
Perba7dc722016-04-19 15:01:23 +0200292 void PerformTest() override {
293 EXPECT_TRUE(Wait())
294 << "Timed out while waiting for enough frames to be decoded.";
295 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000296
Perba7dc722016-04-19 15:01:23 +0200297 void ModifyVideoConfigs(
298 VideoSendStream::Config* send_config,
299 std::vector<VideoReceiveStream::Config>* receive_configs,
300 VideoEncoderConfig* encoder_config) override {
301 send_config->encoder_settings.encoder = encoder_.get();
302 send_config->encoder_settings.payload_name = payload_name_;
303 send_config->encoder_settings.payload_type = 126;
304 encoder_config->streams[0].min_bitrate_bps = 50000;
305 encoder_config->streams[0].target_bitrate_bps =
306 encoder_config->streams[0].max_bitrate_bps = 2000000;
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000307
Perba7dc722016-04-19 15:01:23 +0200308 (*receive_configs)[0].renderer = this;
309 (*receive_configs)[0].decoders.resize(1);
310 (*receive_configs)[0].decoders[0].payload_type =
311 send_config->encoder_settings.payload_type;
312 (*receive_configs)[0].decoders[0].payload_name =
313 send_config->encoder_settings.payload_name;
314 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
315 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000316
Perba7dc722016-04-19 15:01:23 +0200317 void OnFrame(const VideoFrame& video_frame) override {
318 EXPECT_EQ(expected_rotation_, video_frame.rotation());
319 if (++frame_counter_ == no_frames_to_wait_for_)
320 observation_complete_.Set();
321 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000322
Perba7dc722016-04-19 15:01:23 +0200323 void OnFrameGeneratorCapturerCreated(
324 test::FrameGeneratorCapturer* frame_generator_capturer) override {
325 frame_generator_capturer->SetFakeRotation(expected_rotation_);
326 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000327
Perba7dc722016-04-19 15:01:23 +0200328 private:
329 int no_frames_to_wait_for_;
330 VideoRotation expected_rotation_;
331 std::string payload_name_;
332 std::unique_ptr<webrtc::VideoEncoder> encoder_;
333 std::unique_ptr<webrtc::VideoDecoder> decoder_;
334 int frame_counter_;
335};
336
337TEST_F(EndToEndTest, SendsAndReceivesVP8Rotation90) {
338 CodecObserver test(5, kVideoRotation_90, "VP8",
339 VideoEncoder::Create(VideoEncoder::kVp8),
340 VP8Decoder::Create());
341 RunBaseTest(&test);
342}
343
Peter Boström12996152016-05-14 02:03:18 +0200344#if !defined(RTC_DISABLE_VP9)
Perba7dc722016-04-19 15:01:23 +0200345TEST_F(EndToEndTest, SendsAndReceivesVP9) {
346 CodecObserver test(500, kVideoRotation_0, "VP9",
347 VideoEncoder::Create(VideoEncoder::kVp9),
348 VP9Decoder::Create());
349 RunBaseTest(&test);
350}
351
352TEST_F(EndToEndTest, SendsAndReceivesVP9VideoRotation90) {
353 CodecObserver test(5, kVideoRotation_90, "VP9",
354 VideoEncoder::Create(VideoEncoder::kVp9),
355 VP9Decoder::Create());
stefane74eef12016-01-08 06:47:13 -0800356 RunBaseTest(&test);
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000357}
Peter Boström12996152016-05-14 02:03:18 +0200358#endif // !defined(RTC_DISABLE_VP9)
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000359
hbosbab934b2016-01-27 01:36:03 -0800360#if defined(WEBRTC_END_TO_END_H264_TESTS)
361
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000362TEST_F(EndToEndTest, SendsAndReceivesH264) {
Perba7dc722016-04-19 15:01:23 +0200363 CodecObserver test(500, kVideoRotation_0, "H264",
364 VideoEncoder::Create(VideoEncoder::kH264),
365 H264Decoder::Create());
366 RunBaseTest(&test);
367}
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000368
Perba7dc722016-04-19 15:01:23 +0200369TEST_F(EndToEndTest, SendsAndReceivesH264VideoRotation90) {
370 CodecObserver test(5, kVideoRotation_90, "H264",
371 VideoEncoder::Create(VideoEncoder::kH264),
372 H264Decoder::Create());
stefane74eef12016-01-08 06:47:13 -0800373 RunBaseTest(&test);
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000374}
375
hbosbab934b2016-01-27 01:36:03 -0800376#endif // defined(WEBRTC_END_TO_END_H264_TESTS)
377
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000378TEST_F(EndToEndTest, ReceiverUsesLocalSsrc) {
379 class SyncRtcpObserver : public test::EndToEndTest {
380 public:
381 SyncRtcpObserver() : EndToEndTest(kDefaultTimeoutMs) {}
382
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000383 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000384 RTCPUtility::RTCPParserV2 parser(packet, length, true);
385 EXPECT_TRUE(parser.IsValid());
386 uint32_t ssrc = 0;
387 ssrc |= static_cast<uint32_t>(packet[4]) << 24;
388 ssrc |= static_cast<uint32_t>(packet[5]) << 16;
389 ssrc |= static_cast<uint32_t>(packet[6]) << 8;
390 ssrc |= static_cast<uint32_t>(packet[7]) << 0;
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100391 EXPECT_EQ(kReceiverLocalVideoSsrc, ssrc);
Peter Boström5811a392015-12-10 13:02:50 +0100392 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000393
394 return SEND_PACKET;
395 }
396
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000397 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100398 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000399 << "Timed out while waiting for a receiver RTCP packet to be sent.";
400 }
401 } test;
402
stefane74eef12016-01-08 06:47:13 -0800403 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000404}
405
406TEST_F(EndToEndTest, ReceivesAndRetransmitsNack) {
407 static const int kNumberOfNacksToObserve = 2;
408 static const int kLossBurstSize = 2;
409 static const int kPacketsBetweenLossBursts = 9;
410 class NackObserver : public test::EndToEndTest {
411 public:
412 NackObserver()
413 : EndToEndTest(kLongTimeoutMs),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000414 sent_rtp_packets_(0),
415 packets_left_to_drop_(0),
416 nacks_left_(kNumberOfNacksToObserve) {}
417
418 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000419 Action OnSendRtp(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 RTPHeader header;
Peter Boström03671cb2015-12-07 15:22:24 +0100422 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000423
424 // Never drop retransmitted packets.
425 if (dropped_packets_.find(header.sequenceNumber) !=
426 dropped_packets_.end()) {
427 retransmitted_packets_.insert(header.sequenceNumber);
Stefan Holmer586b19b2015-09-18 11:14:31 +0200428 if (nacks_left_ <= 0 &&
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000429 retransmitted_packets_.size() == dropped_packets_.size()) {
Peter Boström5811a392015-12-10 13:02:50 +0100430 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000431 }
432 return SEND_PACKET;
433 }
434
435 ++sent_rtp_packets_;
436
437 // Enough NACKs received, stop dropping packets.
Stefan Holmer586b19b2015-09-18 11:14:31 +0200438 if (nacks_left_ <= 0)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000439 return SEND_PACKET;
440
441 // Check if it's time for a new loss burst.
442 if (sent_rtp_packets_ % kPacketsBetweenLossBursts == 0)
443 packets_left_to_drop_ = kLossBurstSize;
444
Stefan Holmer01b48882015-05-05 10:21:24 +0200445 // Never drop padding packets as those won't be retransmitted.
446 if (packets_left_to_drop_ > 0 && header.paddingLength == 0) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000447 --packets_left_to_drop_;
448 dropped_packets_.insert(header.sequenceNumber);
449 return DROP_PACKET;
450 }
451
452 return SEND_PACKET;
453 }
454
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000455 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700456 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000457 RTCPUtility::RTCPParserV2 parser(packet, length, true);
458 EXPECT_TRUE(parser.IsValid());
459
460 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +0200461 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
462 if (packet_type == RTCPUtility::RTCPPacketTypes::kRtpfbNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000463 --nacks_left_;
464 break;
465 }
466 packet_type = parser.Iterate();
467 }
468 return SEND_PACKET;
469 }
470
stefanff483612015-12-21 03:14:00 -0800471 void ModifyVideoConfigs(
472 VideoSendStream::Config* send_config,
473 std::vector<VideoReceiveStream::Config>* receive_configs,
474 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000475 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000476 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000477 }
478
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000479 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100480 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000481 << "Timed out waiting for packets to be NACKed, retransmitted and "
482 "rendered.";
483 }
484
stefanf116bd02015-10-27 08:29:42 -0700485 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000486 std::set<uint16_t> dropped_packets_;
487 std::set<uint16_t> retransmitted_packets_;
488 uint64_t sent_rtp_packets_;
489 int packets_left_to_drop_;
stefanf116bd02015-10-27 08:29:42 -0700490 int nacks_left_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000491 } test;
492
stefane74eef12016-01-08 06:47:13 -0800493 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000494}
495
Erik Språng737336d2016-07-29 12:59:36 +0200496TEST_F(EndToEndTest, ReceivesNackAndRetransmitsAudio) {
497 class NackObserver : public test::EndToEndTest {
498 public:
499 NackObserver()
500 : EndToEndTest(kLongTimeoutMs),
501 local_ssrc_(0),
502 remote_ssrc_(0),
503 receive_transport_(nullptr) {}
504
505 private:
506 size_t GetNumVideoStreams() const override { return 0; }
507 size_t GetNumAudioStreams() const override { return 1; }
508
509 test::PacketTransport* CreateReceiveTransport() override {
510 test::PacketTransport* receive_transport = new test::PacketTransport(
511 nullptr, this, test::PacketTransport::kReceiver,
512 FakeNetworkPipe::Config());
513 receive_transport_ = receive_transport;
514 return receive_transport;
515 }
516
517 Action OnSendRtp(const uint8_t* packet, size_t length) override {
518 RTPHeader header;
519 EXPECT_TRUE(parser_->Parse(packet, length, &header));
520
521 if (!sequence_number_to_retransmit_) {
522 sequence_number_to_retransmit_ =
523 rtc::Optional<uint16_t>(header.sequenceNumber);
524
525 // Don't ask for retransmission straight away, may be deduped in pacer.
526 } else if (header.sequenceNumber == *sequence_number_to_retransmit_) {
527 observation_complete_.Set();
528 } else {
529 // Send a NACK as often as necessary until retransmission is received.
530 rtcp::Nack nack;
531 nack.From(local_ssrc_);
532 nack.To(remote_ssrc_);
533 uint16_t nack_list[] = {*sequence_number_to_retransmit_};
534 nack.WithList(nack_list, 1);
535 rtc::Buffer buffer = nack.Build();
536
537 EXPECT_TRUE(receive_transport_->SendRtcp(buffer.data(), buffer.size()));
538 }
539
540 return SEND_PACKET;
541 }
542
543 void ModifyAudioConfigs(
544 AudioSendStream::Config* send_config,
545 std::vector<AudioReceiveStream::Config>* receive_configs) override {
546 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
547 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
548 local_ssrc_ = (*receive_configs)[0].rtp.local_ssrc;
549 remote_ssrc_ = (*receive_configs)[0].rtp.remote_ssrc;
550 }
551
552 void PerformTest() override {
553 EXPECT_TRUE(Wait())
554 << "Timed out waiting for packets to be NACKed, retransmitted and "
555 "rendered.";
556 }
557
558 uint32_t local_ssrc_;
559 uint32_t remote_ssrc_;
560 Transport* receive_transport_;
561 rtc::Optional<uint16_t> sequence_number_to_retransmit_;
562 } test;
563
564 RunBaseTest(&test);
565}
566
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000567TEST_F(EndToEndTest, CanReceiveFec) {
nisse7ade7b32016-03-23 04:48:10 -0700568 class FecRenderObserver : public test::EndToEndTest,
569 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000570 public:
571 FecRenderObserver()
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000572 : EndToEndTest(kDefaultTimeoutMs), state_(kFirstPacket) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000573
574 private:
stefanf116bd02015-10-27 08:29:42 -0700575 Action OnSendRtp(const uint8_t* packet, size_t length) override {
576 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000577 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000578 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000579
Stefan Holmer01b48882015-05-05 10:21:24 +0200580 int encapsulated_payload_type = -1;
581 if (header.payloadType == kRedPayloadType) {
582 encapsulated_payload_type =
583 static_cast<int>(packet[header.headerLength]);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100584 if (encapsulated_payload_type != kFakeVideoSendPayloadType)
Stefan Holmer01b48882015-05-05 10:21:24 +0200585 EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
586 } else {
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100587 EXPECT_EQ(kFakeVideoSendPayloadType, header.payloadType);
Stefan Holmer01b48882015-05-05 10:21:24 +0200588 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000589
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000590 if (protected_sequence_numbers_.count(header.sequenceNumber) != 0) {
591 // Retransmitted packet, should not count.
592 protected_sequence_numbers_.erase(header.sequenceNumber);
593 EXPECT_GT(protected_timestamps_.count(header.timestamp), 0u);
594 protected_timestamps_.erase(header.timestamp);
595 return SEND_PACKET;
596 }
597
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000598 switch (state_) {
599 case kFirstPacket:
600 state_ = kDropEveryOtherPacketUntilFec;
601 break;
602 case kDropEveryOtherPacketUntilFec:
603 if (encapsulated_payload_type == kUlpfecPayloadType) {
604 state_ = kDropNextMediaPacket;
605 return SEND_PACKET;
606 }
607 if (header.sequenceNumber % 2 == 0)
608 return DROP_PACKET;
609 break;
610 case kDropNextMediaPacket:
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100611 if (encapsulated_payload_type == kFakeVideoSendPayloadType) {
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000612 protected_sequence_numbers_.insert(header.sequenceNumber);
613 protected_timestamps_.insert(header.timestamp);
614 state_ = kDropEveryOtherPacketUntilFec;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000615 return DROP_PACKET;
616 }
617 break;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000618 }
619
620 return SEND_PACKET;
621 }
622
nisseeb83a1a2016-03-21 01:27:56 -0700623 void OnFrame(const VideoFrame& video_frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200624 rtc::CritScope lock(&crit_);
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000625 // Rendering frame with timestamp of packet that was dropped -> FEC
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000626 // protection worked.
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000627 if (protected_timestamps_.count(video_frame.timestamp()) != 0)
Peter Boström5811a392015-12-10 13:02:50 +0100628 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000629 }
630
631 enum {
632 kFirstPacket,
633 kDropEveryOtherPacketUntilFec,
634 kDropNextMediaPacket,
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000635 } state_;
636
stefanff483612015-12-21 03:14:00 -0800637 void ModifyVideoConfigs(
638 VideoSendStream::Config* send_config,
639 std::vector<VideoReceiveStream::Config>* receive_configs,
640 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000641 // TODO(pbos): Run this test with combined NACK/FEC enabled as well.
642 // int rtp_history_ms = 1000;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000643 // (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000644 // send_config->rtp.nack.rtp_history_ms = rtp_history_ms;
645 send_config->rtp.fec.red_payload_type = kRedPayloadType;
646 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
647
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000648 (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
649 (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
650 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000651 }
652
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000653 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100654 EXPECT_TRUE(Wait())
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000655 << "Timed out waiting for dropped frames frames to be rendered.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000656 }
657
stefanf116bd02015-10-27 08:29:42 -0700658 rtc::CriticalSection crit_;
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000659 std::set<uint32_t> protected_sequence_numbers_ GUARDED_BY(crit_);
660 std::set<uint32_t> protected_timestamps_ GUARDED_BY(crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000661 } test;
662
stefane74eef12016-01-08 06:47:13 -0800663 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000664}
665
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200666TEST_F(EndToEndTest, ReceivedFecPacketsNotNacked) {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000667 class FecNackObserver : public test::EndToEndTest {
668 public:
mflodmand1590b22015-12-09 07:07:59 -0800669 FecNackObserver()
stefanf116bd02015-10-27 08:29:42 -0700670 : EndToEndTest(kDefaultTimeoutMs),
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000671 state_(kFirstPacket),
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000672 fec_sequence_number_(0),
673 has_last_sequence_number_(false),
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200674 last_sequence_number_(0),
675 encoder_(VideoEncoder::Create(VideoEncoder::EncoderType::kVp8)),
676 decoder_(VP8Decoder::Create()) {}
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000677
678 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000679 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -0800680 rtc::CritScope lock_(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000681 RTPHeader header;
682 EXPECT_TRUE(parser_->Parse(packet, length, &header));
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000683
Stefan Holmer01b48882015-05-05 10:21:24 +0200684 int encapsulated_payload_type = -1;
685 if (header.payloadType == kRedPayloadType) {
686 encapsulated_payload_type =
687 static_cast<int>(packet[header.headerLength]);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100688 if (encapsulated_payload_type != kFakeVideoSendPayloadType)
Stefan Holmer01b48882015-05-05 10:21:24 +0200689 EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
690 } else {
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100691 EXPECT_EQ(kFakeVideoSendPayloadType, header.payloadType);
Stefan Holmer01b48882015-05-05 10:21:24 +0200692 }
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000693
694 if (has_last_sequence_number_ &&
695 !IsNewerSequenceNumber(header.sequenceNumber,
696 last_sequence_number_)) {
697 // Drop retransmitted packets.
698 return DROP_PACKET;
699 }
700 last_sequence_number_ = header.sequenceNumber;
701 has_last_sequence_number_ = true;
702
703 bool fec_packet = encapsulated_payload_type == kUlpfecPayloadType;
704 switch (state_) {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000705 case kFirstPacket:
706 state_ = kDropEveryOtherPacketUntilFec;
707 break;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000708 case kDropEveryOtherPacketUntilFec:
709 if (fec_packet) {
710 state_ = kDropAllMediaPacketsUntilFec;
711 } else if (header.sequenceNumber % 2 == 0) {
712 return DROP_PACKET;
713 }
714 break;
715 case kDropAllMediaPacketsUntilFec:
716 if (!fec_packet)
717 return DROP_PACKET;
718 fec_sequence_number_ = header.sequenceNumber;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200719 state_ = kDropOneMediaPacket;
720 break;
721 case kDropOneMediaPacket:
722 if (fec_packet)
723 return DROP_PACKET;
724 state_ = kPassOneMediaPacket;
725 return DROP_PACKET;
726 break;
727 case kPassOneMediaPacket:
728 if (fec_packet)
729 return DROP_PACKET;
730 // Pass one media packet after dropped packet after last FEC,
731 // otherwise receiver might never see a seq_no after
732 // |fec_sequence_number_|
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000733 state_ = kVerifyFecPacketNotInNackList;
734 break;
735 case kVerifyFecPacketNotInNackList:
736 // Continue to drop packets. Make sure no frame can be decoded.
737 if (fec_packet || header.sequenceNumber % 2 == 0)
738 return DROP_PACKET;
739 break;
740 }
741 return SEND_PACKET;
742 }
743
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000744 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -0800745 rtc::CritScope lock_(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000746 if (state_ == kVerifyFecPacketNotInNackList) {
747 test::RtcpPacketParser rtcp_parser;
748 rtcp_parser.Parse(packet, length);
749 std::vector<uint16_t> nacks = rtcp_parser.nack_item()->last_nack_list();
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200750 EXPECT_TRUE(std::find(nacks.begin(), nacks.end(),
751 fec_sequence_number_) == nacks.end())
752 << "Got nack for FEC packet";
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000753 if (!nacks.empty() &&
754 IsNewerSequenceNumber(nacks.back(), fec_sequence_number_)) {
Peter Boström5811a392015-12-10 13:02:50 +0100755 observation_complete_.Set();
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000756 }
757 }
758 return SEND_PACKET;
759 }
760
stefane74eef12016-01-08 06:47:13 -0800761 test::PacketTransport* CreateSendTransport(Call* sender_call) override {
762 // At low RTT (< kLowRttNackMs) -> NACK only, no FEC.
763 // Configure some network delay.
764 const int kNetworkDelayMs = 50;
765 FakeNetworkPipe::Config config;
766 config.queue_delay_ms = kNetworkDelayMs;
767 return new test::PacketTransport(sender_call, this,
768 test::PacketTransport::kSender, config);
769 }
770
Stefan Holmere5904162015-03-26 11:11:06 +0100771 // TODO(holmer): Investigate why we don't send FEC packets when the bitrate
772 // is 10 kbps.
773 Call::Config GetSenderCallConfig() override {
solenberg4fbae2b2015-08-28 04:07:10 -0700774 Call::Config config;
Stefan Holmere5904162015-03-26 11:11:06 +0100775 const int kMinBitrateBps = 30000;
776 config.bitrate_config.min_bitrate_bps = kMinBitrateBps;
777 return config;
778 }
779
stefanff483612015-12-21 03:14:00 -0800780 void ModifyVideoConfigs(
781 VideoSendStream::Config* send_config,
782 std::vector<VideoReceiveStream::Config>* receive_configs,
783 VideoEncoderConfig* encoder_config) override {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000784 // Configure hybrid NACK/FEC.
785 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
786 send_config->rtp.fec.red_payload_type = kRedPayloadType;
787 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200788 // Set codec to VP8, otherwise NACK/FEC hybrid will be disabled.
789 send_config->encoder_settings.encoder = encoder_.get();
790 send_config->encoder_settings.payload_name = "VP8";
791 send_config->encoder_settings.payload_type = kFakeVideoSendPayloadType;
792 encoder_config->streams[0].min_bitrate_bps = 50000;
793 encoder_config->streams[0].max_bitrate_bps =
794 encoder_config->streams[0].target_bitrate_bps = 2000000;
795
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000796 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
797 (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
798 (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200799
800 (*receive_configs)[0].decoders.resize(1);
801 (*receive_configs)[0].decoders[0].payload_type =
802 send_config->encoder_settings.payload_type;
803 (*receive_configs)[0].decoders[0].payload_name =
804 send_config->encoder_settings.payload_name;
805 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000806 }
807
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000808 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100809 EXPECT_TRUE(Wait())
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000810 << "Timed out while waiting for FEC packets to be received.";
811 }
812
813 enum {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000814 kFirstPacket,
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000815 kDropEveryOtherPacketUntilFec,
816 kDropAllMediaPacketsUntilFec,
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200817 kDropOneMediaPacket,
818 kPassOneMediaPacket,
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000819 kVerifyFecPacketNotInNackList,
820 } state_;
821
stefan608213e2015-11-01 14:56:10 -0800822 rtc::CriticalSection crit_;
823 uint16_t fec_sequence_number_ GUARDED_BY(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000824 bool has_last_sequence_number_;
825 uint16_t last_sequence_number_;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200826 std::unique_ptr<webrtc::VideoEncoder> encoder_;
827 std::unique_ptr<webrtc::VideoDecoder> decoder_;
stefanf116bd02015-10-27 08:29:42 -0700828 } test;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000829
stefane74eef12016-01-08 06:47:13 -0800830 RunBaseTest(&test);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000831}
832
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000833// This test drops second RTP packet with a marker bit set, makes sure it's
834// retransmitted and renders. Retransmission SSRCs are also checked.
Peter Boström39593972016-02-15 11:27:15 +0100835void EndToEndTest::DecodesRetransmittedFrame(bool enable_rtx, bool enable_red) {
Peter Boström67680c12016-02-17 11:10:04 +0100836 static const int kDroppedFrameNumber = 10;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000837 class RetransmissionObserver : public test::EndToEndTest,
838 public I420FrameCallback {
839 public:
Peter Boström39593972016-02-15 11:27:15 +0100840 RetransmissionObserver(bool enable_rtx, bool enable_red)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000841 : EndToEndTest(kDefaultTimeoutMs),
Peter Boström39593972016-02-15 11:27:15 +0100842 payload_type_(GetPayloadType(false, enable_red)),
843 retransmission_ssrc_(enable_rtx ? kSendRtxSsrcs[0]
844 : kVideoSendSsrcs[0]),
845 retransmission_payload_type_(GetPayloadType(enable_rtx, enable_red)),
846 encoder_(VideoEncoder::Create(VideoEncoder::EncoderType::kVp8)),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000847 marker_bits_observed_(0),
danilchap192717e2016-07-25 08:20:51 -0700848 retransmitted_timestamp_(0) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000849
850 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000851 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700852 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000853 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000854 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000855
Peter Boström67680c12016-02-17 11:10:04 +0100856 // Ignore padding-only packets over RTX.
857 if (header.payloadType != payload_type_) {
858 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
859 if (length == header.headerLength + header.paddingLength)
860 return SEND_PACKET;
Stefan Holmer586b19b2015-09-18 11:14:31 +0200861 }
Peter Boström67680c12016-02-17 11:10:04 +0100862
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000863 if (header.timestamp == retransmitted_timestamp_) {
864 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
865 EXPECT_EQ(retransmission_payload_type_, header.payloadType);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000866 return SEND_PACKET;
867 }
868
Stefan Holmer586b19b2015-09-18 11:14:31 +0200869 // Found the final packet of the frame to inflict loss to, drop this and
870 // expect a retransmission.
danilchapfdd381c2016-07-25 04:03:20 -0700871 if (header.payloadType == payload_type_ && header.markerBit &&
872 ++marker_bits_observed_ == kDroppedFrameNumber) {
Danil Chapovalov18c65a42016-06-29 15:29:34 +0200873 // This should be the only dropped packet.
874 EXPECT_EQ(0u, retransmitted_timestamp_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000875 retransmitted_timestamp_ = header.timestamp;
danilchap192717e2016-07-25 08:20:51 -0700876 if (std::find(rendered_timestamps_.begin(), rendered_timestamps_.end(),
877 retransmitted_timestamp_) != rendered_timestamps_.end()) {
878 // Frame was rendered before last packet was scheduled for sending.
879 // This is extremly rare but possible scenario because prober able to
880 // resend packet before it was send.
881 // TODO(danilchap): Remove this corner case when prober would not be
882 // able to sneak in between packet saved to history for resending and
883 // pacer notified about existance of that packet for sending.
884 // See https://bugs.chromium.org/p/webrtc/issues/detail?id=5540 for
885 // details.
886 observation_complete_.Set();
887 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000888 return DROP_PACKET;
889 }
890
891 return SEND_PACKET;
892 }
893
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700894 void FrameCallback(VideoFrame* frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200895 rtc::CritScope lock(&crit_);
danilchap192717e2016-07-25 08:20:51 -0700896 if (frame->timestamp() == retransmitted_timestamp_)
Peter Boström5811a392015-12-10 13:02:50 +0100897 observation_complete_.Set();
danilchap192717e2016-07-25 08:20:51 -0700898 rendered_timestamps_.push_back(frame->timestamp());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000899 }
900
stefanff483612015-12-21 03:14:00 -0800901 void ModifyVideoConfigs(
902 VideoSendStream::Config* send_config,
903 std::vector<VideoReceiveStream::Config>* receive_configs,
904 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000905 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000906 (*receive_configs)[0].pre_render_callback = this;
907 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
Shao Changbine62202f2015-04-21 20:24:50 +0800908
909 if (payload_type_ == kRedPayloadType) {
910 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
911 send_config->rtp.fec.red_payload_type = kRedPayloadType;
Stefan Holmer10880012016-02-03 13:29:59 +0100912 if (retransmission_ssrc_ == kSendRtxSsrcs[0])
913 send_config->rtp.fec.red_rtx_payload_type = kRtxRedPayloadType;
914 (*receive_configs)[0].rtp.fec.ulpfec_payload_type =
915 send_config->rtp.fec.ulpfec_payload_type;
916 (*receive_configs)[0].rtp.fec.red_payload_type =
917 send_config->rtp.fec.red_payload_type;
918 (*receive_configs)[0].rtp.fec.red_rtx_payload_type =
919 send_config->rtp.fec.red_rtx_payload_type;
Shao Changbine62202f2015-04-21 20:24:50 +0800920 }
921
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000922 if (retransmission_ssrc_ == kSendRtxSsrcs[0]) {
923 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000924 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
Stefan Holmer10880012016-02-03 13:29:59 +0100925 (*receive_configs)[0].rtp.rtx[payload_type_].ssrc = kSendRtxSsrcs[0];
926 (*receive_configs)[0].rtp.rtx[payload_type_].payload_type =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000927 kSendRtxPayloadType;
928 }
Peter Boström39593972016-02-15 11:27:15 +0100929 // Configure encoding and decoding with VP8, since generic packetization
930 // doesn't support FEC with NACK.
931 RTC_DCHECK_EQ(1u, (*receive_configs)[0].decoders.size());
932 send_config->encoder_settings.encoder = encoder_.get();
933 send_config->encoder_settings.payload_name = "VP8";
934 (*receive_configs)[0].decoders[0].payload_name = "VP8";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000935 }
936
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000937 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100938 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000939 << "Timed out while waiting for retransmission to render.";
940 }
941
Shao Changbine62202f2015-04-21 20:24:50 +0800942 int GetPayloadType(bool use_rtx, bool use_red) {
Stefan Holmer10880012016-02-03 13:29:59 +0100943 if (use_red) {
944 if (use_rtx)
945 return kRtxRedPayloadType;
946 return kRedPayloadType;
947 }
948 if (use_rtx)
949 return kSendRtxPayloadType;
950 return kFakeVideoSendPayloadType;
Shao Changbine62202f2015-04-21 20:24:50 +0800951 }
952
stefanf116bd02015-10-27 08:29:42 -0700953 rtc::CriticalSection crit_;
Shao Changbine62202f2015-04-21 20:24:50 +0800954 const int payload_type_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000955 const uint32_t retransmission_ssrc_;
956 const int retransmission_payload_type_;
kwiberg27f982b2016-03-01 11:52:33 -0800957 std::unique_ptr<VideoEncoder> encoder_;
Peter Boström39593972016-02-15 11:27:15 +0100958 const std::string payload_name_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000959 int marker_bits_observed_;
stefanf116bd02015-10-27 08:29:42 -0700960 uint32_t retransmitted_timestamp_ GUARDED_BY(&crit_);
danilchap192717e2016-07-25 08:20:51 -0700961 std::vector<uint32_t> rendered_timestamps_ GUARDED_BY(&crit_);
Peter Boström39593972016-02-15 11:27:15 +0100962 } test(enable_rtx, enable_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000963
stefane74eef12016-01-08 06:47:13 -0800964 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000965}
966
967TEST_F(EndToEndTest, DecodesRetransmittedFrame) {
Shao Changbine62202f2015-04-21 20:24:50 +0800968 DecodesRetransmittedFrame(false, false);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000969}
970
971TEST_F(EndToEndTest, DecodesRetransmittedFrameOverRtx) {
Shao Changbine62202f2015-04-21 20:24:50 +0800972 DecodesRetransmittedFrame(true, false);
973}
974
975TEST_F(EndToEndTest, DecodesRetransmittedFrameByRed) {
976 DecodesRetransmittedFrame(false, true);
977}
978
979TEST_F(EndToEndTest, DecodesRetransmittedFrameByRedOverRtx) {
980 DecodesRetransmittedFrame(true, true);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000981}
982
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000983void EndToEndTest::ReceivesPliAndRecovers(int rtp_history_ms) {
984 static const int kPacketsToDrop = 1;
985
nisse7ade7b32016-03-23 04:48:10 -0700986 class PliObserver : public test::EndToEndTest,
987 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000988 public:
989 explicit PliObserver(int rtp_history_ms)
990 : EndToEndTest(kLongTimeoutMs),
991 rtp_history_ms_(rtp_history_ms),
992 nack_enabled_(rtp_history_ms > 0),
993 highest_dropped_timestamp_(0),
994 frames_to_drop_(0),
995 received_pli_(false) {}
996
997 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000998 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700999 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001000 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001001 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001002
1003 // Drop all retransmitted packets to force a PLI.
1004 if (header.timestamp <= highest_dropped_timestamp_)
1005 return DROP_PACKET;
1006
1007 if (frames_to_drop_ > 0) {
1008 highest_dropped_timestamp_ = header.timestamp;
1009 --frames_to_drop_;
1010 return DROP_PACKET;
1011 }
1012
1013 return SEND_PACKET;
1014 }
1015
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001016 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -07001017 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001018 RTCPUtility::RTCPParserV2 parser(packet, length, true);
1019 EXPECT_TRUE(parser.IsValid());
1020
1021 for (RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02001022 packet_type != RTCPUtility::RTCPPacketTypes::kInvalid;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001023 packet_type = parser.Iterate()) {
1024 if (!nack_enabled_)
Erik Språng242e22b2015-05-11 10:17:43 +02001025 EXPECT_NE(packet_type, RTCPUtility::RTCPPacketTypes::kRtpfbNack);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001026
Erik Språng242e22b2015-05-11 10:17:43 +02001027 if (packet_type == RTCPUtility::RTCPPacketTypes::kPsfbPli) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001028 received_pli_ = true;
1029 break;
1030 }
1031 }
1032 return SEND_PACKET;
1033 }
1034
nisseeb83a1a2016-03-21 01:27:56 -07001035 void OnFrame(const VideoFrame& video_frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02001036 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001037 if (received_pli_ &&
1038 video_frame.timestamp() > highest_dropped_timestamp_) {
Peter Boström5811a392015-12-10 13:02:50 +01001039 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001040 }
1041 if (!received_pli_)
1042 frames_to_drop_ = kPacketsToDrop;
1043 }
1044
stefanff483612015-12-21 03:14:00 -08001045 void ModifyVideoConfigs(
1046 VideoSendStream::Config* send_config,
1047 std::vector<VideoReceiveStream::Config>* receive_configs,
1048 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001049 send_config->rtp.nack.rtp_history_ms = rtp_history_ms_;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001050 (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms_;
1051 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001052 }
1053
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001054 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001055 EXPECT_TRUE(Wait()) << "Timed out waiting for PLI to be "
1056 "received and a frame to be "
1057 "rendered afterwards.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001058 }
1059
stefanf116bd02015-10-27 08:29:42 -07001060 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001061 int rtp_history_ms_;
1062 bool nack_enabled_;
stefanf116bd02015-10-27 08:29:42 -07001063 uint32_t highest_dropped_timestamp_ GUARDED_BY(&crit_);
1064 int frames_to_drop_ GUARDED_BY(&crit_);
1065 bool received_pli_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001066 } test(rtp_history_ms);
1067
stefane74eef12016-01-08 06:47:13 -08001068 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001069}
1070
1071TEST_F(EndToEndTest, ReceivesPliAndRecoversWithNack) {
1072 ReceivesPliAndRecovers(1000);
1073}
1074
jbauchdb81ffd2015-11-23 03:59:02 -08001075TEST_F(EndToEndTest, ReceivesPliAndRecoversWithoutNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001076 ReceivesPliAndRecovers(0);
1077}
1078
1079TEST_F(EndToEndTest, UnknownRtpPacketGivesUnknownSsrcReturnCode) {
1080 class PacketInputObserver : public PacketReceiver {
1081 public:
1082 explicit PacketInputObserver(PacketReceiver* receiver)
Peter Boström5811a392015-12-10 13:02:50 +01001083 : receiver_(receiver), delivered_packet_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001084
Peter Boström5811a392015-12-10 13:02:50 +01001085 bool Wait() { return delivered_packet_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001086
1087 private:
stefan68786d22015-09-08 05:36:15 -07001088 DeliveryStatus DeliverPacket(MediaType media_type,
1089 const uint8_t* packet,
1090 size_t length,
1091 const PacketTime& packet_time) override {
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001092 if (RtpHeaderParser::IsRtcp(packet, length)) {
stefan68786d22015-09-08 05:36:15 -07001093 return receiver_->DeliverPacket(media_type, packet, length,
1094 packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001095 } else {
1096 DeliveryStatus delivery_status =
stefan68786d22015-09-08 05:36:15 -07001097 receiver_->DeliverPacket(media_type, packet, length, packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001098 EXPECT_EQ(DELIVERY_UNKNOWN_SSRC, delivery_status);
Peter Boström5811a392015-12-10 13:02:50 +01001099 delivered_packet_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001100 return delivery_status;
1101 }
1102 }
1103
1104 PacketReceiver* receiver_;
Peter Boström5811a392015-12-10 13:02:50 +01001105 rtc::Event delivered_packet_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001106 };
1107
solenberg4fbae2b2015-08-28 04:07:10 -07001108 CreateCalls(Call::Config(), Call::Config());
1109
stefanf116bd02015-10-27 08:29:42 -07001110 test::DirectTransport send_transport(sender_call_.get());
1111 test::DirectTransport receive_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001112 PacketInputObserver input_observer(receiver_call_->Receiver());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001113 send_transport.SetReceiver(&input_observer);
1114 receive_transport.SetReceiver(sender_call_->Receiver());
1115
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001116 CreateSendConfig(1, 0, &send_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07001117 CreateMatchingReceiveConfigs(&receive_transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001118
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001119 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001120 CreateFrameGeneratorCapturer();
1121 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001122
stefanff483612015-12-21 03:14:00 -08001123 receiver_call_->DestroyVideoReceiveStream(video_receive_streams_[0]);
1124 video_receive_streams_.clear();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001125
1126 // Wait() waits for a received packet.
Peter Boström5811a392015-12-10 13:02:50 +01001127 EXPECT_TRUE(input_observer.Wait());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001128
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001129 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001130
1131 DestroyStreams();
1132
1133 send_transport.StopSending();
1134 receive_transport.StopSending();
1135}
1136
pbosda903ea2015-10-02 02:36:56 -07001137void EndToEndTest::RespectsRtcpMode(RtcpMode rtcp_mode) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001138 static const int kNumCompoundRtcpPacketsToObserve = 10;
1139 class RtcpModeObserver : public test::EndToEndTest {
1140 public:
pbosda903ea2015-10-02 02:36:56 -07001141 explicit RtcpModeObserver(RtcpMode rtcp_mode)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001142 : EndToEndTest(kDefaultTimeoutMs),
1143 rtcp_mode_(rtcp_mode),
1144 sent_rtp_(0),
1145 sent_rtcp_(0) {}
1146
1147 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001148 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001149 if (++sent_rtp_ % 3 == 0)
1150 return DROP_PACKET;
1151
1152 return SEND_PACKET;
1153 }
1154
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001155 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001156 ++sent_rtcp_;
1157 RTCPUtility::RTCPParserV2 parser(packet, length, true);
1158 EXPECT_TRUE(parser.IsValid());
1159
1160 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
1161 bool has_report_block = false;
Erik Språng242e22b2015-05-11 10:17:43 +02001162 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
1163 EXPECT_NE(RTCPUtility::RTCPPacketTypes::kSr, packet_type);
1164 if (packet_type == RTCPUtility::RTCPPacketTypes::kRr) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001165 has_report_block = true;
1166 break;
1167 }
1168 packet_type = parser.Iterate();
1169 }
1170
1171 switch (rtcp_mode_) {
pbosda903ea2015-10-02 02:36:56 -07001172 case RtcpMode::kCompound:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001173 if (!has_report_block) {
1174 ADD_FAILURE() << "Received RTCP packet without receiver report for "
pbosda903ea2015-10-02 02:36:56 -07001175 "RtcpMode::kCompound.";
Peter Boström5811a392015-12-10 13:02:50 +01001176 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001177 }
1178
1179 if (sent_rtcp_ >= kNumCompoundRtcpPacketsToObserve)
Peter Boström5811a392015-12-10 13:02:50 +01001180 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001181
1182 break;
pbosda903ea2015-10-02 02:36:56 -07001183 case RtcpMode::kReducedSize:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001184 if (!has_report_block)
Peter Boström5811a392015-12-10 13:02:50 +01001185 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001186 break;
pbosda903ea2015-10-02 02:36:56 -07001187 case RtcpMode::kOff:
1188 RTC_NOTREACHED();
1189 break;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001190 }
1191
1192 return SEND_PACKET;
1193 }
1194
stefanff483612015-12-21 03:14:00 -08001195 void ModifyVideoConfigs(
1196 VideoSendStream::Config* send_config,
1197 std::vector<VideoReceiveStream::Config>* receive_configs,
1198 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001199 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001200 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
1201 (*receive_configs)[0].rtp.rtcp_mode = rtcp_mode_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001202 }
1203
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001204 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001205 EXPECT_TRUE(Wait())
pbosda903ea2015-10-02 02:36:56 -07001206 << (rtcp_mode_ == RtcpMode::kCompound
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001207 ? "Timed out before observing enough compound packets."
1208 : "Timed out before receiving a non-compound RTCP packet.");
1209 }
1210
pbosda903ea2015-10-02 02:36:56 -07001211 RtcpMode rtcp_mode_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001212 int sent_rtp_;
1213 int sent_rtcp_;
1214 } test(rtcp_mode);
1215
stefane74eef12016-01-08 06:47:13 -08001216 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001217}
1218
1219TEST_F(EndToEndTest, UsesRtcpCompoundMode) {
pbosda903ea2015-10-02 02:36:56 -07001220 RespectsRtcpMode(RtcpMode::kCompound);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001221}
1222
1223TEST_F(EndToEndTest, UsesRtcpReducedSizeMode) {
pbosda903ea2015-10-02 02:36:56 -07001224 RespectsRtcpMode(RtcpMode::kReducedSize);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001225}
1226
1227// Test sets up a Call multiple senders with different resolutions and SSRCs.
1228// Another is set up to receive all three of these with different renderers.
sprang867fb522015-08-03 04:38:41 -07001229class MultiStreamTest {
1230 public:
1231 static const size_t kNumStreams = 3;
1232 struct CodecSettings {
1233 uint32_t ssrc;
1234 int width;
1235 int height;
1236 } codec_settings[kNumStreams];
1237
1238 MultiStreamTest() {
1239 // TODO(sprang): Cleanup when msvc supports explicit initializers for array.
1240 codec_settings[0] = {1, 640, 480};
1241 codec_settings[1] = {2, 320, 240};
1242 codec_settings[2] = {3, 240, 160};
1243 }
1244
1245 virtual ~MultiStreamTest() {}
1246
1247 void RunTest() {
kwiberg27f982b2016-03-01 11:52:33 -08001248 std::unique_ptr<Call> sender_call(Call::Create(Call::Config()));
1249 std::unique_ptr<Call> receiver_call(Call::Create(Call::Config()));
1250 std::unique_ptr<test::DirectTransport> sender_transport(
stefanf116bd02015-10-27 08:29:42 -07001251 CreateSendTransport(sender_call.get()));
kwiberg27f982b2016-03-01 11:52:33 -08001252 std::unique_ptr<test::DirectTransport> receiver_transport(
stefanf116bd02015-10-27 08:29:42 -07001253 CreateReceiveTransport(receiver_call.get()));
sprang867fb522015-08-03 04:38:41 -07001254 sender_transport->SetReceiver(receiver_call->Receiver());
1255 receiver_transport->SetReceiver(sender_call->Receiver());
1256
kwiberg27f982b2016-03-01 11:52:33 -08001257 std::unique_ptr<VideoEncoder> encoders[kNumStreams];
sprang867fb522015-08-03 04:38:41 -07001258 for (size_t i = 0; i < kNumStreams; ++i)
1259 encoders[i].reset(VideoEncoder::Create(VideoEncoder::kVp8));
1260
1261 VideoSendStream* send_streams[kNumStreams];
1262 VideoReceiveStream* receive_streams[kNumStreams];
1263
1264 test::FrameGeneratorCapturer* frame_generators[kNumStreams];
kwiberg4a206a92016-03-31 10:24:26 -07001265 std::vector<std::unique_ptr<VideoDecoder>> allocated_decoders;
sprang867fb522015-08-03 04:38:41 -07001266 for (size_t i = 0; i < kNumStreams; ++i) {
1267 uint32_t ssrc = codec_settings[i].ssrc;
1268 int width = codec_settings[i].width;
1269 int height = codec_settings[i].height;
1270
solenberg4fbae2b2015-08-28 04:07:10 -07001271 VideoSendStream::Config send_config(sender_transport.get());
sprang867fb522015-08-03 04:38:41 -07001272 send_config.rtp.ssrcs.push_back(ssrc);
1273 send_config.encoder_settings.encoder = encoders[i].get();
1274 send_config.encoder_settings.payload_name = "VP8";
1275 send_config.encoder_settings.payload_type = 124;
1276 VideoEncoderConfig encoder_config;
1277 encoder_config.streams = test::CreateVideoStreams(1);
1278 VideoStream* stream = &encoder_config.streams[0];
1279 stream->width = width;
1280 stream->height = height;
1281 stream->max_framerate = 5;
1282 stream->min_bitrate_bps = stream->target_bitrate_bps =
1283 stream->max_bitrate_bps = 100000;
1284
1285 UpdateSendConfig(i, &send_config, &encoder_config, &frame_generators[i]);
1286
perkj8eb37a32016-08-16 02:40:55 -07001287 send_streams[i] =
1288 sender_call->CreateVideoSendStream(send_config, encoder_config);
sprang867fb522015-08-03 04:38:41 -07001289 send_streams[i]->Start();
1290
solenberg4fbae2b2015-08-28 04:07:10 -07001291 VideoReceiveStream::Config receive_config(receiver_transport.get());
sprang867fb522015-08-03 04:38:41 -07001292 receive_config.rtp.remote_ssrc = ssrc;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001293 receive_config.rtp.local_ssrc = test::CallTest::kReceiverLocalVideoSsrc;
sprang867fb522015-08-03 04:38:41 -07001294 VideoReceiveStream::Decoder decoder =
1295 test::CreateMatchingDecoder(send_config.encoder_settings);
kwiberg4a206a92016-03-31 10:24:26 -07001296 allocated_decoders.push_back(
1297 std::unique_ptr<VideoDecoder>(decoder.decoder));
sprang867fb522015-08-03 04:38:41 -07001298 receive_config.decoders.push_back(decoder);
1299
1300 UpdateReceiveConfig(i, &receive_config);
1301
1302 receive_streams[i] =
Tommi733b5472016-06-10 17:58:01 +02001303 receiver_call->CreateVideoReceiveStream(std::move(receive_config));
sprang867fb522015-08-03 04:38:41 -07001304 receive_streams[i]->Start();
1305
1306 frame_generators[i] = test::FrameGeneratorCapturer::Create(
1307 send_streams[i]->Input(), width, height, 30,
1308 Clock::GetRealTimeClock());
1309 frame_generators[i]->Start();
1310 }
1311
1312 Wait();
1313
1314 for (size_t i = 0; i < kNumStreams; ++i) {
1315 frame_generators[i]->Stop();
1316 sender_call->DestroyVideoSendStream(send_streams[i]);
1317 receiver_call->DestroyVideoReceiveStream(receive_streams[i]);
1318 delete frame_generators[i];
1319 }
1320
1321 sender_transport->StopSending();
1322 receiver_transport->StopSending();
1323 }
1324
1325 protected:
1326 virtual void Wait() = 0;
1327 // Note: frame_generator is a point-to-pointer, since the actual instance
1328 // hasn't been created at the time of this call. Only when packets/frames
1329 // start flowing should this be dereferenced.
1330 virtual void UpdateSendConfig(
1331 size_t stream_index,
1332 VideoSendStream::Config* send_config,
1333 VideoEncoderConfig* encoder_config,
1334 test::FrameGeneratorCapturer** frame_generator) {}
1335 virtual void UpdateReceiveConfig(size_t stream_index,
1336 VideoReceiveStream::Config* receive_config) {
1337 }
stefanf116bd02015-10-27 08:29:42 -07001338 virtual test::DirectTransport* CreateSendTransport(Call* sender_call) {
1339 return new test::DirectTransport(sender_call);
sprang867fb522015-08-03 04:38:41 -07001340 }
stefanf116bd02015-10-27 08:29:42 -07001341 virtual test::DirectTransport* CreateReceiveTransport(Call* receiver_call) {
1342 return new test::DirectTransport(receiver_call);
sprang867fb522015-08-03 04:38:41 -07001343 }
1344};
1345
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001346// Each renderer verifies that it receives the expected resolution, and as soon
1347// as every renderer has received a frame, the test finishes.
andresp@webrtc.org02686112014-09-19 08:24:19 +00001348TEST_F(EndToEndTest, SendsAndReceivesMultipleStreams) {
nisse7ade7b32016-03-23 04:48:10 -07001349 class VideoOutputObserver : public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001350 public:
sprang867fb522015-08-03 04:38:41 -07001351 VideoOutputObserver(const MultiStreamTest::CodecSettings& settings,
1352 uint32_t ssrc,
1353 test::FrameGeneratorCapturer** frame_generator)
1354 : settings_(settings),
1355 ssrc_(ssrc),
1356 frame_generator_(frame_generator),
Peter Boström5811a392015-12-10 13:02:50 +01001357 done_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001358
nisseeb83a1a2016-03-21 01:27:56 -07001359 void OnFrame(const VideoFrame& video_frame) override {
sprang867fb522015-08-03 04:38:41 -07001360 EXPECT_EQ(settings_.width, video_frame.width());
1361 EXPECT_EQ(settings_.height, video_frame.height());
1362 (*frame_generator_)->Stop();
Peter Boström5811a392015-12-10 13:02:50 +01001363 done_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001364 }
1365
sprang867fb522015-08-03 04:38:41 -07001366 uint32_t Ssrc() { return ssrc_; }
1367
Peter Boström5811a392015-12-10 13:02:50 +01001368 bool Wait() { return done_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001369
1370 private:
sprang867fb522015-08-03 04:38:41 -07001371 const MultiStreamTest::CodecSettings& settings_;
1372 const uint32_t ssrc_;
1373 test::FrameGeneratorCapturer** const frame_generator_;
Peter Boström5811a392015-12-10 13:02:50 +01001374 rtc::Event done_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001375 };
1376
sprang867fb522015-08-03 04:38:41 -07001377 class Tester : public MultiStreamTest {
1378 public:
1379 Tester() {}
1380 virtual ~Tester() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001381
sprang867fb522015-08-03 04:38:41 -07001382 protected:
1383 void Wait() override {
1384 for (const auto& observer : observers_) {
Peter Boström5811a392015-12-10 13:02:50 +01001385 EXPECT_TRUE(observer->Wait()) << "Time out waiting for from on ssrc "
1386 << observer->Ssrc();
sprang867fb522015-08-03 04:38:41 -07001387 }
1388 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001389
sprang867fb522015-08-03 04:38:41 -07001390 void UpdateSendConfig(
1391 size_t stream_index,
1392 VideoSendStream::Config* send_config,
1393 VideoEncoderConfig* encoder_config,
1394 test::FrameGeneratorCapturer** frame_generator) override {
1395 observers_[stream_index].reset(new VideoOutputObserver(
1396 codec_settings[stream_index], send_config->rtp.ssrcs.front(),
1397 frame_generator));
1398 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001399
sprang867fb522015-08-03 04:38:41 -07001400 void UpdateReceiveConfig(
1401 size_t stream_index,
1402 VideoReceiveStream::Config* receive_config) override {
1403 receive_config->renderer = observers_[stream_index].get();
1404 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001405
sprang867fb522015-08-03 04:38:41 -07001406 private:
kwiberg27f982b2016-03-01 11:52:33 -08001407 std::unique_ptr<VideoOutputObserver> observers_[kNumStreams];
sprang867fb522015-08-03 04:38:41 -07001408 } tester;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001409
sprang867fb522015-08-03 04:38:41 -07001410 tester.RunTest();
1411}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001412
sprang867fb522015-08-03 04:38:41 -07001413TEST_F(EndToEndTest, AssignsTransportSequenceNumbers) {
sprang867fb522015-08-03 04:38:41 -07001414 static const int kExtensionId = 5;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001415
sprang867fb522015-08-03 04:38:41 -07001416 class RtpExtensionHeaderObserver : public test::DirectTransport {
1417 public:
stefanf116bd02015-10-27 08:29:42 -07001418 RtpExtensionHeaderObserver(Call* sender_call,
1419 const uint32_t& first_media_ssrc,
sprang861c55e2015-10-16 10:01:21 -07001420 const std::map<uint32_t, uint32_t>& ssrc_map)
stefanf116bd02015-10-27 08:29:42 -07001421 : DirectTransport(sender_call),
Peter Boström5811a392015-12-10 13:02:50 +01001422 done_(false, false),
sprang867fb522015-08-03 04:38:41 -07001423 parser_(RtpHeaderParser::Create()),
sprang861c55e2015-10-16 10:01:21 -07001424 first_media_ssrc_(first_media_ssrc),
1425 rtx_to_media_ssrcs_(ssrc_map),
sprang867fb522015-08-03 04:38:41 -07001426 padding_observed_(false),
sprang861c55e2015-10-16 10:01:21 -07001427 rtx_padding_observed_(false),
1428 retransmit_observed_(false),
1429 started_(false) {
sprang867fb522015-08-03 04:38:41 -07001430 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
1431 kExtensionId);
1432 }
1433 virtual ~RtpExtensionHeaderObserver() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001434
stefan1d8a5062015-10-02 03:39:33 -07001435 bool SendRtp(const uint8_t* data,
1436 size_t length,
1437 const PacketOptions& options) override {
sprang861c55e2015-10-16 10:01:21 -07001438 {
1439 rtc::CritScope cs(&lock_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001440
Erik Språng8d629712015-08-04 16:24:03 +02001441 if (IsDone())
sprang861c55e2015-10-16 10:01:21 -07001442 return false;
1443
1444 if (started_) {
1445 RTPHeader header;
1446 EXPECT_TRUE(parser_->Parse(data, length, &header));
1447 bool drop_packet = false;
1448
1449 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
1450 EXPECT_EQ(options.packet_id,
1451 header.extension.transportSequenceNumber);
1452 if (!streams_observed_.empty()) {
1453 // Unwrap packet id and verify uniqueness.
1454 int64_t packet_id = unwrapper_.Unwrap(options.packet_id);
1455 EXPECT_TRUE(received_packed_ids_.insert(packet_id).second);
1456 }
1457
1458 // Drop (up to) every 17th packet, so we get retransmits.
1459 // Only drop media, and not on the first stream (otherwise it will be
1460 // hard to distinguish from padding, which is always sent on the first
1461 // stream).
1462 if (header.payloadType != kSendRtxPayloadType &&
1463 header.ssrc != first_media_ssrc_ &&
1464 header.extension.transportSequenceNumber % 17 == 0) {
1465 dropped_seq_[header.ssrc].insert(header.sequenceNumber);
1466 drop_packet = true;
1467 }
1468
1469 size_t payload_length =
1470 length - (header.headerLength + header.paddingLength);
1471 if (payload_length == 0) {
1472 padding_observed_ = true;
1473 } else if (header.payloadType == kSendRtxPayloadType) {
1474 uint16_t original_sequence_number =
1475 ByteReader<uint16_t>::ReadBigEndian(&data[header.headerLength]);
1476 uint32_t original_ssrc =
1477 rtx_to_media_ssrcs_.find(header.ssrc)->second;
1478 std::set<uint16_t>* seq_no_map = &dropped_seq_[original_ssrc];
1479 auto it = seq_no_map->find(original_sequence_number);
1480 if (it != seq_no_map->end()) {
1481 retransmit_observed_ = true;
1482 seq_no_map->erase(it);
1483 } else {
1484 rtx_padding_observed_ = true;
1485 }
1486 } else {
1487 streams_observed_.insert(header.ssrc);
1488 }
1489
1490 if (IsDone())
Peter Boström5811a392015-12-10 13:02:50 +01001491 done_.Set();
sprang861c55e2015-10-16 10:01:21 -07001492
1493 if (drop_packet)
1494 return true;
1495 }
sprang867fb522015-08-03 04:38:41 -07001496 }
sprang861c55e2015-10-16 10:01:21 -07001497
stefan1d8a5062015-10-02 03:39:33 -07001498 return test::DirectTransport::SendRtp(data, length, options);
sprang867fb522015-08-03 04:38:41 -07001499 }
1500
Erik Språng8d629712015-08-04 16:24:03 +02001501 bool IsDone() {
sprang861c55e2015-10-16 10:01:21 -07001502 bool observed_types_ok =
1503 streams_observed_.size() == MultiStreamTest::kNumStreams &&
1504 padding_observed_ && retransmit_observed_ && rtx_padding_observed_;
1505 if (!observed_types_ok)
1506 return false;
1507 // We should not have any gaps in the sequence number range.
1508 size_t seqno_range =
1509 *received_packed_ids_.rbegin() - *received_packed_ids_.begin() + 1;
1510 return seqno_range == received_packed_ids_.size();
Erik Språng8d629712015-08-04 16:24:03 +02001511 }
1512
Peter Boström5811a392015-12-10 13:02:50 +01001513 bool Wait() {
sprang861c55e2015-10-16 10:01:21 -07001514 {
1515 // Can't be sure until this point that rtx_to_media_ssrcs_ etc have
1516 // been initialized and are OK to read.
1517 rtc::CritScope cs(&lock_);
1518 started_ = true;
1519 }
Peter Boström5811a392015-12-10 13:02:50 +01001520 return done_.Wait(kDefaultTimeoutMs);
sprang861c55e2015-10-16 10:01:21 -07001521 }
sprang867fb522015-08-03 04:38:41 -07001522
sprang861c55e2015-10-16 10:01:21 -07001523 rtc::CriticalSection lock_;
Peter Boström5811a392015-12-10 13:02:50 +01001524 rtc::Event done_;
kwiberg27f982b2016-03-01 11:52:33 -08001525 std::unique_ptr<RtpHeaderParser> parser_;
sprang861c55e2015-10-16 10:01:21 -07001526 SequenceNumberUnwrapper unwrapper_;
1527 std::set<int64_t> received_packed_ids_;
sprang867fb522015-08-03 04:38:41 -07001528 std::set<uint32_t> streams_observed_;
sprang861c55e2015-10-16 10:01:21 -07001529 std::map<uint32_t, std::set<uint16_t>> dropped_seq_;
1530 const uint32_t& first_media_ssrc_;
1531 const std::map<uint32_t, uint32_t>& rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001532 bool padding_observed_;
1533 bool rtx_padding_observed_;
sprang861c55e2015-10-16 10:01:21 -07001534 bool retransmit_observed_;
1535 bool started_;
sprang867fb522015-08-03 04:38:41 -07001536 };
1537
1538 class TransportSequenceNumberTester : public MultiStreamTest {
1539 public:
sprang861c55e2015-10-16 10:01:21 -07001540 TransportSequenceNumberTester()
1541 : first_media_ssrc_(0), observer_(nullptr) {}
sprang867fb522015-08-03 04:38:41 -07001542 virtual ~TransportSequenceNumberTester() {}
1543
1544 protected:
1545 void Wait() override {
Peter Boström74f6e9e2016-04-04 17:56:10 +02001546 RTC_DCHECK(observer_);
Peter Boström5811a392015-12-10 13:02:50 +01001547 EXPECT_TRUE(observer_->Wait());
sprang867fb522015-08-03 04:38:41 -07001548 }
1549
1550 void UpdateSendConfig(
1551 size_t stream_index,
1552 VideoSendStream::Config* send_config,
1553 VideoEncoderConfig* encoder_config,
1554 test::FrameGeneratorCapturer** frame_generator) override {
1555 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07001556 send_config->rtp.extensions.push_back(RtpExtension(
1557 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
sprang867fb522015-08-03 04:38:41 -07001558
1559 // Force some padding to be sent.
1560 const int kPaddingBitrateBps = 50000;
1561 int total_target_bitrate = 0;
1562 for (const VideoStream& stream : encoder_config->streams)
1563 total_target_bitrate += stream.target_bitrate_bps;
1564 encoder_config->min_transmit_bitrate_bps =
1565 total_target_bitrate + kPaddingBitrateBps;
1566
1567 // Configure RTX for redundant payload padding.
1568 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang861c55e2015-10-16 10:01:21 -07001569 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[stream_index]);
sprang867fb522015-08-03 04:38:41 -07001570 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
sprang861c55e2015-10-16 10:01:21 -07001571 rtx_to_media_ssrcs_[kSendRtxSsrcs[stream_index]] =
1572 send_config->rtp.ssrcs[0];
1573
1574 if (stream_index == 0)
1575 first_media_ssrc_ = send_config->rtp.ssrcs[0];
sprang867fb522015-08-03 04:38:41 -07001576 }
1577
1578 void UpdateReceiveConfig(
1579 size_t stream_index,
1580 VideoReceiveStream::Config* receive_config) override {
sprang861c55e2015-10-16 10:01:21 -07001581 receive_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang867fb522015-08-03 04:38:41 -07001582 receive_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07001583 receive_config->rtp.extensions.push_back(RtpExtension(
1584 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
sprang867fb522015-08-03 04:38:41 -07001585 }
1586
stefanf116bd02015-10-27 08:29:42 -07001587 test::DirectTransport* CreateSendTransport(Call* sender_call) override {
1588 observer_ = new RtpExtensionHeaderObserver(sender_call, first_media_ssrc_,
sprang861c55e2015-10-16 10:01:21 -07001589 rtx_to_media_ssrcs_);
sprang867fb522015-08-03 04:38:41 -07001590 return observer_;
1591 }
1592
1593 private:
sprang861c55e2015-10-16 10:01:21 -07001594 uint32_t first_media_ssrc_;
1595 std::map<uint32_t, uint32_t> rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001596 RtpExtensionHeaderObserver* observer_;
1597 } tester;
1598
1599 tester.RunTest();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001600}
1601
Stefan Holmer04cb7632016-01-14 20:34:30 +01001602class TransportFeedbackTester : public test::EndToEndTest {
1603 public:
1604 explicit TransportFeedbackTester(bool feedback_enabled,
1605 size_t num_video_streams,
1606 size_t num_audio_streams)
1607 : EndToEndTest(::webrtc::EndToEndTest::kDefaultTimeoutMs),
1608 feedback_enabled_(feedback_enabled),
1609 num_video_streams_(num_video_streams),
sprangcd349d92016-07-13 09:11:28 -07001610 num_audio_streams_(num_audio_streams),
1611 receiver_call_(nullptr) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001612 // Only one stream of each supported for now.
1613 EXPECT_LE(num_video_streams, 1u);
1614 EXPECT_LE(num_audio_streams, 1u);
1615 }
1616
1617 protected:
1618 Action OnSendRtcp(const uint8_t* data, size_t length) override {
1619 EXPECT_FALSE(HasTransportFeedback(data, length));
1620 return SEND_PACKET;
1621 }
1622
1623 Action OnReceiveRtcp(const uint8_t* data, size_t length) override {
1624 if (HasTransportFeedback(data, length))
1625 observation_complete_.Set();
1626 return SEND_PACKET;
1627 }
1628
1629 bool HasTransportFeedback(const uint8_t* data, size_t length) const {
1630 RTCPUtility::RTCPParserV2 parser(data, length, true);
1631 EXPECT_TRUE(parser.IsValid());
1632
1633 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
1634 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
1635 if (packet_type == RTCPUtility::RTCPPacketTypes::kTransportFeedback)
1636 return true;
1637 packet_type = parser.Iterate();
1638 }
1639
1640 return false;
1641 }
1642
1643 void PerformTest() override {
1644 const int64_t kDisabledFeedbackTimeoutMs = 5000;
1645 EXPECT_EQ(feedback_enabled_,
1646 observation_complete_.Wait(feedback_enabled_
1647 ? test::CallTest::kDefaultTimeoutMs
1648 : kDisabledFeedbackTimeoutMs));
1649 }
1650
1651 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
1652 receiver_call_ = receiver_call;
1653 }
1654
1655 size_t GetNumVideoStreams() const override { return num_video_streams_; }
1656 size_t GetNumAudioStreams() const override { return num_audio_streams_; }
1657
1658 void ModifyVideoConfigs(
1659 VideoSendStream::Config* send_config,
1660 std::vector<VideoReceiveStream::Config>* receive_configs,
1661 VideoEncoderConfig* encoder_config) override {
1662 send_config->rtp.extensions.clear();
1663 send_config->rtp.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001664 RtpExtension(RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer04cb7632016-01-14 20:34:30 +01001665 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1666 (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
1667 }
1668
1669 void ModifyAudioConfigs(
1670 AudioSendStream::Config* send_config,
1671 std::vector<AudioReceiveStream::Config>* receive_configs) override {
1672 send_config->rtp.extensions.clear();
1673 send_config->rtp.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001674 RtpExtension(RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer04cb7632016-01-14 20:34:30 +01001675 (*receive_configs)[0].rtp.extensions.clear();
1676 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1677 (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001678 }
1679
1680 private:
Erik Språng6b8d3552015-09-24 15:06:57 +02001681 static const int kExtensionId = 5;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001682 const bool feedback_enabled_;
1683 const size_t num_video_streams_;
1684 const size_t num_audio_streams_;
1685 Call* receiver_call_;
1686};
Erik Språng6b8d3552015-09-24 15:06:57 +02001687
Stefan Holmer04cb7632016-01-14 20:34:30 +01001688TEST_F(EndToEndTest, VideoReceivesTransportFeedback) {
1689 TransportFeedbackTester test(true, 1, 0);
1690 RunBaseTest(&test);
Erik Språng6b8d3552015-09-24 15:06:57 +02001691}
stefan43edf0f2015-11-20 18:05:48 -08001692
Stefan Holmer04cb7632016-01-14 20:34:30 +01001693TEST_F(EndToEndTest, VideoTransportFeedbackNotConfigured) {
1694 TransportFeedbackTester test(false, 1, 0);
1695 RunBaseTest(&test);
stefan43edf0f2015-11-20 18:05:48 -08001696}
1697
Stefan Holmer04cb7632016-01-14 20:34:30 +01001698TEST_F(EndToEndTest, AudioReceivesTransportFeedback) {
1699 TransportFeedbackTester test(true, 0, 1);
1700 RunBaseTest(&test);
1701}
1702
1703TEST_F(EndToEndTest, AudioTransportFeedbackNotConfigured) {
1704 TransportFeedbackTester test(false, 0, 1);
1705 RunBaseTest(&test);
1706}
1707
1708TEST_F(EndToEndTest, AudioVideoReceivesTransportFeedback) {
1709 TransportFeedbackTester test(true, 1, 1);
1710 RunBaseTest(&test);
stefan43edf0f2015-11-20 18:05:48 -08001711}
1712
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001713TEST_F(EndToEndTest, ObserversEncodedFrames) {
1714 class EncodedFrameTestObserver : public EncodedFrameObserver {
1715 public:
1716 EncodedFrameTestObserver()
Peter Boström5811a392015-12-10 13:02:50 +01001717 : length_(0), frame_type_(kEmptyFrame), called_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001718 virtual ~EncodedFrameTestObserver() {}
1719
1720 virtual void EncodedFrameCallback(const EncodedFrame& encoded_frame) {
1721 frame_type_ = encoded_frame.frame_type_;
1722 length_ = encoded_frame.length_;
1723 buffer_.reset(new uint8_t[length_]);
1724 memcpy(buffer_.get(), encoded_frame.data_, length_);
Peter Boström5811a392015-12-10 13:02:50 +01001725 called_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001726 }
1727
Peter Boström5811a392015-12-10 13:02:50 +01001728 bool Wait() { return called_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001729
1730 void ExpectEqualFrames(const EncodedFrameTestObserver& observer) {
1731 ASSERT_EQ(length_, observer.length_)
1732 << "Observed frames are of different lengths.";
1733 EXPECT_EQ(frame_type_, observer.frame_type_)
1734 << "Observed frames have different frame types.";
1735 EXPECT_EQ(0, memcmp(buffer_.get(), observer.buffer_.get(), length_))
1736 << "Observed encoded frames have different content.";
1737 }
1738
1739 private:
kwiberg27f982b2016-03-01 11:52:33 -08001740 std::unique_ptr<uint8_t[]> buffer_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001741 size_t length_;
1742 FrameType frame_type_;
Peter Boström5811a392015-12-10 13:02:50 +01001743 rtc::Event called_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001744 };
1745
1746 EncodedFrameTestObserver post_encode_observer;
1747 EncodedFrameTestObserver pre_decode_observer;
1748
solenberg4fbae2b2015-08-28 04:07:10 -07001749 CreateCalls(Call::Config(), Call::Config());
1750
stefanf116bd02015-10-27 08:29:42 -07001751 test::DirectTransport sender_transport(sender_call_.get());
1752 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001753 sender_transport.SetReceiver(receiver_call_->Receiver());
1754 receiver_transport.SetReceiver(sender_call_->Receiver());
1755
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001756 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07001757 CreateMatchingReceiveConfigs(&receiver_transport);
stefanff483612015-12-21 03:14:00 -08001758 video_send_config_.post_encode_callback = &post_encode_observer;
1759 video_receive_configs_[0].pre_decode_callback = &pre_decode_observer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001760
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001761 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001762 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001763
kwiberg27f982b2016-03-01 11:52:33 -08001764 std::unique_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +00001765 test::FrameGenerator::CreateChromaGenerator(
stefanff483612015-12-21 03:14:00 -08001766 video_encoder_config_.streams[0].width,
1767 video_encoder_config_.streams[0].height));
1768 video_send_stream_->Input()->IncomingCapturedFrame(
1769 *frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001770
Peter Boström5811a392015-12-10 13:02:50 +01001771 EXPECT_TRUE(post_encode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001772 << "Timed out while waiting for send-side encoded-frame callback.";
1773
Peter Boström5811a392015-12-10 13:02:50 +01001774 EXPECT_TRUE(pre_decode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001775 << "Timed out while waiting for pre-decode encoded-frame callback.";
1776
1777 post_encode_observer.ExpectEqualFrames(pre_decode_observer);
1778
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001779 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001780
1781 sender_transport.StopSending();
1782 receiver_transport.StopSending();
1783
1784 DestroyStreams();
1785}
1786
1787TEST_F(EndToEndTest, ReceiveStreamSendsRemb) {
1788 class RembObserver : public test::EndToEndTest {
1789 public:
1790 RembObserver() : EndToEndTest(kDefaultTimeoutMs) {}
1791
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001792 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001793 RTCPUtility::RTCPParserV2 parser(packet, length, true);
1794 EXPECT_TRUE(parser.IsValid());
1795
1796 bool received_psfb = false;
1797 bool received_remb = false;
1798 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02001799 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
1800 if (packet_type == RTCPUtility::RTCPPacketTypes::kPsfbRemb) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001801 const RTCPUtility::RTCPPacket& packet = parser.Packet();
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001802 EXPECT_EQ(packet.PSFBAPP.SenderSSRC, kReceiverLocalVideoSsrc);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001803 received_psfb = true;
Erik Språng242e22b2015-05-11 10:17:43 +02001804 } else if (packet_type == RTCPUtility::RTCPPacketTypes::kPsfbRembItem) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001805 const RTCPUtility::RTCPPacket& packet = parser.Packet();
1806 EXPECT_GT(packet.REMBItem.BitRate, 0u);
1807 EXPECT_EQ(packet.REMBItem.NumberOfSSRCs, 1u);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001808 EXPECT_EQ(packet.REMBItem.SSRCs[0], kVideoSendSsrcs[0]);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001809 received_remb = true;
1810 }
1811 packet_type = parser.Iterate();
1812 }
1813 if (received_psfb && received_remb)
Peter Boström5811a392015-12-10 13:02:50 +01001814 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001815 return SEND_PACKET;
1816 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001817 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001818 EXPECT_TRUE(Wait()) << "Timed out while waiting for a "
1819 "receiver RTCP REMB packet to be "
1820 "sent.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001821 }
1822 } test;
1823
stefane74eef12016-01-08 06:47:13 -08001824 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001825}
1826
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001827TEST_F(EndToEndTest, VerifyBandwidthStats) {
stefanf116bd02015-10-27 08:29:42 -07001828 class RtcpObserver : public test::EndToEndTest {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001829 public:
1830 RtcpObserver()
1831 : EndToEndTest(kDefaultTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00001832 sender_call_(nullptr),
1833 receiver_call_(nullptr),
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001834 has_seen_pacer_delay_(false) {}
1835
stefanf116bd02015-10-27 08:29:42 -07001836 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001837 Call::Stats sender_stats = sender_call_->GetStats();
1838 Call::Stats receiver_stats = receiver_call_->GetStats();
1839 if (!has_seen_pacer_delay_)
1840 has_seen_pacer_delay_ = sender_stats.pacer_delay_ms > 0;
1841 if (sender_stats.send_bandwidth_bps > 0 &&
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00001842 receiver_stats.recv_bandwidth_bps > 0 && has_seen_pacer_delay_) {
Peter Boström5811a392015-12-10 13:02:50 +01001843 observation_complete_.Set();
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00001844 }
stefanf116bd02015-10-27 08:29:42 -07001845 return SEND_PACKET;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001846 }
1847
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001848 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001849 sender_call_ = sender_call;
1850 receiver_call_ = receiver_call;
1851 }
1852
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001853 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001854 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
1855 "non-zero bandwidth stats.";
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001856 }
1857
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001858 private:
1859 Call* sender_call_;
1860 Call* receiver_call_;
1861 bool has_seen_pacer_delay_;
1862 } test;
1863
stefane74eef12016-01-08 06:47:13 -08001864 RunBaseTest(&test);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001865}
1866
stefan32f81542016-01-20 07:13:58 -08001867
1868// Verifies that it's possible to limit the send BWE by sending a REMB.
1869// This is verified by allowing the send BWE to ramp-up to >1000 kbps,
1870// then have the test generate a REMB of 500 kbps and verify that the send BWE
1871// is reduced to exactly 500 kbps. Then a REMB of 1000 kbps is generated and the
1872// test verifies that the send BWE ramps back up to exactly 1000 kbps.
1873TEST_F(EndToEndTest, RembWithSendSideBwe) {
1874 class BweObserver : public test::EndToEndTest {
1875 public:
1876 BweObserver()
1877 : EndToEndTest(kDefaultTimeoutMs),
1878 sender_call_(nullptr),
1879 clock_(Clock::GetRealTimeClock()),
1880 sender_ssrc_(0),
1881 remb_bitrate_bps_(1000000),
1882 receive_transport_(nullptr),
1883 event_(false, false),
1884 poller_thread_(&BitrateStatsPollingThread,
1885 this,
1886 "BitrateStatsPollingThread"),
Erik Språng737336d2016-07-29 12:59:36 +02001887 state_(kWaitForFirstRampUp),
1888 retransmission_rate_limiter_(clock_, 1000) {}
stefan32f81542016-01-20 07:13:58 -08001889
1890 ~BweObserver() {}
1891
nisseef8b61e2016-04-29 06:09:15 -07001892 test::PacketTransport* CreateReceiveTransport() override {
stefan32f81542016-01-20 07:13:58 -08001893 receive_transport_ = new test::PacketTransport(
1894 nullptr, this, test::PacketTransport::kReceiver,
1895 FakeNetworkPipe::Config());
1896 return receive_transport_;
1897 }
1898
1899 Call::Config GetSenderCallConfig() override {
1900 Call::Config config;
1901 // Set a high start bitrate to reduce the test completion time.
1902 config.bitrate_config.start_bitrate_bps = remb_bitrate_bps_;
1903 return config;
1904 }
1905
1906 void ModifyVideoConfigs(
1907 VideoSendStream::Config* send_config,
1908 std::vector<VideoReceiveStream::Config>* receive_configs,
1909 VideoEncoderConfig* encoder_config) override {
1910 ASSERT_EQ(1u, send_config->rtp.ssrcs.size());
1911 send_config->rtp.extensions.clear();
1912 send_config->rtp.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001913 RtpExtension(RtpExtension::kTransportSequenceNumberUri,
stefan32f81542016-01-20 07:13:58 -08001914 test::kTransportSequenceNumberExtensionId));
1915 sender_ssrc_ = send_config->rtp.ssrcs[0];
1916
1917 encoder_config->streams[0].max_bitrate_bps =
1918 encoder_config->streams[0].target_bitrate_bps = 2000000;
1919
1920 ASSERT_EQ(1u, receive_configs->size());
1921 (*receive_configs)[0].rtp.remb = false;
1922 (*receive_configs)[0].rtp.transport_cc = true;
1923 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1924 RtpRtcp::Configuration config;
1925 config.receiver_only = true;
1926 config.clock = clock_;
1927 config.outgoing_transport = receive_transport_;
Erik Språng737336d2016-07-29 12:59:36 +02001928 config.retransmission_rate_limiter = &retransmission_rate_limiter_;
stefan32f81542016-01-20 07:13:58 -08001929 rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(config));
1930 rtp_rtcp_->SetRemoteSSRC((*receive_configs)[0].rtp.remote_ssrc);
1931 rtp_rtcp_->SetSSRC((*receive_configs)[0].rtp.local_ssrc);
1932 rtp_rtcp_->SetREMBStatus(true);
1933 rtp_rtcp_->SetSendingStatus(true);
1934 rtp_rtcp_->SetRTCPStatus(RtcpMode::kReducedSize);
1935 }
1936
1937 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
1938 sender_call_ = sender_call;
1939 }
1940
1941 static bool BitrateStatsPollingThread(void* obj) {
1942 return static_cast<BweObserver*>(obj)->PollStats();
1943 }
1944
1945 bool PollStats() {
1946 if (sender_call_) {
1947 Call::Stats stats = sender_call_->GetStats();
1948 switch (state_) {
1949 case kWaitForFirstRampUp:
1950 if (stats.send_bandwidth_bps >= remb_bitrate_bps_) {
1951 state_ = kWaitForRemb;
1952 remb_bitrate_bps_ /= 2;
1953 rtp_rtcp_->SetREMBData(
1954 remb_bitrate_bps_,
1955 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
1956 rtp_rtcp_->SendRTCP(kRtcpRr);
1957 }
1958 break;
1959
1960 case kWaitForRemb:
1961 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
1962 state_ = kWaitForSecondRampUp;
1963 remb_bitrate_bps_ *= 2;
1964 rtp_rtcp_->SetREMBData(
1965 remb_bitrate_bps_,
1966 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
1967 rtp_rtcp_->SendRTCP(kRtcpRr);
1968 }
1969 break;
1970
1971 case kWaitForSecondRampUp:
1972 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
1973 observation_complete_.Set();
1974 }
1975 break;
1976 }
1977 }
1978
1979 return !event_.Wait(1000);
1980 }
1981
1982 void PerformTest() override {
1983 poller_thread_.Start();
1984 EXPECT_TRUE(Wait())
1985 << "Timed out while waiting for bitrate to change according to REMB.";
1986 poller_thread_.Stop();
1987 }
1988
1989 private:
1990 enum TestState { kWaitForFirstRampUp, kWaitForRemb, kWaitForSecondRampUp };
1991
1992 Call* sender_call_;
1993 Clock* const clock_;
1994 uint32_t sender_ssrc_;
1995 int remb_bitrate_bps_;
kwiberg27f982b2016-03-01 11:52:33 -08001996 std::unique_ptr<RtpRtcp> rtp_rtcp_;
stefan32f81542016-01-20 07:13:58 -08001997 test::PacketTransport* receive_transport_;
1998 rtc::Event event_;
1999 rtc::PlatformThread poller_thread_;
2000 TestState state_;
Erik Språng737336d2016-07-29 12:59:36 +02002001 RateLimiter retransmission_rate_limiter_;
stefan32f81542016-01-20 07:13:58 -08002002 } test;
2003
2004 RunBaseTest(&test);
2005}
2006
Åsa Persson352b2d72015-04-15 18:00:40 +02002007TEST_F(EndToEndTest, VerifyNackStats) {
2008 static const int kPacketNumberToDrop = 200;
2009 class NackObserver : public test::EndToEndTest {
2010 public:
2011 NackObserver()
2012 : EndToEndTest(kLongTimeoutMs),
2013 sent_rtp_packets_(0),
2014 dropped_rtp_packet_(0),
2015 dropped_rtp_packet_requested_(false),
2016 send_stream_(nullptr),
2017 start_runtime_ms_(-1) {}
2018
2019 private:
2020 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002021 rtc::CritScope lock(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02002022 if (++sent_rtp_packets_ == kPacketNumberToDrop) {
kwiberg27f982b2016-03-01 11:52:33 -08002023 std::unique_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
Åsa Persson352b2d72015-04-15 18:00:40 +02002024 RTPHeader header;
2025 EXPECT_TRUE(parser->Parse(packet, length, &header));
2026 dropped_rtp_packet_ = header.sequenceNumber;
2027 return DROP_PACKET;
2028 }
2029 VerifyStats();
2030 return SEND_PACKET;
2031 }
2032
2033 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002034 rtc::CritScope lock(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02002035 test::RtcpPacketParser rtcp_parser;
2036 rtcp_parser.Parse(packet, length);
2037 std::vector<uint16_t> nacks = rtcp_parser.nack_item()->last_nack_list();
2038 if (!nacks.empty() && std::find(
2039 nacks.begin(), nacks.end(), dropped_rtp_packet_) != nacks.end()) {
2040 dropped_rtp_packet_requested_ = true;
2041 }
2042 return SEND_PACKET;
2043 }
2044
stefan608213e2015-11-01 14:56:10 -08002045 void VerifyStats() EXCLUSIVE_LOCKS_REQUIRED(&crit_) {
Åsa Persson352b2d72015-04-15 18:00:40 +02002046 if (!dropped_rtp_packet_requested_)
2047 return;
2048 int send_stream_nack_packets = 0;
2049 int receive_stream_nack_packets = 0;
2050 VideoSendStream::Stats stats = send_stream_->GetStats();
2051 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
2052 stats.substreams.begin(); it != stats.substreams.end(); ++it) {
2053 const VideoSendStream::StreamStats& stream_stats = it->second;
2054 send_stream_nack_packets +=
2055 stream_stats.rtcp_packet_type_counts.nack_packets;
2056 }
2057 for (size_t i = 0; i < receive_streams_.size(); ++i) {
2058 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
2059 receive_stream_nack_packets +=
2060 stats.rtcp_packet_type_counts.nack_packets;
2061 }
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002062 if (send_stream_nack_packets >= 1 && receive_stream_nack_packets >= 1) {
Åsa Persson352b2d72015-04-15 18:00:40 +02002063 // NACK packet sent on receive stream and received on sent stream.
2064 if (MinMetricRunTimePassed())
Peter Boström5811a392015-12-10 13:02:50 +01002065 observation_complete_.Set();
Åsa Persson352b2d72015-04-15 18:00:40 +02002066 }
2067 }
2068
2069 bool MinMetricRunTimePassed() {
2070 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
2071 if (start_runtime_ms_ == -1) {
2072 start_runtime_ms_ = now;
2073 return false;
2074 }
2075 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
2076 return elapsed_sec > metrics::kMinRunTimeInSeconds;
2077 }
2078
stefanff483612015-12-21 03:14:00 -08002079 void ModifyVideoConfigs(
2080 VideoSendStream::Config* send_config,
2081 std::vector<VideoReceiveStream::Config>* receive_configs,
2082 VideoEncoderConfig* encoder_config) override {
Åsa Persson352b2d72015-04-15 18:00:40 +02002083 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2084 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2085 }
2086
stefanff483612015-12-21 03:14:00 -08002087 void OnVideoStreamsCreated(
Åsa Persson352b2d72015-04-15 18:00:40 +02002088 VideoSendStream* send_stream,
2089 const std::vector<VideoReceiveStream*>& receive_streams) override {
2090 send_stream_ = send_stream;
2091 receive_streams_ = receive_streams;
2092 }
2093
2094 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002095 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Åsa Persson352b2d72015-04-15 18:00:40 +02002096 }
2097
stefan608213e2015-11-01 14:56:10 -08002098 rtc::CriticalSection crit_;
Åsa Persson352b2d72015-04-15 18:00:40 +02002099 uint64_t sent_rtp_packets_;
stefan608213e2015-11-01 14:56:10 -08002100 uint16_t dropped_rtp_packet_ GUARDED_BY(&crit_);
2101 bool dropped_rtp_packet_requested_ GUARDED_BY(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02002102 std::vector<VideoReceiveStream*> receive_streams_;
2103 VideoSendStream* send_stream_;
2104 int64_t start_runtime_ms_;
2105 } test;
2106
asapersson01d70a32016-05-20 06:29:46 -07002107 metrics::Reset();
stefane74eef12016-01-08 06:47:13 -08002108 RunBaseTest(&test);
Åsa Persson352b2d72015-04-15 18:00:40 +02002109
asapersson01d70a32016-05-20 06:29:46 -07002110 EXPECT_EQ(
2111 1, metrics::NumSamples("WebRTC.Video.UniqueNackRequestsSentInPercent"));
2112 EXPECT_EQ(1, metrics::NumSamples(
2113 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
2114 EXPECT_GT(metrics::MinSample("WebRTC.Video.NackPacketsSentPerMinute"), 0);
Åsa Persson352b2d72015-04-15 18:00:40 +02002115}
2116
sprangb4a1ae52015-12-03 08:10:08 -08002117void EndToEndTest::VerifyHistogramStats(bool use_rtx,
2118 bool use_red,
2119 bool screenshare) {
tommi2e82f382016-06-21 00:26:43 -07002120 class StatsObserver : public test::EndToEndTest,
2121 public rtc::VideoSinkInterface<VideoFrame> {
Åsa Persson3c391cb2015-04-27 10:09:49 +02002122 public:
sprangb4a1ae52015-12-03 08:10:08 -08002123 StatsObserver(bool use_rtx, bool use_red, bool screenshare)
Åsa Persson3c391cb2015-04-27 10:09:49 +02002124 : EndToEndTest(kLongTimeoutMs),
2125 use_rtx_(use_rtx),
2126 use_red_(use_red),
sprangb4a1ae52015-12-03 08:10:08 -08002127 screenshare_(screenshare),
Peter Boström39593972016-02-15 11:27:15 +01002128 // This test uses NACK, so to send FEC we can't use a fake encoder.
2129 vp8_encoder_(
2130 use_red ? VideoEncoder::Create(VideoEncoder::EncoderType::kVp8)
2131 : nullptr),
Åsa Persson3c391cb2015-04-27 10:09:49 +02002132 sender_call_(nullptr),
2133 receiver_call_(nullptr),
2134 start_runtime_ms_(-1) {}
2135
2136 private:
tommi2e82f382016-06-21 00:26:43 -07002137 void OnFrame(const VideoFrame& video_frame) override {}
2138
Åsa Persson3c391cb2015-04-27 10:09:49 +02002139 Action OnSendRtp(const uint8_t* packet, size_t length) override {
2140 if (MinMetricRunTimePassed())
Peter Boström5811a392015-12-10 13:02:50 +01002141 observation_complete_.Set();
Åsa Persson3c391cb2015-04-27 10:09:49 +02002142
stefanf116bd02015-10-27 08:29:42 -07002143 return SEND_PACKET;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002144 }
2145
2146 bool MinMetricRunTimePassed() {
2147 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
2148 if (start_runtime_ms_ == -1) {
2149 start_runtime_ms_ = now;
2150 return false;
2151 }
2152 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
2153 return elapsed_sec > metrics::kMinRunTimeInSeconds * 2;
2154 }
2155
stefanff483612015-12-21 03:14:00 -08002156 void ModifyVideoConfigs(
2157 VideoSendStream::Config* send_config,
2158 std::vector<VideoReceiveStream::Config>* receive_configs,
2159 VideoEncoderConfig* encoder_config) override {
stefana23fc622016-07-28 07:56:38 -07002160 static const int kExtensionId = 8;
2161 send_config->rtp.extensions.push_back(RtpExtension(
2162 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
2163 (*receive_configs)[0].rtp.extensions.push_back(RtpExtension(
2164 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002165 // NACK
2166 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2167 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
tommi2e82f382016-06-21 00:26:43 -07002168 (*receive_configs)[0].renderer = this;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002169 // FEC
2170 if (use_red_) {
2171 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
2172 send_config->rtp.fec.red_payload_type = kRedPayloadType;
Peter Boström39593972016-02-15 11:27:15 +01002173 send_config->encoder_settings.encoder = vp8_encoder_.get();
2174 send_config->encoder_settings.payload_name = "VP8";
2175 (*receive_configs)[0].decoders[0].payload_name = "VP8";
Åsa Persson3c391cb2015-04-27 10:09:49 +02002176 (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
2177 (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
2178 }
2179 // RTX
2180 if (use_rtx_) {
2181 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
2182 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002183 (*receive_configs)[0].rtp.rtx[kFakeVideoSendPayloadType].ssrc =
Åsa Persson3c391cb2015-04-27 10:09:49 +02002184 kSendRtxSsrcs[0];
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002185 (*receive_configs)[0].rtp.rtx[kFakeVideoSendPayloadType].payload_type =
Åsa Persson3c391cb2015-04-27 10:09:49 +02002186 kSendRtxPayloadType;
2187 }
sprangb4a1ae52015-12-03 08:10:08 -08002188 encoder_config->content_type =
2189 screenshare_ ? VideoEncoderConfig::ContentType::kScreen
2190 : VideoEncoderConfig::ContentType::kRealtimeVideo;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002191 }
2192
2193 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2194 sender_call_ = sender_call;
2195 receiver_call_ = receiver_call;
2196 }
2197
Åsa Persson3c391cb2015-04-27 10:09:49 +02002198 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002199 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Åsa Persson3c391cb2015-04-27 10:09:49 +02002200 }
2201
sprangb4a1ae52015-12-03 08:10:08 -08002202 const bool use_rtx_;
2203 const bool use_red_;
2204 const bool screenshare_;
kwiberg27f982b2016-03-01 11:52:33 -08002205 const std::unique_ptr<VideoEncoder> vp8_encoder_;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002206 Call* sender_call_;
2207 Call* receiver_call_;
2208 int64_t start_runtime_ms_;
sprangb4a1ae52015-12-03 08:10:08 -08002209 } test(use_rtx, use_red, screenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002210
asapersson01d70a32016-05-20 06:29:46 -07002211 metrics::Reset();
stefane74eef12016-01-08 06:47:13 -08002212 RunBaseTest(&test);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002213
stefan91d92602015-11-11 10:13:02 -08002214 // Delete the call for Call stats to be reported.
stefan18adf0a2015-11-17 06:24:56 -08002215 sender_call_.reset();
stefan91d92602015-11-11 10:13:02 -08002216 receiver_call_.reset();
2217
sprangb4a1ae52015-12-03 08:10:08 -08002218 std::string video_prefix =
2219 screenshare ? "WebRTC.Video.Screenshare." : "WebRTC.Video.";
2220
Åsa Persson3c391cb2015-04-27 10:09:49 +02002221 // Verify that stats have been updated once.
asapersson4374a092016-07-27 00:39:09 -07002222 EXPECT_EQ(2, metrics::NumSamples("WebRTC.Call.LifetimeInSeconds"));
asapersson01d70a32016-05-20 06:29:46 -07002223 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.VideoBitrateReceivedInKbps"));
2224 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.RtcpBitrateReceivedInBps"));
2225 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.BitrateReceivedInKbps"));
2226 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.EstimatedSendBitrateInKbps"));
2227 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.PacerBitrateInKbps"));
2228
asapersson4374a092016-07-27 00:39:09 -07002229 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SendStreamLifetimeInSeconds"));
2230 EXPECT_EQ(1,
2231 metrics::NumSamples("WebRTC.Video.ReceiveStreamLifetimeInSeconds"));
2232
asapersson01d70a32016-05-20 06:29:46 -07002233 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
stefan91d92602015-11-11 10:13:02 -08002234 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002235 metrics::NumSamples(video_prefix + "NackPacketsReceivedPerMinute"));
2236 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
asaperssond89920b2015-07-22 06:52:00 -07002237 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002238 metrics::NumSamples(video_prefix + "FirPacketsReceivedPerMinute"));
2239 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
sprangb4a1ae52015-12-03 08:10:08 -08002240 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002241 metrics::NumSamples(video_prefix + "PliPacketsReceivedPerMinute"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002242
asapersson01d70a32016-05-20 06:29:46 -07002243 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "KeyFramesSentInPermille"));
2244 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
2245
2246 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentPacketsLostInPercent"));
2247 EXPECT_EQ(1,
2248 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
2249
2250 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputWidthInPixels"));
2251 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputHeightInPixels"));
2252 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentWidthInPixels"));
2253 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentHeightInPixels"));
2254 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedWidthInPixels"));
2255 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedHeightInPixels"));
2256
2257 EXPECT_EQ(1, metrics::NumEvents(
2258 video_prefix + "InputWidthInPixels",
2259 static_cast<int>(video_encoder_config_.streams[0].width)));
2260 EXPECT_EQ(1, metrics::NumEvents(
2261 video_prefix + "InputHeightInPixels",
2262 static_cast<int>(video_encoder_config_.streams[0].height)));
2263 EXPECT_EQ(1, metrics::NumEvents(
2264 video_prefix + "SentWidthInPixels",
2265 static_cast<int>(video_encoder_config_.streams[0].width)));
2266 EXPECT_EQ(1, metrics::NumEvents(
2267 video_prefix + "SentHeightInPixels",
2268 static_cast<int>(video_encoder_config_.streams[0].height)));
2269 EXPECT_EQ(1, metrics::NumEvents(
2270 "WebRTC.Video.ReceivedWidthInPixels",
2271 static_cast<int>(video_encoder_config_.streams[0].width)));
2272 EXPECT_EQ(1, metrics::NumEvents(
2273 "WebRTC.Video.ReceivedHeightInPixels",
2274 static_cast<int>(video_encoder_config_.streams[0].height)));
2275
2276 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputFramesPerSecond"));
2277 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentFramesPerSecond"));
2278 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
2279 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
2280
2281 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
2282 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
2283 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
2284 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
2285
2286 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
2287
2288 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "EncodeTimeInMs"));
2289 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodeTimeInMs"));
2290
2291 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "BitrateSentInKbps"));
2292 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateReceivedInKbps"));
2293 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "MediaBitrateSentInKbps"));
2294 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.MediaBitrateReceivedInKbps"));
2295 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "PaddingBitrateSentInKbps"));
2296 EXPECT_EQ(1,
2297 metrics::NumSamples("WebRTC.Video.PaddingBitrateReceivedInKbps"));
asapersson6f14be82015-11-16 00:40:49 -08002298 EXPECT_EQ(
asapersson01d70a32016-05-20 06:29:46 -07002299 1, metrics::NumSamples(video_prefix + "RetransmittedBitrateSentInKbps"));
2300 EXPECT_EQ(1, metrics::NumSamples(
2301 "WebRTC.Video.RetransmittedBitrateReceivedInKbps"));
asapersson6f14be82015-11-16 00:40:49 -08002302
asapersson01d70a32016-05-20 06:29:46 -07002303 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SendDelayInMs"));
2304 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SendSideDelayInMs"));
2305 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SendSideDelayMaxInMs"));
asapersson6f14be82015-11-16 00:40:49 -08002306
Åsa Persson3c391cb2015-04-27 10:09:49 +02002307 int num_rtx_samples = use_rtx ? 1 : 0;
asapersson01d70a32016-05-20 06:29:46 -07002308 EXPECT_EQ(num_rtx_samples,
2309 metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2310 EXPECT_EQ(num_rtx_samples,
2311 metrics::NumSamples("WebRTC.Video.RtxBitrateReceivedInKbps"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002312
2313 int num_red_samples = use_red ? 1 : 0;
asapersson01d70a32016-05-20 06:29:46 -07002314 EXPECT_EQ(num_red_samples,
2315 metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2316 EXPECT_EQ(num_red_samples,
2317 metrics::NumSamples("WebRTC.Video.FecBitrateReceivedInKbps"));
2318 EXPECT_EQ(num_red_samples,
2319 metrics::NumSamples("WebRTC.Video.ReceivedFecPacketsInPercent"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002320}
2321
2322TEST_F(EndToEndTest, VerifyHistogramStatsWithRtx) {
2323 const bool kEnabledRtx = true;
2324 const bool kEnabledRed = false;
sprangb4a1ae52015-12-03 08:10:08 -08002325 const bool kScreenshare = false;
2326 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002327}
2328
2329TEST_F(EndToEndTest, VerifyHistogramStatsWithRed) {
2330 const bool kEnabledRtx = false;
2331 const bool kEnabledRed = true;
sprangb4a1ae52015-12-03 08:10:08 -08002332 const bool kScreenshare = false;
2333 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
2334}
2335
2336TEST_F(EndToEndTest, VerifyHistogramStatsWithScreenshare) {
2337 const bool kEnabledRtx = false;
2338 const bool kEnabledRed = false;
2339 const bool kScreenshare = true;
2340 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002341}
2342
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002343void EndToEndTest::TestXrReceiverReferenceTimeReport(bool enable_rrtr) {
2344 static const int kNumRtcpReportPacketsToObserve = 5;
2345 class RtcpXrObserver : public test::EndToEndTest {
2346 public:
2347 explicit RtcpXrObserver(bool enable_rrtr)
2348 : EndToEndTest(kDefaultTimeoutMs),
2349 enable_rrtr_(enable_rrtr),
2350 sent_rtcp_sr_(0),
2351 sent_rtcp_rr_(0),
2352 sent_rtcp_rrtr_(0),
2353 sent_rtcp_dlrr_(0) {}
2354
2355 private:
2356 // Receive stream should send RR packets (and RRTR packets if enabled).
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002357 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002358 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002359 RTCPUtility::RTCPParserV2 parser(packet, length, true);
2360 EXPECT_TRUE(parser.IsValid());
2361
2362 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02002363 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
2364 if (packet_type == RTCPUtility::RTCPPacketTypes::kRr) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002365 ++sent_rtcp_rr_;
2366 } else if (packet_type ==
Erik Språng242e22b2015-05-11 10:17:43 +02002367 RTCPUtility::RTCPPacketTypes::kXrReceiverReferenceTime) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002368 ++sent_rtcp_rrtr_;
2369 }
Erik Språng242e22b2015-05-11 10:17:43 +02002370 EXPECT_NE(packet_type, RTCPUtility::RTCPPacketTypes::kSr);
2371 EXPECT_NE(packet_type,
2372 RTCPUtility::RTCPPacketTypes::kXrDlrrReportBlockItem);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002373 packet_type = parser.Iterate();
2374 }
2375 return SEND_PACKET;
2376 }
2377 // Send stream should send SR packets (and DLRR packets if enabled).
nisseef8b61e2016-04-29 06:09:15 -07002378 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002379 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002380 RTCPUtility::RTCPParserV2 parser(packet, length, true);
2381 EXPECT_TRUE(parser.IsValid());
2382
2383 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02002384 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
2385 if (packet_type == RTCPUtility::RTCPPacketTypes::kSr) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002386 ++sent_rtcp_sr_;
Erik Språng242e22b2015-05-11 10:17:43 +02002387 } else if (packet_type ==
2388 RTCPUtility::RTCPPacketTypes::kXrDlrrReportBlockItem) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002389 ++sent_rtcp_dlrr_;
2390 }
Erik Språng242e22b2015-05-11 10:17:43 +02002391 EXPECT_NE(packet_type,
2392 RTCPUtility::RTCPPacketTypes::kXrReceiverReferenceTime);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002393 packet_type = parser.Iterate();
2394 }
2395 if (sent_rtcp_sr_ > kNumRtcpReportPacketsToObserve &&
2396 sent_rtcp_rr_ > kNumRtcpReportPacketsToObserve) {
2397 if (enable_rrtr_) {
2398 EXPECT_GT(sent_rtcp_rrtr_, 0);
2399 EXPECT_GT(sent_rtcp_dlrr_, 0);
2400 } else {
2401 EXPECT_EQ(0, sent_rtcp_rrtr_);
2402 EXPECT_EQ(0, sent_rtcp_dlrr_);
2403 }
Peter Boström5811a392015-12-10 13:02:50 +01002404 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002405 }
2406 return SEND_PACKET;
2407 }
2408
stefanff483612015-12-21 03:14:00 -08002409 void ModifyVideoConfigs(
2410 VideoSendStream::Config* send_config,
2411 std::vector<VideoReceiveStream::Config>* receive_configs,
2412 VideoEncoderConfig* encoder_config) override {
pbosda903ea2015-10-02 02:36:56 -07002413 (*receive_configs)[0].rtp.rtcp_mode = RtcpMode::kReducedSize;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002414 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report =
2415 enable_rrtr_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002416 }
2417
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002418 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002419 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002420 << "Timed out while waiting for RTCP SR/RR packets to be sent.";
2421 }
2422
stefan608213e2015-11-01 14:56:10 -08002423 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002424 bool enable_rrtr_;
2425 int sent_rtcp_sr_;
stefan608213e2015-11-01 14:56:10 -08002426 int sent_rtcp_rr_ GUARDED_BY(&crit_);
2427 int sent_rtcp_rrtr_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002428 int sent_rtcp_dlrr_;
2429 } test(enable_rrtr);
2430
stefane74eef12016-01-08 06:47:13 -08002431 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002432}
2433
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002434void EndToEndTest::TestSendsSetSsrcs(size_t num_ssrcs,
2435 bool send_single_ssrc_first) {
2436 class SendsSetSsrcs : public test::EndToEndTest {
2437 public:
2438 SendsSetSsrcs(const uint32_t* ssrcs,
2439 size_t num_ssrcs,
2440 bool send_single_ssrc_first)
2441 : EndToEndTest(kDefaultTimeoutMs),
2442 num_ssrcs_(num_ssrcs),
2443 send_single_ssrc_first_(send_single_ssrc_first),
2444 ssrcs_to_observe_(num_ssrcs),
sprang867fb522015-08-03 04:38:41 -07002445 expect_single_ssrc_(send_single_ssrc_first),
2446 send_stream_(nullptr) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002447 for (size_t i = 0; i < num_ssrcs; ++i)
2448 valid_ssrcs_[ssrcs[i]] = true;
2449 }
2450
2451 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002452 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002453 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002454 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002455
2456 EXPECT_TRUE(valid_ssrcs_[header.ssrc])
2457 << "Received unknown SSRC: " << header.ssrc;
2458
2459 if (!valid_ssrcs_[header.ssrc])
Peter Boström5811a392015-12-10 13:02:50 +01002460 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002461
2462 if (!is_observed_[header.ssrc]) {
2463 is_observed_[header.ssrc] = true;
2464 --ssrcs_to_observe_;
2465 if (expect_single_ssrc_) {
2466 expect_single_ssrc_ = false;
Peter Boström5811a392015-12-10 13:02:50 +01002467 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002468 }
2469 }
2470
2471 if (ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01002472 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002473
2474 return SEND_PACKET;
2475 }
2476
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002477 size_t GetNumVideoStreams() const override { return num_ssrcs_; }
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002478
stefanff483612015-12-21 03:14:00 -08002479 void ModifyVideoConfigs(
2480 VideoSendStream::Config* send_config,
2481 std::vector<VideoReceiveStream::Config>* receive_configs,
2482 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002483 if (num_ssrcs_ > 1) {
2484 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002485 for (size_t i = 0; i < encoder_config->streams.size(); ++i) {
2486 encoder_config->streams[i].min_bitrate_bps = 10000;
2487 encoder_config->streams[i].target_bitrate_bps = 15000;
2488 encoder_config->streams[i].max_bitrate_bps = 20000;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002489 }
2490 }
2491
perkj8eb37a32016-08-16 02:40:55 -07002492 video_encoder_config_all_streams_ = *encoder_config;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002493 if (send_single_ssrc_first_)
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002494 encoder_config->streams.resize(1);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002495 }
2496
stefanff483612015-12-21 03:14:00 -08002497 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002498 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002499 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002500 send_stream_ = send_stream;
2501 }
2502
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002503 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002504 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
2505 << (send_single_ssrc_first_ ? "first SSRC."
2506 : "SSRCs.");
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002507
2508 if (send_single_ssrc_first_) {
2509 // Set full simulcast and continue with the rest of the SSRCs.
stefanff483612015-12-21 03:14:00 -08002510 send_stream_->ReconfigureVideoEncoder(
perkj8eb37a32016-08-16 02:40:55 -07002511 video_encoder_config_all_streams_);
Peter Boström5811a392015-12-10 13:02:50 +01002512 EXPECT_TRUE(Wait()) << "Timed out while waiting on additional SSRCs.";
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002513 }
2514 }
2515
2516 private:
2517 std::map<uint32_t, bool> valid_ssrcs_;
2518 std::map<uint32_t, bool> is_observed_;
2519
2520 const size_t num_ssrcs_;
2521 const bool send_single_ssrc_first_;
2522
2523 size_t ssrcs_to_observe_;
2524 bool expect_single_ssrc_;
2525
2526 VideoSendStream* send_stream_;
stefanff483612015-12-21 03:14:00 -08002527 VideoEncoderConfig video_encoder_config_all_streams_;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002528 } test(kVideoSendSsrcs, num_ssrcs, send_single_ssrc_first);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002529
stefane74eef12016-01-08 06:47:13 -08002530 RunBaseTest(&test);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002531}
2532
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002533TEST_F(EndToEndTest, ReportsSetEncoderRates) {
2534 class EncoderRateStatsTest : public test::EndToEndTest,
2535 public test::FakeEncoder {
2536 public:
2537 EncoderRateStatsTest()
2538 : EndToEndTest(kDefaultTimeoutMs),
sprang867fb522015-08-03 04:38:41 -07002539 FakeEncoder(Clock::GetRealTimeClock()),
2540 send_stream_(nullptr),
2541 bitrate_kbps_(0) {}
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002542
stefanff483612015-12-21 03:14:00 -08002543 void OnVideoStreamsCreated(
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002544 VideoSendStream* send_stream,
2545 const std::vector<VideoReceiveStream*>& receive_streams) override {
2546 send_stream_ = send_stream;
2547 }
2548
stefanff483612015-12-21 03:14:00 -08002549 void ModifyVideoConfigs(
2550 VideoSendStream::Config* send_config,
2551 std::vector<VideoReceiveStream::Config>* receive_configs,
2552 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002553 send_config->encoder_settings.encoder = this;
perkj57c21f92016-06-17 07:27:16 -07002554 RTC_DCHECK_EQ(1u, encoder_config->streams.size());
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002555 }
2556
2557 int32_t SetRates(uint32_t new_target_bitrate, uint32_t framerate) override {
2558 // Make sure not to trigger on any default zero bitrates.
2559 if (new_target_bitrate == 0)
2560 return 0;
Peter Boströmf2f82832015-05-01 13:00:41 +02002561 rtc::CritScope lock(&crit_);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002562 bitrate_kbps_ = new_target_bitrate;
Peter Boström5811a392015-12-10 13:02:50 +01002563 observation_complete_.Set();
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002564 return 0;
2565 }
2566
2567 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002568 ASSERT_TRUE(Wait())
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002569 << "Timed out while waiting for encoder SetRates() call.";
perkjf5b2e512016-07-05 08:34:04 -07002570 WaitForEncoderTargetBitrateMatchStats();
2571 send_stream_->Stop();
2572 WaitForStatsReportZeroTargetBitrate();
2573 send_stream_->Start();
2574 WaitForEncoderTargetBitrateMatchStats();
2575 }
2576
2577 void WaitForEncoderTargetBitrateMatchStats() {
Peter Boström5811a392015-12-10 13:02:50 +01002578 for (int i = 0; i < kDefaultTimeoutMs; ++i) {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002579 VideoSendStream::Stats stats = send_stream_->GetStats();
2580 {
Peter Boströmf2f82832015-05-01 13:00:41 +02002581 rtc::CritScope lock(&crit_);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002582 if ((stats.target_media_bitrate_bps + 500) / 1000 ==
2583 static_cast<int>(bitrate_kbps_)) {
2584 return;
2585 }
2586 }
2587 SleepMs(1);
2588 }
2589 FAIL()
2590 << "Timed out waiting for stats reporting the currently set bitrate.";
2591 }
2592
perkjf5b2e512016-07-05 08:34:04 -07002593 void WaitForStatsReportZeroTargetBitrate() {
2594 for (int i = 0; i < kDefaultTimeoutMs; ++i) {
2595 if (send_stream_->GetStats().target_media_bitrate_bps == 0) {
2596 return;
2597 }
2598 SleepMs(1);
2599 }
2600 FAIL() << "Timed out waiting for stats reporting zero bitrate.";
2601 }
2602
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002603 private:
stefanf116bd02015-10-27 08:29:42 -07002604 rtc::CriticalSection crit_;
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002605 VideoSendStream* send_stream_;
2606 uint32_t bitrate_kbps_ GUARDED_BY(crit_);
2607 } test;
2608
stefane74eef12016-01-08 06:47:13 -08002609 RunBaseTest(&test);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002610}
2611
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002612TEST_F(EndToEndTest, GetStats) {
2613 static const int kStartBitrateBps = 3000000;
Peter Boströmdef398832015-05-27 17:59:11 +02002614 static const int kExpectedRenderDelayMs = 20;
tommi2e82f382016-06-21 00:26:43 -07002615
2616 class ReceiveStreamRenderer : public rtc::VideoSinkInterface<VideoFrame> {
2617 public:
2618 ReceiveStreamRenderer() {}
2619
2620 private:
2621 void OnFrame(const VideoFrame& video_frame) override {}
2622 };
2623
nissed30a1112016-04-18 05:15:22 -07002624 class StatsObserver : public test::EndToEndTest,
2625 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002626 public:
stefanf116bd02015-10-27 08:29:42 -07002627 StatsObserver()
2628 : EndToEndTest(kLongTimeoutMs),
Peter Boströmc6e16e32016-02-05 14:15:53 +01002629 encoder_(Clock::GetRealTimeClock(), 10),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00002630 send_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002631 expected_send_ssrcs_(),
Peter Boström5811a392015-12-10 13:02:50 +01002632 check_stats_event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002633
2634 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002635 Action OnSendRtp(const uint8_t* packet, size_t length) override {
sprangcd349d92016-07-13 09:11:28 -07002636 // Drop every 25th packet => 4% loss.
2637 static const int kPacketLossFrac = 25;
2638 RTPHeader header;
2639 RtpUtility::RtpHeaderParser parser(packet, length);
2640 if (parser.Parse(&header) &&
2641 expected_send_ssrcs_.find(header.ssrc) !=
2642 expected_send_ssrcs_.end() &&
2643 header.sequenceNumber % kPacketLossFrac == 0) {
2644 return DROP_PACKET;
2645 }
Peter Boström5811a392015-12-10 13:02:50 +01002646 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002647 return SEND_PACKET;
2648 }
2649
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002650 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002651 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002652 return SEND_PACKET;
2653 }
2654
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002655 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002656 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002657 return SEND_PACKET;
2658 }
2659
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002660 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002661 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002662 return SEND_PACKET;
2663 }
2664
nissed30a1112016-04-18 05:15:22 -07002665 void OnFrame(const VideoFrame& video_frame) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002666 // Ensure that we have at least 5ms send side delay.
nissed30a1112016-04-18 05:15:22 -07002667 SleepMs(5);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002668 }
2669
2670 bool CheckReceiveStats() {
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002671 for (size_t i = 0; i < receive_streams_.size(); ++i) {
2672 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
2673 EXPECT_EQ(expected_receive_ssrcs_[i], stats.ssrc);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002674
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002675 // Make sure all fields have been populated.
2676 // TODO(pbos): Use CompoundKey if/when we ever know that all stats are
2677 // always filled for all receivers.
2678 receive_stats_filled_["IncomingRate"] |=
2679 stats.network_frame_rate != 0 || stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002680
Peter Boströmb7d9a972015-12-18 16:01:11 +01002681 send_stats_filled_["DecoderImplementationName"] |=
2682 stats.decoder_implementation_name ==
2683 test::FakeDecoder::kImplementationName;
Peter Boströmdef398832015-05-27 17:59:11 +02002684 receive_stats_filled_["RenderDelayAsHighAsExpected"] |=
2685 stats.render_delay_ms >= kExpectedRenderDelayMs;
2686
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002687 receive_stats_filled_["FrameCallback"] |= stats.decode_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002688
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002689 receive_stats_filled_["FrameRendered"] |= stats.render_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002690
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002691 receive_stats_filled_["StatisticsUpdated"] |=
2692 stats.rtcp_stats.cumulative_lost != 0 ||
2693 stats.rtcp_stats.extended_max_sequence_number != 0 ||
2694 stats.rtcp_stats.fraction_lost != 0 || stats.rtcp_stats.jitter != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002695
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002696 receive_stats_filled_["DataCountersUpdated"] |=
2697 stats.rtp_stats.transmitted.payload_bytes != 0 ||
2698 stats.rtp_stats.fec.packets != 0 ||
2699 stats.rtp_stats.transmitted.header_bytes != 0 ||
2700 stats.rtp_stats.transmitted.packets != 0 ||
2701 stats.rtp_stats.transmitted.padding_bytes != 0 ||
2702 stats.rtp_stats.retransmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002703
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002704 receive_stats_filled_["CodecStats"] |=
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002705 stats.target_delay_ms != 0 || stats.discarded_packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002706
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002707 receive_stats_filled_["FrameCounts"] |=
2708 stats.frame_counts.key_frames != 0 ||
2709 stats.frame_counts.delta_frames != 0;
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002710
pbosbb36fdf2015-07-09 07:48:14 -07002711 receive_stats_filled_["CName"] |= !stats.c_name.empty();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002712
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002713 receive_stats_filled_["RtcpPacketTypeCount"] |=
2714 stats.rtcp_packet_type_counts.fir_packets != 0 ||
2715 stats.rtcp_packet_type_counts.nack_packets != 0 ||
2716 stats.rtcp_packet_type_counts.pli_packets != 0 ||
2717 stats.rtcp_packet_type_counts.nack_requests != 0 ||
2718 stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbosf42376c2015-08-28 07:35:32 -07002719
2720 assert(stats.current_payload_type == -1 ||
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002721 stats.current_payload_type == kFakeVideoSendPayloadType);
pbosf42376c2015-08-28 07:35:32 -07002722 receive_stats_filled_["IncomingPayloadType"] |=
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002723 stats.current_payload_type == kFakeVideoSendPayloadType;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002724 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002725
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002726 return AllStatsFilled(receive_stats_filled_);
2727 }
2728
2729 bool CheckSendStats() {
Peter Boström74f6e9e2016-04-04 17:56:10 +02002730 RTC_DCHECK(send_stream_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002731 VideoSendStream::Stats stats = send_stream_->GetStats();
2732
2733 send_stats_filled_["NumStreams"] |=
2734 stats.substreams.size() == expected_send_ssrcs_.size();
2735
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00002736 send_stats_filled_["CpuOveruseMetrics"] |=
Peter Boströme4499152016-02-05 11:13:28 +01002737 stats.avg_encode_time_ms != 0 && stats.encode_usage_percent != 0;
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00002738
Peter Boströmb7d9a972015-12-18 16:01:11 +01002739 send_stats_filled_["EncoderImplementationName"] |=
2740 stats.encoder_implementation_name ==
2741 test::FakeEncoder::kImplementationName;
2742
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002743 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002744 stats.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002745 it != stats.substreams.end(); ++it) {
sprangcd349d92016-07-13 09:11:28 -07002746 if (expected_send_ssrcs_.find(it->first) == expected_send_ssrcs_.end())
2747 continue; // Probably RTX.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002748
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002749 send_stats_filled_[CompoundKey("CapturedFrameRate", it->first)] |=
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002750 stats.input_frame_rate != 0;
2751
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002752 const VideoSendStream::StreamStats& stream_stats = it->second;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002753
2754 send_stats_filled_[CompoundKey("StatisticsUpdated", it->first)] |=
2755 stream_stats.rtcp_stats.cumulative_lost != 0 ||
2756 stream_stats.rtcp_stats.extended_max_sequence_number != 0 ||
2757 stream_stats.rtcp_stats.fraction_lost != 0;
2758
2759 send_stats_filled_[CompoundKey("DataCountersUpdated", it->first)] |=
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00002760 stream_stats.rtp_stats.fec.packets != 0 ||
2761 stream_stats.rtp_stats.transmitted.padding_bytes != 0 ||
2762 stream_stats.rtp_stats.retransmitted.packets != 0 ||
2763 stream_stats.rtp_stats.transmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002764
sprangcd349d92016-07-13 09:11:28 -07002765 send_stats_filled_[CompoundKey("BitrateStatisticsObserver.Total",
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002766 it->first)] |=
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002767 stream_stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002768
sprangcd349d92016-07-13 09:11:28 -07002769 send_stats_filled_[CompoundKey("BitrateStatisticsObserver.Retransmit",
2770 it->first)] |=
2771 stream_stats.retransmit_bitrate_bps != 0;
2772
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002773 send_stats_filled_[CompoundKey("FrameCountObserver", it->first)] |=
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002774 stream_stats.frame_counts.delta_frames != 0 ||
2775 stream_stats.frame_counts.key_frames != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002776
2777 send_stats_filled_[CompoundKey("OutgoingRate", it->first)] |=
2778 stats.encode_frame_rate != 0;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +00002779
2780 send_stats_filled_[CompoundKey("Delay", it->first)] |=
2781 stream_stats.avg_delay_ms != 0 || stream_stats.max_delay_ms != 0;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002782
2783 // TODO(pbos): Use CompoundKey when the test makes sure that all SSRCs
2784 // report dropped packets.
2785 send_stats_filled_["RtcpPacketTypeCount"] |=
2786 stream_stats.rtcp_packet_type_counts.fir_packets != 0 ||
2787 stream_stats.rtcp_packet_type_counts.nack_packets != 0 ||
2788 stream_stats.rtcp_packet_type_counts.pli_packets != 0 ||
2789 stream_stats.rtcp_packet_type_counts.nack_requests != 0 ||
2790 stream_stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002791 }
2792
2793 return AllStatsFilled(send_stats_filled_);
2794 }
2795
2796 std::string CompoundKey(const char* name, uint32_t ssrc) {
2797 std::ostringstream oss;
2798 oss << name << "_" << ssrc;
2799 return oss.str();
2800 }
2801
2802 bool AllStatsFilled(const std::map<std::string, bool>& stats_map) {
sprangcd349d92016-07-13 09:11:28 -07002803 for (const auto& stat : stats_map) {
2804 if (!stat.second)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002805 return false;
2806 }
2807 return true;
2808 }
2809
stefane74eef12016-01-08 06:47:13 -08002810 test::PacketTransport* CreateSendTransport(Call* sender_call) override {
2811 FakeNetworkPipe::Config network_config;
2812 network_config.loss_percent = 5;
2813 return new test::PacketTransport(
2814 sender_call, this, test::PacketTransport::kSender, network_config);
2815 }
2816
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002817 Call::Config GetSenderCallConfig() override {
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002818 Call::Config config = EndToEndTest::GetSenderCallConfig();
Stefan Holmere5904162015-03-26 11:11:06 +01002819 config.bitrate_config.start_bitrate_bps = kStartBitrateBps;
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002820 return config;
2821 }
2822
stefanff483612015-12-21 03:14:00 -08002823 void ModifyVideoConfigs(
2824 VideoSendStream::Config* send_config,
2825 std::vector<VideoReceiveStream::Config>* receive_configs,
2826 VideoEncoderConfig* encoder_config) override {
sprangcd349d92016-07-13 09:11:28 -07002827 // Set low rates to avoid waiting for rampup.
2828 for (size_t i = 0; i < encoder_config->streams.size(); ++i) {
2829 encoder_config->streams[i].min_bitrate_bps = 10000;
2830 encoder_config->streams[i].target_bitrate_bps = 15000;
2831 encoder_config->streams[i].max_bitrate_bps = 20000;
2832 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002833 send_config->pre_encode_callback = this; // Used to inject delay.
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002834 expected_cname_ = send_config->rtp.c_name = "SomeCName";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002835
sprangcd349d92016-07-13 09:11:28 -07002836 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2837 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
2838
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002839 const std::vector<uint32_t>& ssrcs = send_config->rtp.ssrcs;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002840 for (size_t i = 0; i < ssrcs.size(); ++i) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002841 expected_send_ssrcs_.insert(ssrcs[i]);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002842 expected_receive_ssrcs_.push_back(
2843 (*receive_configs)[i].rtp.remote_ssrc);
Peter Boströmdef398832015-05-27 17:59:11 +02002844 (*receive_configs)[i].render_delay_ms = kExpectedRenderDelayMs;
tommi2e82f382016-06-21 00:26:43 -07002845 (*receive_configs)[i].renderer = &receive_stream_renderer_;
sprangcd349d92016-07-13 09:11:28 -07002846 (*receive_configs)[i].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2847
2848 (*receive_configs)[i].rtp.rtx[kFakeVideoSendPayloadType].ssrc =
2849 kSendRtxSsrcs[i];
2850 (*receive_configs)[i].rtp.rtx[kFakeVideoSendPayloadType].payload_type =
2851 kSendRtxPayloadType;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002852 }
sprangcd349d92016-07-13 09:11:28 -07002853
2854 for (size_t i = 0; i < kNumSsrcs; ++i)
2855 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
2856
Peter Boströmc6e16e32016-02-05 14:15:53 +01002857 // Use a delayed encoder to make sure we see CpuOveruseMetrics stats that
2858 // are non-zero.
2859 send_config->encoder_settings.encoder = &encoder_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002860 }
2861
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002862 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.orgece38902014-11-14 11:52:04 +00002863
stefanff483612015-12-21 03:14:00 -08002864 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002865 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002866 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002867 send_stream_ = send_stream;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002868 receive_streams_ = receive_streams;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002869 }
2870
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002871 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002872 Clock* clock = Clock::GetRealTimeClock();
2873 int64_t now = clock->TimeInMilliseconds();
2874 int64_t stop_time = now + test::CallTest::kLongTimeoutMs;
2875 bool receive_ok = false;
2876 bool send_ok = false;
2877
2878 while (now < stop_time) {
2879 if (!receive_ok)
2880 receive_ok = CheckReceiveStats();
2881 if (!send_ok)
2882 send_ok = CheckSendStats();
2883
2884 if (receive_ok && send_ok)
2885 return;
2886
2887 int64_t time_until_timout_ = stop_time - now;
2888 if (time_until_timout_ > 0)
Peter Boström5811a392015-12-10 13:02:50 +01002889 check_stats_event_.Wait(time_until_timout_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002890 now = clock->TimeInMilliseconds();
2891 }
2892
2893 ADD_FAILURE() << "Timed out waiting for filled stats.";
2894 for (std::map<std::string, bool>::const_iterator it =
2895 receive_stats_filled_.begin();
2896 it != receive_stats_filled_.end();
2897 ++it) {
2898 if (!it->second) {
2899 ADD_FAILURE() << "Missing receive stats: " << it->first;
2900 }
2901 }
2902
2903 for (std::map<std::string, bool>::const_iterator it =
2904 send_stats_filled_.begin();
2905 it != send_stats_filled_.end();
2906 ++it) {
2907 if (!it->second) {
2908 ADD_FAILURE() << "Missing send stats: " << it->first;
2909 }
2910 }
2911 }
2912
Peter Boströmc6e16e32016-02-05 14:15:53 +01002913 test::DelayedEncoder encoder_;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002914 std::vector<VideoReceiveStream*> receive_streams_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002915 std::map<std::string, bool> receive_stats_filled_;
2916
2917 VideoSendStream* send_stream_;
2918 std::map<std::string, bool> send_stats_filled_;
2919
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002920 std::vector<uint32_t> expected_receive_ssrcs_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002921 std::set<uint32_t> expected_send_ssrcs_;
2922 std::string expected_cname_;
2923
Peter Boström5811a392015-12-10 13:02:50 +01002924 rtc::Event check_stats_event_;
tommi2e82f382016-06-21 00:26:43 -07002925 ReceiveStreamRenderer receive_stream_renderer_;
stefanf116bd02015-10-27 08:29:42 -07002926 } test;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002927
stefane74eef12016-01-08 06:47:13 -08002928 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002929}
2930
2931TEST_F(EndToEndTest, ReceiverReferenceTimeReportEnabled) {
2932 TestXrReceiverReferenceTimeReport(true);
2933}
2934
2935TEST_F(EndToEndTest, ReceiverReferenceTimeReportDisabled) {
2936 TestXrReceiverReferenceTimeReport(false);
2937}
2938
2939TEST_F(EndToEndTest, TestReceivedRtpPacketStats) {
2940 static const size_t kNumRtpPacketsToSend = 5;
2941 class ReceivedRtpStatsObserver : public test::EndToEndTest {
2942 public:
2943 ReceivedRtpStatsObserver()
2944 : EndToEndTest(kDefaultTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00002945 receive_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002946 sent_rtp_(0) {}
2947
2948 private:
stefanff483612015-12-21 03:14:00 -08002949 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002950 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002951 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002952 receive_stream_ = receive_streams[0];
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002953 }
2954
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002955 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002956 if (sent_rtp_ >= kNumRtpPacketsToSend) {
2957 VideoReceiveStream::Stats stats = receive_stream_->GetStats();
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00002958 if (kNumRtpPacketsToSend == stats.rtp_stats.transmitted.packets) {
Peter Boström5811a392015-12-10 13:02:50 +01002959 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002960 }
2961 return DROP_PACKET;
2962 }
2963 ++sent_rtp_;
2964 return SEND_PACKET;
2965 }
2966
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002967 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002968 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002969 << "Timed out while verifying number of received RTP packets.";
2970 }
2971
2972 VideoReceiveStream* receive_stream_;
2973 uint32_t sent_rtp_;
2974 } test;
2975
stefane74eef12016-01-08 06:47:13 -08002976 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002977}
2978
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002979TEST_F(EndToEndTest, SendsSetSsrc) { TestSendsSetSsrcs(1, false); }
2980
2981TEST_F(EndToEndTest, SendsSetSimulcastSsrcs) {
2982 TestSendsSetSsrcs(kNumSsrcs, false);
2983}
2984
2985TEST_F(EndToEndTest, CanSwitchToUseAllSsrcs) {
2986 TestSendsSetSsrcs(kNumSsrcs, true);
2987}
2988
mflodman@webrtc.orgf9460682014-07-24 16:41:25 +00002989TEST_F(EndToEndTest, DISABLED_RedundantPayloadsTransmittedOnAllSsrcs) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002990 class ObserveRedundantPayloads: public test::EndToEndTest {
2991 public:
2992 ObserveRedundantPayloads()
2993 : EndToEndTest(kDefaultTimeoutMs), ssrcs_to_observe_(kNumSsrcs) {
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00002994 for (size_t i = 0; i < kNumSsrcs; ++i) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002995 registered_rtx_ssrc_[kSendRtxSsrcs[i]] = true;
2996 }
2997 }
2998
2999 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003000 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003001 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00003002 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003003
3004 if (!registered_rtx_ssrc_[header.ssrc])
3005 return SEND_PACKET;
3006
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00003007 EXPECT_LE(header.headerLength + header.paddingLength, length);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003008 const bool packet_is_redundant_payload =
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00003009 header.headerLength + header.paddingLength < length;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003010
3011 if (!packet_is_redundant_payload)
3012 return SEND_PACKET;
3013
3014 if (!observed_redundant_retransmission_[header.ssrc]) {
3015 observed_redundant_retransmission_[header.ssrc] = true;
3016 if (--ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01003017 observation_complete_.Set();
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003018 }
3019
3020 return SEND_PACKET;
3021 }
3022
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003023 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003024
stefanff483612015-12-21 03:14:00 -08003025 void ModifyVideoConfigs(
3026 VideoSendStream::Config* send_config,
3027 std::vector<VideoReceiveStream::Config>* receive_configs,
3028 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003029 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00003030 for (size_t i = 0; i < encoder_config->streams.size(); ++i) {
3031 encoder_config->streams[i].min_bitrate_bps = 10000;
3032 encoder_config->streams[i].target_bitrate_bps = 15000;
3033 encoder_config->streams[i].max_bitrate_bps = 20000;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003034 }
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003035
3036 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003037
3038 for (size_t i = 0; i < kNumSsrcs; ++i)
3039 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.orgad3b5a52014-10-24 09:23:21 +00003040
3041 // Significantly higher than max bitrates for all video streams -> forcing
3042 // padding to trigger redundant padding on all RTX SSRCs.
3043 encoder_config->min_transmit_bitrate_bps = 100000;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003044 }
3045
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003046 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003047 EXPECT_TRUE(Wait())
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003048 << "Timed out while waiting for redundant payloads on all SSRCs.";
3049 }
3050
3051 private:
3052 size_t ssrcs_to_observe_;
3053 std::map<uint32_t, bool> observed_redundant_retransmission_;
3054 std::map<uint32_t, bool> registered_rtx_ssrc_;
3055 } test;
3056
stefane74eef12016-01-08 06:47:13 -08003057 RunBaseTest(&test);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003058}
3059
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003060void EndToEndTest::TestRtpStatePreservation(bool use_rtx,
3061 bool provoke_rtcpsr_before_rtp) {
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003062 class RtpSequenceObserver : public test::RtpRtcpObserver {
3063 public:
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00003064 explicit RtpSequenceObserver(bool use_rtx)
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003065 : test::RtpRtcpObserver(kDefaultTimeoutMs),
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003066 ssrcs_to_observe_(kNumSsrcs) {
3067 for (size_t i = 0; i < kNumSsrcs; ++i) {
danilchap32cd2c42016-08-01 06:58:34 -07003068 ssrc_is_rtx_[kVideoSendSsrcs[i]] = false;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003069 if (use_rtx)
danilchap32cd2c42016-08-01 06:58:34 -07003070 ssrc_is_rtx_[kSendRtxSsrcs[i]] = true;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003071 }
3072 }
3073
3074 void ResetExpectedSsrcs(size_t num_expected_ssrcs) {
Peter Boströmf2f82832015-05-01 13:00:41 +02003075 rtc::CritScope lock(&crit_);
danilchap34877ee2016-02-01 08:25:04 -08003076 ssrc_observed_.clear();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003077 ssrcs_to_observe_ = num_expected_ssrcs;
3078 }
3079
3080 private:
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003081 void ValidateTimestampGap(uint32_t ssrc,
3082 uint32_t timestamp,
3083 bool only_padding)
3084 EXCLUSIVE_LOCKS_REQUIRED(crit_) {
3085 static const int32_t kMaxTimestampGap = kDefaultTimeoutMs * 90;
3086 auto timestamp_it = last_observed_timestamp_.find(ssrc);
3087 if (timestamp_it == last_observed_timestamp_.end()) {
3088 EXPECT_FALSE(only_padding);
3089 last_observed_timestamp_[ssrc] = timestamp;
3090 } else {
3091 // Verify timestamps are reasonably close.
3092 uint32_t latest_observed = timestamp_it->second;
3093 // Wraparound handling is unnecessary here as long as an int variable
3094 // is used to store the result.
3095 int32_t timestamp_gap = timestamp - latest_observed;
3096 EXPECT_LE(std::abs(timestamp_gap), kMaxTimestampGap)
3097 << "Gap in timestamps (" << latest_observed << " -> " << timestamp
3098 << ") too large for SSRC: " << ssrc << ".";
3099 timestamp_it->second = timestamp;
3100 }
3101 }
3102
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003103 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003104 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00003105 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003106 const uint32_t ssrc = header.ssrc;
danilchap5c35cf92016-02-03 14:14:49 -08003107 const int64_t sequence_number =
3108 seq_numbers_unwrapper_.Unwrap(header.sequenceNumber);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003109 const uint32_t timestamp = header.timestamp;
danilchap34877ee2016-02-01 08:25:04 -08003110 const bool only_padding =
3111 header.headerLength + header.paddingLength == length;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003112
danilchap32cd2c42016-08-01 06:58:34 -07003113 EXPECT_TRUE(ssrc_is_rtx_.find(ssrc) != ssrc_is_rtx_.end())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003114 << "Received SSRC that wasn't configured: " << ssrc;
3115
danilchap5c35cf92016-02-03 14:14:49 -08003116 static const int64_t kMaxSequenceNumberGap = 100;
3117 std::list<int64_t>* seq_numbers = &last_observed_seq_numbers_[ssrc];
3118 if (seq_numbers->empty()) {
3119 seq_numbers->push_back(sequence_number);
3120 } else {
3121 // We shouldn't get replays of previous sequence numbers.
3122 for (int64_t observed : *seq_numbers) {
3123 EXPECT_NE(observed, sequence_number)
3124 << "Received sequence number " << sequence_number
3125 << " for SSRC " << ssrc << " 2nd time.";
3126 }
3127 // Verify sequence numbers are reasonably close.
3128 int64_t latest_observed = seq_numbers->back();
3129 int64_t sequence_number_gap = sequence_number - latest_observed;
3130 EXPECT_LE(std::abs(sequence_number_gap), kMaxSequenceNumberGap)
3131 << "Gap in sequence numbers (" << latest_observed << " -> "
3132 << sequence_number << ") too large for SSRC: " << ssrc << ".";
3133 seq_numbers->push_back(sequence_number);
3134 if (seq_numbers->size() >= kMaxSequenceNumberGap) {
3135 seq_numbers->pop_front();
3136 }
3137 }
3138
danilchap32cd2c42016-08-01 06:58:34 -07003139 if (!ssrc_is_rtx_[ssrc]) {
3140 rtc::CritScope lock(&crit_);
3141 ValidateTimestampGap(ssrc, timestamp, only_padding);
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003142
danilchap32cd2c42016-08-01 06:58:34 -07003143 // Wait for media packets on all ssrcs.
3144 if (!ssrc_observed_[ssrc] && !only_padding) {
3145 ssrc_observed_[ssrc] = true;
3146 if (--ssrcs_to_observe_ == 0)
3147 observation_complete_.Set();
3148 }
danilchap34877ee2016-02-01 08:25:04 -08003149 }
3150
danilchapf4b9c772016-01-28 06:14:24 -08003151 return SEND_PACKET;
3152 }
3153
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003154 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
3155 test::RtcpPacketParser rtcp_parser;
3156 rtcp_parser.Parse(packet, length);
3157 if (rtcp_parser.sender_report()->num_packets() > 0) {
3158 uint32_t ssrc = rtcp_parser.sender_report()->Ssrc();
3159 uint32_t rtcp_timestamp = rtcp_parser.sender_report()->RtpTimestamp();
3160
3161 rtc::CritScope lock(&crit_);
3162 ValidateTimestampGap(ssrc, rtcp_timestamp, false);
3163 }
3164 return SEND_PACKET;
3165 }
3166
danilchap5c35cf92016-02-03 14:14:49 -08003167 SequenceNumberUnwrapper seq_numbers_unwrapper_;
3168 std::map<uint32_t, std::list<int64_t>> last_observed_seq_numbers_;
danilchap34877ee2016-02-01 08:25:04 -08003169 std::map<uint32_t, uint32_t> last_observed_timestamp_;
danilchap32cd2c42016-08-01 06:58:34 -07003170 std::map<uint32_t, bool> ssrc_is_rtx_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003171
Peter Boströmf2f82832015-05-01 13:00:41 +02003172 rtc::CriticalSection crit_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003173 size_t ssrcs_to_observe_ GUARDED_BY(crit_);
danilchap34877ee2016-02-01 08:25:04 -08003174 std::map<uint32_t, bool> ssrc_observed_ GUARDED_BY(crit_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003175 } observer(use_rtx);
3176
solenberg4fbae2b2015-08-28 04:07:10 -07003177 CreateCalls(Call::Config(), Call::Config());
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003178
stefanf116bd02015-10-27 08:29:42 -07003179 test::PacketTransport send_transport(sender_call_.get(), &observer,
3180 test::PacketTransport::kSender,
3181 FakeNetworkPipe::Config());
3182 test::PacketTransport receive_transport(nullptr, &observer,
3183 test::PacketTransport::kReceiver,
3184 FakeNetworkPipe::Config());
3185 send_transport.SetReceiver(receiver_call_->Receiver());
3186 receive_transport.SetReceiver(sender_call_->Receiver());
3187
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003188 CreateSendConfig(kNumSsrcs, 0, &send_transport);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003189
3190 if (use_rtx) {
3191 for (size_t i = 0; i < kNumSsrcs; ++i) {
stefanff483612015-12-21 03:14:00 -08003192 video_send_config_.rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003193 }
stefanff483612015-12-21 03:14:00 -08003194 video_send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003195 }
3196
3197 // Lower bitrates so that all streams send initially.
stefanff483612015-12-21 03:14:00 -08003198 for (size_t i = 0; i < video_encoder_config_.streams.size(); ++i) {
3199 video_encoder_config_.streams[i].min_bitrate_bps = 10000;
3200 video_encoder_config_.streams[i].target_bitrate_bps = 15000;
3201 video_encoder_config_.streams[i].max_bitrate_bps = 20000;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003202 }
3203
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003204 // Use the same total bitrates when sending a single stream to avoid lowering
3205 // the bitrate estimate and requiring a subsequent rampup.
perkj8eb37a32016-08-16 02:40:55 -07003206 VideoEncoderConfig one_stream = video_encoder_config_;
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003207 one_stream.streams.resize(1);
stefanff483612015-12-21 03:14:00 -08003208 for (size_t i = 1; i < video_encoder_config_.streams.size(); ++i) {
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003209 one_stream.streams.front().min_bitrate_bps +=
stefanff483612015-12-21 03:14:00 -08003210 video_encoder_config_.streams[i].min_bitrate_bps;
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003211 one_stream.streams.front().target_bitrate_bps +=
stefanff483612015-12-21 03:14:00 -08003212 video_encoder_config_.streams[i].target_bitrate_bps;
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003213 one_stream.streams.front().max_bitrate_bps +=
stefanff483612015-12-21 03:14:00 -08003214 video_encoder_config_.streams[i].max_bitrate_bps;
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003215 }
3216
stefanf116bd02015-10-27 08:29:42 -07003217 CreateMatchingReceiveConfigs(&receive_transport);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003218
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003219 CreateVideoStreams();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003220 CreateFrameGeneratorCapturer();
3221
3222 Start();
Peter Boström5811a392015-12-10 13:02:50 +01003223 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003224 << "Timed out waiting for all SSRCs to send packets.";
3225
3226 // Test stream resetting more than once to make sure that the state doesn't
3227 // get set once (this could be due to using std::map::insert for instance).
3228 for (size_t i = 0; i < 3; ++i) {
3229 frame_generator_capturer_->Stop();
stefanff483612015-12-21 03:14:00 -08003230 sender_call_->DestroyVideoSendStream(video_send_stream_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003231
3232 // Re-create VideoSendStream with only one stream.
perkj8eb37a32016-08-16 02:40:55 -07003233 video_send_stream_ =
3234 sender_call_->CreateVideoSendStream(video_send_config_, one_stream);
stefanff483612015-12-21 03:14:00 -08003235 video_send_stream_->Start();
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003236 if (provoke_rtcpsr_before_rtp) {
3237 // Rapid Resync Request forces sending RTCP Sender Report back.
3238 // Using this request speeds up this test because then there is no need
3239 // to wait for a second for periodic Sender Report.
3240 rtcp::RapidResyncRequest force_send_sr_back_request;
3241 rtc::Buffer packet = force_send_sr_back_request.Build();
3242 static_cast<webrtc::test::DirectTransport&>(receive_transport)
3243 .SendRtcp(packet.data(), packet.size());
3244 }
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003245 CreateFrameGeneratorCapturer();
3246 frame_generator_capturer_->Start();
3247
3248 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01003249 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003250
3251 // Reconfigure back to use all streams.
perkj8eb37a32016-08-16 02:40:55 -07003252 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003253 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01003254 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003255 << "Timed out waiting for all SSRCs to send packets.";
3256
3257 // Reconfigure down to one stream.
perkj8eb37a32016-08-16 02:40:55 -07003258 video_send_stream_->ReconfigureVideoEncoder(one_stream);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003259 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01003260 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003261
3262 // Reconfigure back to use all streams.
perkj8eb37a32016-08-16 02:40:55 -07003263 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003264 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01003265 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003266 << "Timed out waiting for all SSRCs to send packets.";
3267 }
3268
stefanf116bd02015-10-27 08:29:42 -07003269 send_transport.StopSending();
3270 receive_transport.StopSending();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003271
3272 Stop();
3273 DestroyStreams();
3274}
3275
Peter Boströmfc968a22016-02-19 16:14:37 +01003276TEST_F(EndToEndTest, RestartingSendStreamPreservesRtpState) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003277 TestRtpStatePreservation(false, false);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003278}
3279
danilchap32cd2c42016-08-01 06:58:34 -07003280TEST_F(EndToEndTest, RestartingSendStreamPreservesRtpStatesWithRtx) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003281 TestRtpStatePreservation(true, false);
3282}
3283
danilchap32cd2c42016-08-01 06:58:34 -07003284TEST_F(EndToEndTest, RestartingSendStreamKeepsRtpAndRtcpTimestampsSynced) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003285 TestRtpStatePreservation(true, true);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003286}
3287
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003288TEST_F(EndToEndTest, RespectsNetworkState) {
3289 // TODO(pbos): Remove accepted downtime packets etc. when signaling network
3290 // down blocks until no more packets will be sent.
3291
3292 // Pacer will send from its packet list and then send required padding before
3293 // checking paused_ again. This should be enough for one round of pacing,
3294 // otherwise increase.
3295 static const int kNumAcceptedDowntimeRtp = 5;
3296 // A single RTCP may be in the pipeline.
3297 static const int kNumAcceptedDowntimeRtcp = 1;
3298 class NetworkStateTest : public test::EndToEndTest, public test::FakeEncoder {
3299 public:
3300 NetworkStateTest()
3301 : EndToEndTest(kDefaultTimeoutMs),
3302 FakeEncoder(Clock::GetRealTimeClock()),
Peter Boström5811a392015-12-10 13:02:50 +01003303 encoded_frames_(false, false),
3304 packet_event_(false, false),
sprang867fb522015-08-03 04:38:41 -07003305 sender_call_(nullptr),
3306 receiver_call_(nullptr),
Jelena Marusiccd670222015-07-16 09:30:09 +02003307 sender_state_(kNetworkUp),
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003308 sender_rtp_(0),
3309 sender_rtcp_(0),
3310 receiver_rtcp_(0),
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003311 down_frames_(0) {}
3312
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003313 Action OnSendRtp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003314 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003315 ++sender_rtp_;
Peter Boström5811a392015-12-10 13:02:50 +01003316 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003317 return SEND_PACKET;
3318 }
3319
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003320 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003321 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003322 ++sender_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01003323 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003324 return SEND_PACKET;
3325 }
3326
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003327 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003328 ADD_FAILURE() << "Unexpected receiver RTP, should not be sending.";
3329 return SEND_PACKET;
3330 }
3331
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003332 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003333 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003334 ++receiver_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01003335 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003336 return SEND_PACKET;
3337 }
3338
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003339 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003340 sender_call_ = sender_call;
3341 receiver_call_ = receiver_call;
3342 }
3343
stefanff483612015-12-21 03:14:00 -08003344 void ModifyVideoConfigs(
3345 VideoSendStream::Config* send_config,
3346 std::vector<VideoReceiveStream::Config>* receive_configs,
3347 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003348 send_config->encoder_settings.encoder = this;
3349 }
3350
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003351 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003352 EXPECT_TRUE(encoded_frames_.Wait(kDefaultTimeoutMs))
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003353 << "No frames received by the encoder.";
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003354 // Wait for packets from both sender/receiver.
3355 WaitForPacketsOrSilence(false, false);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003356
skvlad7a43d252016-03-22 15:32:27 -07003357 // Sender-side network down for audio; there should be no effect on video
3358 sender_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkDown);
3359 WaitForPacketsOrSilence(false, false);
3360
3361 // Receiver-side network down for audio; no change expected
3362 receiver_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkDown);
3363 WaitForPacketsOrSilence(false, false);
3364
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003365 // Sender-side network down.
skvlad7a43d252016-03-22 15:32:27 -07003366 sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkDown);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003367 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003368 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003369 // After network goes down we shouldn't be encoding more frames.
Jelena Marusiccd670222015-07-16 09:30:09 +02003370 sender_state_ = kNetworkDown;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003371 }
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003372 // Wait for receiver-packets and no sender packets.
3373 WaitForPacketsOrSilence(true, false);
3374
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003375 // Receiver-side network down.
skvlad7a43d252016-03-22 15:32:27 -07003376 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkDown);
3377 WaitForPacketsOrSilence(true, true);
3378
3379 // Network up for audio for both sides; video is still not expected to
3380 // start
3381 sender_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkUp);
3382 receiver_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkUp);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003383 WaitForPacketsOrSilence(true, true);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003384
3385 // Network back up again for both.
3386 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003387 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003388 // It's OK to encode frames again, as we're about to bring up the
3389 // network.
Jelena Marusiccd670222015-07-16 09:30:09 +02003390 sender_state_ = kNetworkUp;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003391 }
skvlad7a43d252016-03-22 15:32:27 -07003392 sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
3393 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003394 WaitForPacketsOrSilence(false, false);
skvlad7a43d252016-03-22 15:32:27 -07003395
3396 // TODO(skvlad): add tests to verify that the audio streams are stopped
3397 // when the network goes down for audio once the workaround in
3398 // paced_sender.cc is removed.
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003399 }
3400
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07003401 int32_t Encode(const VideoFrame& input_image,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003402 const CodecSpecificInfo* codec_specific_info,
pbos22993e12015-10-19 02:39:06 -07003403 const std::vector<FrameType>* frame_types) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003404 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003405 rtc::CritScope lock(&test_crit_);
Jelena Marusiccd670222015-07-16 09:30:09 +02003406 if (sender_state_ == kNetworkDown) {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003407 ++down_frames_;
3408 EXPECT_LE(down_frames_, 1)
3409 << "Encoding more than one frame while network is down.";
3410 if (down_frames_ > 1)
Peter Boström5811a392015-12-10 13:02:50 +01003411 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003412 } else {
Peter Boström5811a392015-12-10 13:02:50 +01003413 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003414 }
3415 }
3416 return test::FakeEncoder::Encode(
3417 input_image, codec_specific_info, frame_types);
3418 }
3419
3420 private:
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003421 void WaitForPacketsOrSilence(bool sender_down, bool receiver_down) {
3422 int64_t initial_time_ms = clock_->TimeInMilliseconds();
3423 int initial_sender_rtp;
3424 int initial_sender_rtcp;
3425 int initial_receiver_rtcp;
3426 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003427 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003428 initial_sender_rtp = sender_rtp_;
3429 initial_sender_rtcp = sender_rtcp_;
3430 initial_receiver_rtcp = receiver_rtcp_;
3431 }
3432 bool sender_done = false;
3433 bool receiver_done = false;
mflodmand1590b22015-12-09 07:07:59 -08003434 while (!sender_done || !receiver_done) {
Peter Boström5811a392015-12-10 13:02:50 +01003435 packet_event_.Wait(kSilenceTimeoutMs);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003436 int64_t time_now_ms = clock_->TimeInMilliseconds();
Peter Boströmf2f82832015-05-01 13:00:41 +02003437 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003438 if (sender_down) {
3439 ASSERT_LE(sender_rtp_ - initial_sender_rtp, kNumAcceptedDowntimeRtp)
3440 << "RTP sent during sender-side downtime.";
3441 ASSERT_LE(sender_rtcp_ - initial_sender_rtcp,
3442 kNumAcceptedDowntimeRtcp)
3443 << "RTCP sent during sender-side downtime.";
3444 if (time_now_ms - initial_time_ms >=
3445 static_cast<int64_t>(kSilenceTimeoutMs)) {
3446 sender_done = true;
3447 }
3448 } else {
skvlad7a43d252016-03-22 15:32:27 -07003449 if (sender_rtp_ > initial_sender_rtp + kNumAcceptedDowntimeRtp)
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003450 sender_done = true;
3451 }
3452 if (receiver_down) {
3453 ASSERT_LE(receiver_rtcp_ - initial_receiver_rtcp,
3454 kNumAcceptedDowntimeRtcp)
3455 << "RTCP sent during receiver-side downtime.";
3456 if (time_now_ms - initial_time_ms >=
3457 static_cast<int64_t>(kSilenceTimeoutMs)) {
3458 receiver_done = true;
3459 }
3460 } else {
skvlad7a43d252016-03-22 15:32:27 -07003461 if (receiver_rtcp_ > initial_receiver_rtcp + kNumAcceptedDowntimeRtcp)
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003462 receiver_done = true;
3463 }
3464 }
3465 }
3466
Peter Boströmf2f82832015-05-01 13:00:41 +02003467 rtc::CriticalSection test_crit_;
Peter Boström5811a392015-12-10 13:02:50 +01003468 rtc::Event encoded_frames_;
3469 rtc::Event packet_event_;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003470 Call* sender_call_;
3471 Call* receiver_call_;
Jelena Marusiccd670222015-07-16 09:30:09 +02003472 NetworkState sender_state_ GUARDED_BY(test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003473 int sender_rtp_ GUARDED_BY(test_crit_);
3474 int sender_rtcp_ GUARDED_BY(test_crit_);
3475 int receiver_rtcp_ GUARDED_BY(test_crit_);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003476 int down_frames_ GUARDED_BY(test_crit_);
3477 } test;
3478
stefane74eef12016-01-08 06:47:13 -08003479 RunBaseTest(&test);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003480}
3481
danilchapa6a70072016-06-01 11:20:43 -07003482TEST_F(EndToEndTest, CallReportsRttForSender) {
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003483 static const int kSendDelayMs = 30;
3484 static const int kReceiveDelayMs = 70;
3485
solenberg4fbae2b2015-08-28 04:07:10 -07003486 CreateCalls(Call::Config(), Call::Config());
3487
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003488 FakeNetworkPipe::Config config;
3489 config.queue_delay_ms = kSendDelayMs;
stefanf116bd02015-10-27 08:29:42 -07003490 test::DirectTransport sender_transport(config, sender_call_.get());
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003491 config.queue_delay_ms = kReceiveDelayMs;
stefanf116bd02015-10-27 08:29:42 -07003492 test::DirectTransport receiver_transport(config, receiver_call_.get());
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003493 sender_transport.SetReceiver(receiver_call_->Receiver());
3494 receiver_transport.SetReceiver(sender_call_->Receiver());
3495
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003496 CreateSendConfig(1, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07003497 CreateMatchingReceiveConfigs(&receiver_transport);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003498
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003499 CreateVideoStreams();
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003500 CreateFrameGeneratorCapturer();
3501 Start();
3502
3503 int64_t start_time_ms = clock_->TimeInMilliseconds();
3504 while (true) {
3505 Call::Stats stats = sender_call_->GetStats();
3506 ASSERT_GE(start_time_ms + kDefaultTimeoutMs,
3507 clock_->TimeInMilliseconds())
3508 << "No RTT stats before timeout!";
3509 if (stats.rtt_ms != -1) {
3510 EXPECT_GE(stats.rtt_ms, kSendDelayMs + kReceiveDelayMs);
3511 break;
3512 }
3513 SleepMs(10);
3514 }
3515
3516 Stop();
3517 DestroyStreams();
3518}
3519
skvlad7a43d252016-03-22 15:32:27 -07003520void EndToEndTest::VerifyNewVideoSendStreamsRespectNetworkState(
3521 MediaType network_to_bring_down,
3522 VideoEncoder* encoder,
3523 Transport* transport) {
solenberg4fbae2b2015-08-28 04:07:10 -07003524 CreateSenderCall(Call::Config());
skvlad7a43d252016-03-22 15:32:27 -07003525 sender_call_->SignalChannelNetworkState(network_to_bring_down, kNetworkDown);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003526
skvlad7a43d252016-03-22 15:32:27 -07003527 CreateSendConfig(1, 0, transport);
3528 video_send_config_.encoder_settings.encoder = encoder;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003529 CreateVideoStreams();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003530 CreateFrameGeneratorCapturer();
3531
3532 Start();
3533 SleepMs(kSilenceTimeoutMs);
3534 Stop();
3535
3536 DestroyStreams();
3537}
3538
skvlad7a43d252016-03-22 15:32:27 -07003539void EndToEndTest::VerifyNewVideoReceiveStreamsRespectNetworkState(
3540 MediaType network_to_bring_down,
3541 Transport* transport) {
solenberg4fbae2b2015-08-28 04:07:10 -07003542 CreateCalls(Call::Config(), Call::Config());
skvlad7a43d252016-03-22 15:32:27 -07003543 receiver_call_->SignalChannelNetworkState(network_to_bring_down,
3544 kNetworkDown);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003545
stefanf116bd02015-10-27 08:29:42 -07003546 test::DirectTransport sender_transport(sender_call_.get());
solenberg4fbae2b2015-08-28 04:07:10 -07003547 sender_transport.SetReceiver(receiver_call_->Receiver());
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003548 CreateSendConfig(1, 0, &sender_transport);
skvlad7a43d252016-03-22 15:32:27 -07003549 CreateMatchingReceiveConfigs(transport);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003550 CreateVideoStreams();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003551 CreateFrameGeneratorCapturer();
3552
3553 Start();
3554 SleepMs(kSilenceTimeoutMs);
3555 Stop();
3556
3557 sender_transport.StopSending();
3558
3559 DestroyStreams();
3560}
pbos@webrtc.org09cc6862014-11-04 13:48:15 +00003561
skvlad7a43d252016-03-22 15:32:27 -07003562TEST_F(EndToEndTest, NewVideoSendStreamsRespectVideoNetworkDown) {
3563 class UnusedEncoder : public test::FakeEncoder {
3564 public:
3565 UnusedEncoder() : FakeEncoder(Clock::GetRealTimeClock()) {}
perkjfea93092016-05-14 00:58:48 -07003566
3567 int32_t InitEncode(const VideoCodec* config,
3568 int32_t number_of_cores,
3569 size_t max_payload_size) override {
3570 EXPECT_GT(config->startBitrate, 0u);
3571 return 0;
3572 }
skvlad7a43d252016-03-22 15:32:27 -07003573 int32_t Encode(const VideoFrame& input_image,
3574 const CodecSpecificInfo* codec_specific_info,
3575 const std::vector<FrameType>* frame_types) override {
3576 ADD_FAILURE() << "Unexpected frame encode.";
3577 return test::FakeEncoder::Encode(input_image, codec_specific_info,
3578 frame_types);
3579 }
3580 };
3581
3582 UnusedEncoder unused_encoder;
3583 UnusedTransport unused_transport;
3584 VerifyNewVideoSendStreamsRespectNetworkState(
3585 MediaType::VIDEO, &unused_encoder, &unused_transport);
3586}
3587
3588TEST_F(EndToEndTest, NewVideoSendStreamsIgnoreAudioNetworkDown) {
3589 class RequiredEncoder : public test::FakeEncoder {
3590 public:
3591 RequiredEncoder()
3592 : FakeEncoder(Clock::GetRealTimeClock()), encoded_frame_(false) {}
3593 ~RequiredEncoder() {
3594 if (!encoded_frame_) {
3595 ADD_FAILURE() << "Didn't encode an expected frame";
3596 }
3597 }
3598 int32_t Encode(const VideoFrame& input_image,
3599 const CodecSpecificInfo* codec_specific_info,
3600 const std::vector<FrameType>* frame_types) override {
3601 encoded_frame_ = true;
3602 return test::FakeEncoder::Encode(input_image, codec_specific_info,
3603 frame_types);
3604 }
3605
3606 private:
3607 bool encoded_frame_;
3608 };
3609
3610 RequiredTransport required_transport(true /*rtp*/, false /*rtcp*/);
3611 RequiredEncoder required_encoder;
3612 VerifyNewVideoSendStreamsRespectNetworkState(
3613 MediaType::AUDIO, &required_encoder, &required_transport);
3614}
3615
3616TEST_F(EndToEndTest, NewVideoReceiveStreamsRespectVideoNetworkDown) {
3617 UnusedTransport transport;
3618 VerifyNewVideoReceiveStreamsRespectNetworkState(MediaType::VIDEO, &transport);
3619}
3620
3621TEST_F(EndToEndTest, NewVideoReceiveStreamsIgnoreAudioNetworkDown) {
3622 RequiredTransport transport(false /*rtp*/, true /*rtcp*/);
3623 VerifyNewVideoReceiveStreamsRespectNetworkState(MediaType::AUDIO, &transport);
3624}
3625
Peter Boströmd7da1202015-06-05 14:09:38 +02003626void VerifyEmptyNackConfig(const NackConfig& config) {
3627 EXPECT_EQ(0, config.rtp_history_ms)
3628 << "Enabling NACK requires rtcp-fb: nack negotiation.";
3629}
3630
3631void VerifyEmptyFecConfig(const FecConfig& config) {
3632 EXPECT_EQ(-1, config.ulpfec_payload_type)
3633 << "Enabling FEC requires rtpmap: ulpfec negotiation.";
3634 EXPECT_EQ(-1, config.red_payload_type)
3635 << "Enabling FEC requires rtpmap: red negotiation.";
3636 EXPECT_EQ(-1, config.red_rtx_payload_type)
3637 << "Enabling RTX in FEC requires rtpmap: rtx negotiation.";
3638}
3639
3640TEST_F(EndToEndTest, VerifyDefaultSendConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07003641 VideoSendStream::Config default_send_config(nullptr);
Peter Boströmd7da1202015-06-05 14:09:38 +02003642 EXPECT_EQ(0, default_send_config.rtp.nack.rtp_history_ms)
3643 << "Enabling NACK require rtcp-fb: nack negotiation.";
3644 EXPECT_TRUE(default_send_config.rtp.rtx.ssrcs.empty())
3645 << "Enabling RTX requires rtpmap: rtx negotiation.";
3646 EXPECT_TRUE(default_send_config.rtp.extensions.empty())
3647 << "Enabling RTP extensions require negotiation.";
3648
3649 VerifyEmptyNackConfig(default_send_config.rtp.nack);
3650 VerifyEmptyFecConfig(default_send_config.rtp.fec);
3651}
3652
3653TEST_F(EndToEndTest, VerifyDefaultReceiveConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07003654 VideoReceiveStream::Config default_receive_config(nullptr);
pbosda903ea2015-10-02 02:36:56 -07003655 EXPECT_EQ(RtcpMode::kCompound, default_receive_config.rtp.rtcp_mode)
Peter Boströmd7da1202015-06-05 14:09:38 +02003656 << "Reduced-size RTCP require rtcp-rsize to be negotiated.";
3657 EXPECT_FALSE(default_receive_config.rtp.remb)
3658 << "REMB require rtcp-fb: goog-remb to be negotiated.";
3659 EXPECT_FALSE(
3660 default_receive_config.rtp.rtcp_xr.receiver_reference_time_report)
3661 << "RTCP XR settings require rtcp-xr to be negotiated.";
3662 EXPECT_TRUE(default_receive_config.rtp.rtx.empty())
3663 << "Enabling RTX requires rtpmap: rtx negotiation.";
3664 EXPECT_TRUE(default_receive_config.rtp.extensions.empty())
3665 << "Enabling RTP extensions require negotiation.";
3666
3667 VerifyEmptyNackConfig(default_receive_config.rtp.nack);
3668 VerifyEmptyFecConfig(default_receive_config.rtp.fec);
3669}
3670
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003671TEST_F(EndToEndTest, TransportSeqNumOnAudioAndVideo) {
3672 static const int kExtensionId = 8;
3673 class TransportSequenceNumberTest : public test::EndToEndTest {
3674 public:
3675 TransportSequenceNumberTest()
3676 : EndToEndTest(kDefaultTimeoutMs),
3677 video_observed_(false),
3678 audio_observed_(false) {
3679 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
3680 kExtensionId);
3681 }
3682
3683 size_t GetNumVideoStreams() const override { return 1; }
3684 size_t GetNumAudioStreams() const override { return 1; }
3685
3686 void ModifyVideoConfigs(
3687 VideoSendStream::Config* send_config,
3688 std::vector<VideoReceiveStream::Config>* receive_configs,
3689 VideoEncoderConfig* encoder_config) override {
3690 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07003691 send_config->rtp.extensions.push_back(RtpExtension(
3692 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003693 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
3694 }
3695
3696 void ModifyAudioConfigs(
3697 AudioSendStream::Config* send_config,
3698 std::vector<AudioReceiveStream::Config>* receive_configs) override {
3699 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07003700 send_config->rtp.extensions.push_back(RtpExtension(
3701 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003702 (*receive_configs)[0].rtp.extensions.clear();
3703 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
3704 }
3705
3706 Action OnSendRtp(const uint8_t* packet, size_t length) override {
3707 RTPHeader header;
3708 EXPECT_TRUE(parser_->Parse(packet, length, &header));
3709 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
3710 // Unwrap packet id and verify uniqueness.
3711 int64_t packet_id =
3712 unwrapper_.Unwrap(header.extension.transportSequenceNumber);
3713 EXPECT_TRUE(received_packet_ids_.insert(packet_id).second);
3714
3715 if (header.ssrc == kVideoSendSsrcs[0])
3716 video_observed_ = true;
3717 if (header.ssrc == kAudioSendSsrc)
3718 audio_observed_ = true;
3719 if (audio_observed_ && video_observed_ &&
3720 received_packet_ids_.size() == 50) {
3721 size_t packet_id_range =
3722 *received_packet_ids_.rbegin() - *received_packet_ids_.begin() + 1;
3723 EXPECT_EQ(received_packet_ids_.size(), packet_id_range);
3724 observation_complete_.Set();
3725 }
3726 return SEND_PACKET;
3727 }
3728
3729 void PerformTest() override {
3730 EXPECT_TRUE(Wait()) << "Timed out while waiting for audio and video "
3731 "packets with transport sequence number.";
3732 }
3733
3734 private:
3735 bool video_observed_;
3736 bool audio_observed_;
3737 SequenceNumberUnwrapper unwrapper_;
3738 std::set<int64_t> received_packet_ids_;
3739 } test;
3740
stefane74eef12016-01-08 06:47:13 -08003741 RunBaseTest(&test);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003742}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003743} // namespace webrtc