blob: 286da6c221bc9cddfafb4a4586b732e0868cc107 [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
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +000018#include "webrtc/base/checks.h"
Erik Språng6b8d3552015-09-24 15:06:57 +020019#include "webrtc/base/event.h"
palmkviste75f2042016-09-28 06:19:48 -070020#include "webrtc/base/file.h"
Erik Språng737336d2016-07-29 12:59:36 +020021#include "webrtc/base/optional.h"
22#include "webrtc/base/rate_limiter.h"
ossuf515ab82016-12-07 04:52:58 -080023#include "webrtc/call/call.h"
pbosa96b60b2016-04-18 21:12:48 -070024#include "webrtc/common_video/include/frame_callback.h"
skvlad11a9cbf2016-10-07 11:53:05 -070025#include "webrtc/logging/rtc_event_log/rtc_event_log.h"
sakal55d932b2016-09-30 06:19:08 -070026#include "webrtc/media/base/fakevideorenderer.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"
sprangcd349d92016-07-13 09:11:28 -070032#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
hbosbab934b2016-01-27 01:36:03 -080033#include "webrtc/modules/video_coding/codecs/h264/include/h264.h"
marpan@webrtc.org5b883172014-11-01 06:10:48 +000034#include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h"
35#include "webrtc/modules/video_coding/codecs/vp9/include/vp9.h"
Henrik Kjellander2557b862015-11-18 22:00:21 +010036#include "webrtc/modules/video_coding/include/video_coding_defines.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010037#include "webrtc/system_wrappers/include/metrics.h"
asapersson01d70a32016-05-20 06:29:46 -070038#include "webrtc/system_wrappers/include/metrics_default.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010039#include "webrtc/system_wrappers/include/sleep.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000040#include "webrtc/test/call_test.h"
41#include "webrtc/test/direct_transport.h"
42#include "webrtc/test/encoder_settings.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000043#include "webrtc/test/fake_decoder.h"
44#include "webrtc/test/fake_encoder.h"
philipel266f0a42016-11-28 08:49:07 -080045#include "webrtc/test/field_trial.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000046#include "webrtc/test/frame_generator.h"
47#include "webrtc/test/frame_generator_capturer.h"
kwibergac9f8762016-09-30 22:29:43 -070048#include "webrtc/test/gtest.h"
philipel266f0a42016-11-28 08:49:07 -080049#include "webrtc/test/gmock.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000050#include "webrtc/test/null_transport.h"
asapersson@webrtc.org37c05592015-01-28 13:58:27 +000051#include "webrtc/test/rtcp_packet_parser.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000052#include "webrtc/test/rtp_rtcp_observer.h"
53#include "webrtc/test/testsupport/fileutils.h"
54#include "webrtc/test/testsupport/perf_test.h"
charujainbf6a45b2016-11-03 04:21:42 -070055#include "webrtc/video/transport_adapter.h"
pbos@webrtc.orgab990ae2014-09-17 09:02:25 +000056#include "webrtc/video_encoder.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000057
58namespace webrtc {
59
philipel266f0a42016-11-28 08:49:07 -080060namespace {
61const char new_jb_enabled[] = "WebRTC-NewVideoJitterBuffer/Enabled/";
62const char new_jb_disabled[] = "WebRTC-NewVideoJitterBuffer/Disabled/";
63} // anonymous namespace
64
Peter Boström5811a392015-12-10 13:02:50 +010065static const int kSilenceTimeoutMs = 2000;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000066
philipel266f0a42016-11-28 08:49:07 -080067class EndToEndTest : public test::CallTest,
68 public ::testing::WithParamInterface<std::string> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000069 public:
philipel266f0a42016-11-28 08:49:07 -080070 EndToEndTest() : scoped_field_trial_(GetParam()) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000071
72 virtual ~EndToEndTest() {
stefanff483612015-12-21 03:14:00 -080073 EXPECT_EQ(nullptr, video_send_stream_);
74 EXPECT_TRUE(video_receive_streams_.empty());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000075 }
76
77 protected:
pbos2d566682015-09-28 09:59:31 -070078 class UnusedTransport : public Transport {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000079 private:
stefan1d8a5062015-10-02 03:39:33 -070080 bool SendRtp(const uint8_t* packet,
81 size_t length,
82 const PacketOptions& options) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000083 ADD_FAILURE() << "Unexpected RTP sent.";
84 return false;
85 }
86
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000087 bool SendRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000088 ADD_FAILURE() << "Unexpected RTCP sent.";
89 return false;
90 }
91 };
92
skvlad7a43d252016-03-22 15:32:27 -070093 class RequiredTransport : public Transport {
94 public:
95 RequiredTransport(bool rtp_required, bool rtcp_required)
96 : need_rtp_(rtp_required), need_rtcp_(rtcp_required) {}
97 ~RequiredTransport() {
98 if (need_rtp_) {
99 ADD_FAILURE() << "Expected RTP packet not sent.";
100 }
101 if (need_rtcp_) {
102 ADD_FAILURE() << "Expected RTCP packet not sent.";
103 }
104 }
105
106 private:
107 bool SendRtp(const uint8_t* packet,
108 size_t length,
109 const PacketOptions& options) override {
Taylor Brandstetter14cf12b2016-08-22 18:14:14 -0700110 rtc::CritScope lock(&crit_);
skvlad7a43d252016-03-22 15:32:27 -0700111 need_rtp_ = false;
112 return true;
113 }
114
115 bool SendRtcp(const uint8_t* packet, size_t length) override {
Taylor Brandstetter14cf12b2016-08-22 18:14:14 -0700116 rtc::CritScope lock(&crit_);
skvlad7a43d252016-03-22 15:32:27 -0700117 need_rtcp_ = false;
118 return true;
119 }
120 bool need_rtp_;
121 bool need_rtcp_;
Taylor Brandstetter14cf12b2016-08-22 18:14:14 -0700122 rtc::CriticalSection crit_;
skvlad7a43d252016-03-22 15:32:27 -0700123 };
124
Peter Boström39593972016-02-15 11:27:15 +0100125 void DecodesRetransmittedFrame(bool enable_rtx, bool enable_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000126 void ReceivesPliAndRecovers(int rtp_history_ms);
pbosda903ea2015-10-02 02:36:56 -0700127 void RespectsRtcpMode(RtcpMode rtcp_mode);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000128 void TestSendsSetSsrcs(size_t num_ssrcs, bool send_single_ssrc_first);
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200129 void TestRtpStatePreservation(bool use_rtx, bool provoke_rtcpsr_before_rtp);
sprangb4a1ae52015-12-03 08:10:08 -0800130 void VerifyHistogramStats(bool use_rtx, bool use_red, bool screenshare);
skvlad7a43d252016-03-22 15:32:27 -0700131 void VerifyNewVideoSendStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -0800132 MediaType network_to_bring_up,
skvlad7a43d252016-03-22 15:32:27 -0700133 VideoEncoder* encoder,
134 Transport* transport);
135 void VerifyNewVideoReceiveStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -0800136 MediaType network_to_bring_up,
skvlad7a43d252016-03-22 15:32:27 -0700137 Transport* transport);
philipel266f0a42016-11-28 08:49:07 -0800138 test::ScopedFieldTrials scoped_field_trial_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000139};
140
philipel266f0a42016-11-28 08:49:07 -0800141INSTANTIATE_TEST_CASE_P(TestWithNewVideoJitterBuffer,
142 EndToEndTest,
143 ::testing::Values(new_jb_enabled, new_jb_disabled));
144
145TEST_P(EndToEndTest, ReceiverCanBeStartedTwice) {
skvlad11a9cbf2016-10-07 11:53:05 -0700146 CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000147
solenberg4fbae2b2015-08-28 04:07:10 -0700148 test::NullTransport transport;
brandtr841de6a2016-11-15 07:10:52 -0800149 CreateSendConfig(1, 0, 0, &transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700150 CreateMatchingReceiveConfigs(&transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000151
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100152 CreateVideoStreams();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000153
stefanff483612015-12-21 03:14:00 -0800154 video_receive_streams_[0]->Start();
155 video_receive_streams_[0]->Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000156
157 DestroyStreams();
158}
159
philipel266f0a42016-11-28 08:49:07 -0800160TEST_P(EndToEndTest, ReceiverCanBeStoppedTwice) {
skvlad11a9cbf2016-10-07 11:53:05 -0700161 CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000162
solenberg4fbae2b2015-08-28 04:07:10 -0700163 test::NullTransport transport;
brandtr841de6a2016-11-15 07:10:52 -0800164 CreateSendConfig(1, 0, 0, &transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700165 CreateMatchingReceiveConfigs(&transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000166
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100167 CreateVideoStreams();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000168
stefanff483612015-12-21 03:14:00 -0800169 video_receive_streams_[0]->Stop();
170 video_receive_streams_[0]->Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000171
172 DestroyStreams();
173}
174
philipel266f0a42016-11-28 08:49:07 -0800175TEST_P(EndToEndTest, ReceiverCanBeStoppedAndRestarted) {
sprang113bdca2016-10-11 03:10:10 -0700176 CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_));
177
178 test::NullTransport transport;
brandtr841de6a2016-11-15 07:10:52 -0800179 CreateSendConfig(1, 0, 0, &transport);
sprang113bdca2016-10-11 03:10:10 -0700180 CreateMatchingReceiveConfigs(&transport);
181
182 CreateVideoStreams();
183
184 video_receive_streams_[0]->Stop();
185 video_receive_streams_[0]->Start();
186 video_receive_streams_[0]->Stop();
187
188 DestroyStreams();
189}
190
philipel266f0a42016-11-28 08:49:07 -0800191TEST_P(EndToEndTest, RendersSingleDelayedFrame) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000192 static const int kWidth = 320;
193 static const int kHeight = 240;
194 // This constant is chosen to be higher than the timeout in the video_render
195 // module. This makes sure that frames aren't dropped if there are no other
196 // frames in the queue.
197 static const int kDelayRenderCallbackMs = 1000;
198
nisse7ade7b32016-03-23 04:48:10 -0700199 class Renderer : public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000200 public:
Peter Boström5811a392015-12-10 13:02:50 +0100201 Renderer() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000202
nisseeb83a1a2016-03-21 01:27:56 -0700203 void OnFrame(const VideoFrame& video_frame) override { event_.Set(); }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000204
Peter Boström5811a392015-12-10 13:02:50 +0100205 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000206
Peter Boström5811a392015-12-10 13:02:50 +0100207 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000208 } renderer;
209
210 class TestFrameCallback : public I420FrameCallback {
211 public:
Peter Boström5811a392015-12-10 13:02:50 +0100212 TestFrameCallback() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000213
Peter Boström5811a392015-12-10 13:02:50 +0100214 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000215
216 private:
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700217 void FrameCallback(VideoFrame* frame) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000218 SleepMs(kDelayRenderCallbackMs);
Peter Boström5811a392015-12-10 13:02:50 +0100219 event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000220 }
221
Peter Boström5811a392015-12-10 13:02:50 +0100222 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000223 };
224
skvlad11a9cbf2016-10-07 11:53:05 -0700225 CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_));
solenberg4fbae2b2015-08-28 04:07:10 -0700226
stefanf116bd02015-10-27 08:29:42 -0700227 test::DirectTransport sender_transport(sender_call_.get());
228 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000229 sender_transport.SetReceiver(receiver_call_->Receiver());
230 receiver_transport.SetReceiver(sender_call_->Receiver());
231
brandtr841de6a2016-11-15 07:10:52 -0800232 CreateSendConfig(1, 0, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700233 CreateMatchingReceiveConfigs(&receiver_transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000234
235 TestFrameCallback pre_render_callback;
stefanff483612015-12-21 03:14:00 -0800236 video_receive_configs_[0].pre_render_callback = &pre_render_callback;
237 video_receive_configs_[0].renderer = &renderer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000238
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100239 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000240 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000241
242 // Create frames that are smaller than the send width/height, this is done to
243 // check that the callbacks are done after processing video.
kwiberg27f982b2016-03-01 11:52:33 -0800244 std::unique_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +0000245 test::FrameGenerator::CreateChromaGenerator(kWidth, kHeight));
perkja49cbd32016-09-16 07:53:41 -0700246 test::FrameForwarder frame_forwarder;
perkj803d97f2016-11-01 11:45:46 -0700247 video_send_stream_->SetSource(
248 &frame_forwarder, VideoSendStream::DegradationPreference::kBalanced);
perkja49cbd32016-09-16 07:53:41 -0700249
250 frame_forwarder.IncomingCapturedFrame(*frame_generator->NextFrame());
Peter Boström5811a392015-12-10 13:02:50 +0100251 EXPECT_TRUE(pre_render_callback.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000252 << "Timed out while waiting for pre-render callback.";
Peter Boström5811a392015-12-10 13:02:50 +0100253 EXPECT_TRUE(renderer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000254 << "Timed out while waiting for the frame to render.";
255
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000256 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000257
258 sender_transport.StopSending();
259 receiver_transport.StopSending();
260
261 DestroyStreams();
262}
263
philipel266f0a42016-11-28 08:49:07 -0800264TEST_P(EndToEndTest, TransmitsFirstFrame) {
nisse7ade7b32016-03-23 04:48:10 -0700265 class Renderer : public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000266 public:
Peter Boström5811a392015-12-10 13:02:50 +0100267 Renderer() : event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000268
nisseeb83a1a2016-03-21 01:27:56 -0700269 void OnFrame(const VideoFrame& video_frame) override { event_.Set(); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000270
Peter Boström5811a392015-12-10 13:02:50 +0100271 bool Wait() { return event_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000272
Peter Boström5811a392015-12-10 13:02:50 +0100273 rtc::Event event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000274 } renderer;
275
skvlad11a9cbf2016-10-07 11:53:05 -0700276 CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_));
solenberg4fbae2b2015-08-28 04:07:10 -0700277
stefanf116bd02015-10-27 08:29:42 -0700278 test::DirectTransport sender_transport(sender_call_.get());
279 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000280 sender_transport.SetReceiver(receiver_call_->Receiver());
281 receiver_transport.SetReceiver(sender_call_->Receiver());
282
brandtr841de6a2016-11-15 07:10:52 -0800283 CreateSendConfig(1, 0, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -0700284 CreateMatchingReceiveConfigs(&receiver_transport);
stefanff483612015-12-21 03:14:00 -0800285 video_receive_configs_[0].renderer = &renderer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000286
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100287 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000288 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000289
kwiberg27f982b2016-03-01 11:52:33 -0800290 std::unique_ptr<test::FrameGenerator> frame_generator(
perkjfa10b552016-10-02 23:45:26 -0700291 test::FrameGenerator::CreateChromaGenerator(kDefaultWidth,
292 kDefaultHeight));
perkja49cbd32016-09-16 07:53:41 -0700293 test::FrameForwarder frame_forwarder;
perkj803d97f2016-11-01 11:45:46 -0700294 video_send_stream_->SetSource(
295 &frame_forwarder, VideoSendStream::DegradationPreference::kBalanced);
perkja49cbd32016-09-16 07:53:41 -0700296 frame_forwarder.IncomingCapturedFrame(*frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000297
Peter Boström5811a392015-12-10 13:02:50 +0100298 EXPECT_TRUE(renderer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000299 << "Timed out while waiting for the frame to render.";
300
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000301 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000302
303 sender_transport.StopSending();
304 receiver_transport.StopSending();
305
306 DestroyStreams();
307}
308
Perba7dc722016-04-19 15:01:23 +0200309class CodecObserver : public test::EndToEndTest,
nisse7ade7b32016-03-23 04:48:10 -0700310 public rtc::VideoSinkInterface<VideoFrame> {
Perba7dc722016-04-19 15:01:23 +0200311 public:
312 CodecObserver(int no_frames_to_wait_for,
313 VideoRotation rotation_to_test,
314 const std::string& payload_name,
315 webrtc::VideoEncoder* encoder,
316 webrtc::VideoDecoder* decoder)
hta9aa96882016-12-06 05:36:03 -0800317 : EndToEndTest(4 * webrtc::EndToEndTest::kDefaultTimeoutMs),
318 // TODO(hta): This timeout (120 seconds) is excessive.
319 // https://bugs.webrtc.org/6830
Perba7dc722016-04-19 15:01:23 +0200320 no_frames_to_wait_for_(no_frames_to_wait_for),
321 expected_rotation_(rotation_to_test),
322 payload_name_(payload_name),
323 encoder_(encoder),
324 decoder_(decoder),
325 frame_counter_(0) {}
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000326
Perba7dc722016-04-19 15:01:23 +0200327 void PerformTest() override {
328 EXPECT_TRUE(Wait())
329 << "Timed out while waiting for enough frames to be decoded.";
330 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000331
Perba7dc722016-04-19 15:01:23 +0200332 void ModifyVideoConfigs(
333 VideoSendStream::Config* send_config,
334 std::vector<VideoReceiveStream::Config>* receive_configs,
335 VideoEncoderConfig* encoder_config) override {
336 send_config->encoder_settings.encoder = encoder_.get();
337 send_config->encoder_settings.payload_name = payload_name_;
338 send_config->encoder_settings.payload_type = 126;
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000339
Perba7dc722016-04-19 15:01:23 +0200340 (*receive_configs)[0].renderer = this;
341 (*receive_configs)[0].decoders.resize(1);
342 (*receive_configs)[0].decoders[0].payload_type =
343 send_config->encoder_settings.payload_type;
344 (*receive_configs)[0].decoders[0].payload_name =
345 send_config->encoder_settings.payload_name;
346 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
347 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000348
Perba7dc722016-04-19 15:01:23 +0200349 void OnFrame(const VideoFrame& video_frame) override {
350 EXPECT_EQ(expected_rotation_, video_frame.rotation());
351 if (++frame_counter_ == no_frames_to_wait_for_)
352 observation_complete_.Set();
353 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000354
Perba7dc722016-04-19 15:01:23 +0200355 void OnFrameGeneratorCapturerCreated(
356 test::FrameGeneratorCapturer* frame_generator_capturer) override {
357 frame_generator_capturer->SetFakeRotation(expected_rotation_);
358 }
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000359
Perba7dc722016-04-19 15:01:23 +0200360 private:
361 int no_frames_to_wait_for_;
362 VideoRotation expected_rotation_;
363 std::string payload_name_;
364 std::unique_ptr<webrtc::VideoEncoder> encoder_;
365 std::unique_ptr<webrtc::VideoDecoder> decoder_;
366 int frame_counter_;
367};
368
philipel266f0a42016-11-28 08:49:07 -0800369TEST_P(EndToEndTest, SendsAndReceivesVP8) {
370 CodecObserver test(5, kVideoRotation_0, "VP8", VP8Encoder::Create(),
371 VP8Decoder::Create());
372 RunBaseTest(&test);
373}
374
375TEST_P(EndToEndTest, SendsAndReceivesVP8Rotation90) {
magjed509e4fe2016-11-18 01:34:11 -0800376 CodecObserver test(5, kVideoRotation_90, "VP8", VP8Encoder::Create(),
Perba7dc722016-04-19 15:01:23 +0200377 VP8Decoder::Create());
378 RunBaseTest(&test);
379}
380
Peter Boström12996152016-05-14 02:03:18 +0200381#if !defined(RTC_DISABLE_VP9)
philipel266f0a42016-11-28 08:49:07 -0800382TEST_P(EndToEndTest, SendsAndReceivesVP9) {
magjed509e4fe2016-11-18 01:34:11 -0800383 CodecObserver test(500, kVideoRotation_0, "VP9", VP9Encoder::Create(),
Perba7dc722016-04-19 15:01:23 +0200384 VP9Decoder::Create());
385 RunBaseTest(&test);
386}
387
philipel266f0a42016-11-28 08:49:07 -0800388TEST_P(EndToEndTest, SendsAndReceivesVP9VideoRotation90) {
magjed509e4fe2016-11-18 01:34:11 -0800389 CodecObserver test(5, kVideoRotation_90, "VP9", VP9Encoder::Create(),
Perba7dc722016-04-19 15:01:23 +0200390 VP9Decoder::Create());
stefane74eef12016-01-08 06:47:13 -0800391 RunBaseTest(&test);
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000392}
Peter Boström12996152016-05-14 02:03:18 +0200393#endif // !defined(RTC_DISABLE_VP9)
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000394
brandtr445fb8f2016-11-14 04:11:23 -0800395#if defined(WEBRTC_USE_H264)
philipel266f0a42016-11-28 08:49:07 -0800396TEST_P(EndToEndTest, SendsAndReceivesH264) {
magjedceecea42016-11-28 07:20:21 -0800397 CodecObserver test(500, kVideoRotation_0, "H264",
398 H264Encoder::Create(cricket::VideoCodec("H264")),
Perba7dc722016-04-19 15:01:23 +0200399 H264Decoder::Create());
400 RunBaseTest(&test);
401}
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000402
philipel266f0a42016-11-28 08:49:07 -0800403TEST_P(EndToEndTest, SendsAndReceivesH264VideoRotation90) {
magjedceecea42016-11-28 07:20:21 -0800404 CodecObserver test(5, kVideoRotation_90, "H264",
405 H264Encoder::Create(cricket::VideoCodec("H264")),
Perba7dc722016-04-19 15:01:23 +0200406 H264Decoder::Create());
stefane74eef12016-01-08 06:47:13 -0800407 RunBaseTest(&test);
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000408}
hta9aa96882016-12-06 05:36:03 -0800409
410TEST_P(EndToEndTest, SendsAndReceivesH264PacketizationMode0) {
411 cricket::VideoCodec codec = cricket::VideoCodec("H264");
412 codec.SetParam(cricket::kH264FmtpPacketizationMode, "0");
413 CodecObserver test(500, kVideoRotation_0, "H264", H264Encoder::Create(codec),
414 H264Decoder::Create());
415 RunBaseTest(&test);
416}
417
418TEST_P(EndToEndTest, SendsAndReceivesH264PacketizationMode1) {
419 cricket::VideoCodec codec = cricket::VideoCodec("H264");
420 codec.SetParam(cricket::kH264FmtpPacketizationMode, "1");
421 CodecObserver test(500, kVideoRotation_0, "H264", H264Encoder::Create(codec),
422 H264Decoder::Create());
423 RunBaseTest(&test);
424}
425
brandtr445fb8f2016-11-14 04:11:23 -0800426#endif // defined(WEBRTC_USE_H264)
hbosbab934b2016-01-27 01:36:03 -0800427
philipel266f0a42016-11-28 08:49:07 -0800428TEST_P(EndToEndTest, ReceiverUsesLocalSsrc) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000429 class SyncRtcpObserver : public test::EndToEndTest {
430 public:
431 SyncRtcpObserver() : EndToEndTest(kDefaultTimeoutMs) {}
432
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000433 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
danilchap3dc929e2016-11-02 08:21:59 -0700434 test::RtcpPacketParser parser;
435 EXPECT_TRUE(parser.Parse(packet, length));
436 EXPECT_EQ(kReceiverLocalVideoSsrc, parser.sender_ssrc());
Peter Boström5811a392015-12-10 13:02:50 +0100437 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000438
439 return SEND_PACKET;
440 }
441
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000442 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100443 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000444 << "Timed out while waiting for a receiver RTCP packet to be sent.";
445 }
446 } test;
447
stefane74eef12016-01-08 06:47:13 -0800448 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000449}
450
philipel266f0a42016-11-28 08:49:07 -0800451TEST_P(EndToEndTest, ReceivesAndRetransmitsNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000452 static const int kNumberOfNacksToObserve = 2;
453 static const int kLossBurstSize = 2;
454 static const int kPacketsBetweenLossBursts = 9;
455 class NackObserver : public test::EndToEndTest {
456 public:
457 NackObserver()
458 : EndToEndTest(kLongTimeoutMs),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000459 sent_rtp_packets_(0),
460 packets_left_to_drop_(0),
461 nacks_left_(kNumberOfNacksToObserve) {}
462
463 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000464 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700465 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000466 RTPHeader header;
Peter Boström03671cb2015-12-07 15:22:24 +0100467 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000468
469 // Never drop retransmitted packets.
470 if (dropped_packets_.find(header.sequenceNumber) !=
471 dropped_packets_.end()) {
472 retransmitted_packets_.insert(header.sequenceNumber);
Stefan Holmer586b19b2015-09-18 11:14:31 +0200473 if (nacks_left_ <= 0 &&
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000474 retransmitted_packets_.size() == dropped_packets_.size()) {
Peter Boström5811a392015-12-10 13:02:50 +0100475 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000476 }
477 return SEND_PACKET;
478 }
479
480 ++sent_rtp_packets_;
481
482 // Enough NACKs received, stop dropping packets.
Stefan Holmer586b19b2015-09-18 11:14:31 +0200483 if (nacks_left_ <= 0)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000484 return SEND_PACKET;
485
486 // Check if it's time for a new loss burst.
487 if (sent_rtp_packets_ % kPacketsBetweenLossBursts == 0)
488 packets_left_to_drop_ = kLossBurstSize;
489
Stefan Holmer01b48882015-05-05 10:21:24 +0200490 // Never drop padding packets as those won't be retransmitted.
491 if (packets_left_to_drop_ > 0 && header.paddingLength == 0) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000492 --packets_left_to_drop_;
493 dropped_packets_.insert(header.sequenceNumber);
494 return DROP_PACKET;
495 }
496
497 return SEND_PACKET;
498 }
499
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000500 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700501 rtc::CritScope lock(&crit_);
danilchap3dc929e2016-11-02 08:21:59 -0700502 test::RtcpPacketParser parser;
503 EXPECT_TRUE(parser.Parse(packet, length));
504 nacks_left_ -= parser.nack()->num_packets();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000505 return SEND_PACKET;
506 }
507
stefanff483612015-12-21 03:14:00 -0800508 void ModifyVideoConfigs(
509 VideoSendStream::Config* send_config,
510 std::vector<VideoReceiveStream::Config>* receive_configs,
511 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000512 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000513 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000514 }
515
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000516 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100517 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000518 << "Timed out waiting for packets to be NACKed, retransmitted and "
519 "rendered.";
520 }
521
stefanf116bd02015-10-27 08:29:42 -0700522 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000523 std::set<uint16_t> dropped_packets_;
524 std::set<uint16_t> retransmitted_packets_;
525 uint64_t sent_rtp_packets_;
526 int packets_left_to_drop_;
stefanf116bd02015-10-27 08:29:42 -0700527 int nacks_left_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000528 } test;
529
stefane74eef12016-01-08 06:47:13 -0800530 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000531}
532
philipel266f0a42016-11-28 08:49:07 -0800533TEST_P(EndToEndTest, ReceivesNackAndRetransmitsAudio) {
Erik Språng737336d2016-07-29 12:59:36 +0200534 class NackObserver : public test::EndToEndTest {
535 public:
536 NackObserver()
537 : EndToEndTest(kLongTimeoutMs),
538 local_ssrc_(0),
539 remote_ssrc_(0),
540 receive_transport_(nullptr) {}
541
542 private:
543 size_t GetNumVideoStreams() const override { return 0; }
544 size_t GetNumAudioStreams() const override { return 1; }
545
546 test::PacketTransport* CreateReceiveTransport() override {
547 test::PacketTransport* receive_transport = new test::PacketTransport(
548 nullptr, this, test::PacketTransport::kReceiver,
549 FakeNetworkPipe::Config());
550 receive_transport_ = receive_transport;
551 return receive_transport;
552 }
553
554 Action OnSendRtp(const uint8_t* packet, size_t length) override {
555 RTPHeader header;
556 EXPECT_TRUE(parser_->Parse(packet, length, &header));
557
558 if (!sequence_number_to_retransmit_) {
559 sequence_number_to_retransmit_ =
560 rtc::Optional<uint16_t>(header.sequenceNumber);
561
562 // Don't ask for retransmission straight away, may be deduped in pacer.
563 } else if (header.sequenceNumber == *sequence_number_to_retransmit_) {
564 observation_complete_.Set();
565 } else {
566 // Send a NACK as often as necessary until retransmission is received.
567 rtcp::Nack nack;
danilchap822a16f2016-09-27 09:27:47 -0700568 nack.SetSenderSsrc(local_ssrc_);
569 nack.SetMediaSsrc(remote_ssrc_);
Erik Språng737336d2016-07-29 12:59:36 +0200570 uint16_t nack_list[] = {*sequence_number_to_retransmit_};
danilchap822a16f2016-09-27 09:27:47 -0700571 nack.SetPacketIds(nack_list, 1);
Erik Språng737336d2016-07-29 12:59:36 +0200572 rtc::Buffer buffer = nack.Build();
573
574 EXPECT_TRUE(receive_transport_->SendRtcp(buffer.data(), buffer.size()));
575 }
576
577 return SEND_PACKET;
578 }
579
580 void ModifyAudioConfigs(
581 AudioSendStream::Config* send_config,
582 std::vector<AudioReceiveStream::Config>* receive_configs) override {
583 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
584 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
585 local_ssrc_ = (*receive_configs)[0].rtp.local_ssrc;
586 remote_ssrc_ = (*receive_configs)[0].rtp.remote_ssrc;
587 }
588
589 void PerformTest() override {
590 EXPECT_TRUE(Wait())
591 << "Timed out waiting for packets to be NACKed, retransmitted and "
592 "rendered.";
593 }
594
595 uint32_t local_ssrc_;
596 uint32_t remote_ssrc_;
597 Transport* receive_transport_;
598 rtc::Optional<uint16_t> sequence_number_to_retransmit_;
599 } test;
600
601 RunBaseTest(&test);
602}
603
philipel266f0a42016-11-28 08:49:07 -0800604TEST_P(EndToEndTest, CanReceiveUlpfec) {
brandtr535830e2016-10-31 03:45:58 -0700605 class UlpfecRenderObserver : public test::EndToEndTest,
606 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000607 public:
brandtr535830e2016-10-31 03:45:58 -0700608 UlpfecRenderObserver()
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000609 : EndToEndTest(kDefaultTimeoutMs), state_(kFirstPacket) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000610
611 private:
stefanf116bd02015-10-27 08:29:42 -0700612 Action OnSendRtp(const uint8_t* packet, size_t length) override {
613 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000614 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000615 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000616
Stefan Holmer01b48882015-05-05 10:21:24 +0200617 int encapsulated_payload_type = -1;
618 if (header.payloadType == kRedPayloadType) {
619 encapsulated_payload_type =
620 static_cast<int>(packet[header.headerLength]);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100621 if (encapsulated_payload_type != kFakeVideoSendPayloadType)
Stefan Holmer01b48882015-05-05 10:21:24 +0200622 EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
623 } else {
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100624 EXPECT_EQ(kFakeVideoSendPayloadType, header.payloadType);
Stefan Holmer01b48882015-05-05 10:21:24 +0200625 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000626
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000627 if (protected_sequence_numbers_.count(header.sequenceNumber) != 0) {
628 // Retransmitted packet, should not count.
629 protected_sequence_numbers_.erase(header.sequenceNumber);
philipel266f0a42016-11-28 08:49:07 -0800630 auto ts_it = protected_timestamps_.find(header.timestamp);
631 EXPECT_NE(ts_it, protected_timestamps_.end());
632 protected_timestamps_.erase(ts_it);
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000633 return SEND_PACKET;
634 }
635
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000636 switch (state_) {
637 case kFirstPacket:
brandtr535830e2016-10-31 03:45:58 -0700638 state_ = kDropEveryOtherPacketUntilUlpfec;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000639 break;
brandtr535830e2016-10-31 03:45:58 -0700640 case kDropEveryOtherPacketUntilUlpfec:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000641 if (encapsulated_payload_type == kUlpfecPayloadType) {
642 state_ = kDropNextMediaPacket;
643 return SEND_PACKET;
644 }
645 if (header.sequenceNumber % 2 == 0)
646 return DROP_PACKET;
647 break;
648 case kDropNextMediaPacket:
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100649 if (encapsulated_payload_type == kFakeVideoSendPayloadType) {
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000650 protected_sequence_numbers_.insert(header.sequenceNumber);
651 protected_timestamps_.insert(header.timestamp);
brandtr535830e2016-10-31 03:45:58 -0700652 state_ = kDropEveryOtherPacketUntilUlpfec;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000653 return DROP_PACKET;
654 }
655 break;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000656 }
657
658 return SEND_PACKET;
659 }
660
nisseeb83a1a2016-03-21 01:27:56 -0700661 void OnFrame(const VideoFrame& video_frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200662 rtc::CritScope lock(&crit_);
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000663 // Rendering frame with timestamp of packet that was dropped -> FEC
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000664 // protection worked.
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000665 if (protected_timestamps_.count(video_frame.timestamp()) != 0)
Peter Boström5811a392015-12-10 13:02:50 +0100666 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000667 }
668
669 enum {
670 kFirstPacket,
brandtr535830e2016-10-31 03:45:58 -0700671 kDropEveryOtherPacketUntilUlpfec,
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000672 kDropNextMediaPacket,
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000673 } state_;
674
stefanff483612015-12-21 03:14:00 -0800675 void ModifyVideoConfigs(
676 VideoSendStream::Config* send_config,
677 std::vector<VideoReceiveStream::Config>* receive_configs,
678 VideoEncoderConfig* encoder_config) override {
brandtr535830e2016-10-31 03:45:58 -0700679 // TODO(pbos): Run this test with combined NACK/ULPFEC enabled as well.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000680 // int rtp_history_ms = 1000;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000681 // (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000682 // send_config->rtp.nack.rtp_history_ms = rtp_history_ms;
brandtrb5f2c3f2016-10-04 23:28:39 -0700683 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
684 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000685
brandtrb5f2c3f2016-10-04 23:28:39 -0700686 (*receive_configs)[0].rtp.ulpfec.red_payload_type = kRedPayloadType;
687 (*receive_configs)[0].rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000688 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000689 }
690
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000691 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100692 EXPECT_TRUE(Wait())
brandtr1e3dfbf2016-11-16 22:45:19 -0800693 << "Timed out waiting for dropped frames to be rendered.";
694 }
695
696 rtc::CriticalSection crit_;
697 std::set<uint32_t> protected_sequence_numbers_ GUARDED_BY(crit_);
philipel266f0a42016-11-28 08:49:07 -0800698 // Since several packets can have the same timestamp a multiset is used
699 // instead of a set.
700 std::multiset<uint32_t> protected_timestamps_ GUARDED_BY(crit_);
brandtr1e3dfbf2016-11-16 22:45:19 -0800701 } test;
702
703 RunBaseTest(&test);
704}
705
philipel266f0a42016-11-28 08:49:07 -0800706TEST_P(EndToEndTest, CanReceiveFlexfec) {
brandtr1e3dfbf2016-11-16 22:45:19 -0800707 class FlexfecRenderObserver : public test::EndToEndTest,
708 public rtc::VideoSinkInterface<VideoFrame> {
709 public:
710 FlexfecRenderObserver()
711 : EndToEndTest(kDefaultTimeoutMs), state_(kFirstPacket) {}
712
713 size_t GetNumFlexfecStreams() const override { return 1; }
714
715 private:
716 Action OnSendRtp(const uint8_t* packet, size_t length) override {
717 rtc::CritScope lock(&crit_);
718 RTPHeader header;
719 EXPECT_TRUE(parser_->Parse(packet, length, &header));
720
721 uint8_t payload_type = header.payloadType;
722 if (payload_type != kFakeVideoSendPayloadType) {
723 EXPECT_EQ(kFlexfecPayloadType, payload_type);
724 }
725
726 auto seq_num_it = protected_sequence_numbers_.find(header.sequenceNumber);
727 if (seq_num_it != protected_sequence_numbers_.end()) {
728 // Retransmitted packet, should not count.
729 protected_sequence_numbers_.erase(seq_num_it);
730 auto ts_it = protected_timestamps_.find(header.timestamp);
731 EXPECT_NE(ts_it, protected_timestamps_.end());
732 protected_timestamps_.erase(ts_it);
733 return SEND_PACKET;
734 }
735
736 switch (state_) {
737 case kFirstPacket:
738 state_ = kDropEveryOtherPacketUntilFlexfec;
739 break;
740 case kDropEveryOtherPacketUntilFlexfec:
741 if (payload_type == kFlexfecPayloadType) {
742 state_ = kDropNextMediaPacket;
743 return SEND_PACKET;
744 }
745 if (header.sequenceNumber % 2 == 0)
746 return DROP_PACKET;
747 break;
748 case kDropNextMediaPacket:
749 if (payload_type == kFakeVideoSendPayloadType) {
750 protected_sequence_numbers_.insert(header.sequenceNumber);
751 protected_timestamps_.insert(header.timestamp);
752 state_ = kDropEveryOtherPacketUntilFlexfec;
753 return DROP_PACKET;
754 }
755 break;
756 }
757
758 return SEND_PACKET;
759 }
760
761 void OnFrame(const VideoFrame& video_frame) override {
762 rtc::CritScope lock(&crit_);
763 // Rendering frame with timestamp of packet that was dropped -> FEC
764 // protection worked.
765 auto it = protected_timestamps_.find(video_frame.timestamp());
766 if (it != protected_timestamps_.end())
767 observation_complete_.Set();
768 }
769
770 enum {
771 kFirstPacket,
772 kDropEveryOtherPacketUntilFlexfec,
773 kDropNextMediaPacket,
774 } state_;
775
776 void ModifyVideoConfigs(
777 VideoSendStream::Config* send_config,
778 std::vector<VideoReceiveStream::Config>* receive_configs,
779 VideoEncoderConfig* encoder_config) override {
780 (*receive_configs)[0].renderer = this;
781 }
782
783 void PerformTest() override {
784 EXPECT_TRUE(Wait())
785 << "Timed out waiting for dropped frames to be rendered.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000786 }
787
stefanf116bd02015-10-27 08:29:42 -0700788 rtc::CriticalSection crit_;
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000789 std::set<uint32_t> protected_sequence_numbers_ GUARDED_BY(crit_);
philipel266f0a42016-11-28 08:49:07 -0800790 // Since several packets can have the same timestamp a multiset is used
791 // instead of a set.
792 std::multiset<uint32_t> protected_timestamps_ GUARDED_BY(crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000793 } test;
794
stefane74eef12016-01-08 06:47:13 -0800795 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000796}
797
philipel266f0a42016-11-28 08:49:07 -0800798TEST_P(EndToEndTest, ReceivedUlpfecPacketsNotNacked) {
brandtr535830e2016-10-31 03:45:58 -0700799 class UlpfecNackObserver : public test::EndToEndTest {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000800 public:
brandtr535830e2016-10-31 03:45:58 -0700801 UlpfecNackObserver()
stefanf116bd02015-10-27 08:29:42 -0700802 : EndToEndTest(kDefaultTimeoutMs),
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000803 state_(kFirstPacket),
brandtr535830e2016-10-31 03:45:58 -0700804 ulpfec_sequence_number_(0),
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000805 has_last_sequence_number_(false),
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200806 last_sequence_number_(0),
magjed509e4fe2016-11-18 01:34:11 -0800807 encoder_(VP8Encoder::Create()),
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200808 decoder_(VP8Decoder::Create()) {}
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000809
810 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000811 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -0800812 rtc::CritScope lock_(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000813 RTPHeader header;
814 EXPECT_TRUE(parser_->Parse(packet, length, &header));
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000815
Stefan Holmer01b48882015-05-05 10:21:24 +0200816 int encapsulated_payload_type = -1;
817 if (header.payloadType == kRedPayloadType) {
818 encapsulated_payload_type =
819 static_cast<int>(packet[header.headerLength]);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100820 if (encapsulated_payload_type != kFakeVideoSendPayloadType)
Stefan Holmer01b48882015-05-05 10:21:24 +0200821 EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
822 } else {
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100823 EXPECT_EQ(kFakeVideoSendPayloadType, header.payloadType);
Stefan Holmer01b48882015-05-05 10:21:24 +0200824 }
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000825
826 if (has_last_sequence_number_ &&
827 !IsNewerSequenceNumber(header.sequenceNumber,
828 last_sequence_number_)) {
829 // Drop retransmitted packets.
830 return DROP_PACKET;
831 }
832 last_sequence_number_ = header.sequenceNumber;
833 has_last_sequence_number_ = true;
834
brandtr535830e2016-10-31 03:45:58 -0700835 bool ulpfec_packet = encapsulated_payload_type == kUlpfecPayloadType;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000836 switch (state_) {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000837 case kFirstPacket:
brandtr535830e2016-10-31 03:45:58 -0700838 state_ = kDropEveryOtherPacketUntilUlpfec;
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000839 break;
brandtr535830e2016-10-31 03:45:58 -0700840 case kDropEveryOtherPacketUntilUlpfec:
841 if (ulpfec_packet) {
842 state_ = kDropAllMediaPacketsUntilUlpfec;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000843 } else if (header.sequenceNumber % 2 == 0) {
844 return DROP_PACKET;
845 }
846 break;
brandtr535830e2016-10-31 03:45:58 -0700847 case kDropAllMediaPacketsUntilUlpfec:
848 if (!ulpfec_packet)
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000849 return DROP_PACKET;
brandtr535830e2016-10-31 03:45:58 -0700850 ulpfec_sequence_number_ = header.sequenceNumber;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200851 state_ = kDropOneMediaPacket;
852 break;
853 case kDropOneMediaPacket:
brandtr535830e2016-10-31 03:45:58 -0700854 if (ulpfec_packet)
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200855 return DROP_PACKET;
856 state_ = kPassOneMediaPacket;
857 return DROP_PACKET;
858 break;
859 case kPassOneMediaPacket:
brandtr535830e2016-10-31 03:45:58 -0700860 if (ulpfec_packet)
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200861 return DROP_PACKET;
862 // Pass one media packet after dropped packet after last FEC,
863 // otherwise receiver might never see a seq_no after
brandtr535830e2016-10-31 03:45:58 -0700864 // |ulpfec_sequence_number_|
865 state_ = kVerifyUlpfecPacketNotInNackList;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000866 break;
brandtr535830e2016-10-31 03:45:58 -0700867 case kVerifyUlpfecPacketNotInNackList:
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000868 // Continue to drop packets. Make sure no frame can be decoded.
brandtr535830e2016-10-31 03:45:58 -0700869 if (ulpfec_packet || header.sequenceNumber % 2 == 0)
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000870 return DROP_PACKET;
871 break;
872 }
873 return SEND_PACKET;
874 }
875
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000876 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -0800877 rtc::CritScope lock_(&crit_);
brandtr535830e2016-10-31 03:45:58 -0700878 if (state_ == kVerifyUlpfecPacketNotInNackList) {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000879 test::RtcpPacketParser rtcp_parser;
880 rtcp_parser.Parse(packet, length);
Danil Chapovalovba6f7be2016-09-02 18:29:10 +0200881 const std::vector<uint16_t>& nacks = rtcp_parser.nack()->packet_ids();
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200882 EXPECT_TRUE(std::find(nacks.begin(), nacks.end(),
brandtr535830e2016-10-31 03:45:58 -0700883 ulpfec_sequence_number_) == nacks.end())
884 << "Got nack for ULPFEC packet";
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000885 if (!nacks.empty() &&
brandtr535830e2016-10-31 03:45:58 -0700886 IsNewerSequenceNumber(nacks.back(), ulpfec_sequence_number_)) {
Peter Boström5811a392015-12-10 13:02:50 +0100887 observation_complete_.Set();
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000888 }
889 }
890 return SEND_PACKET;
891 }
892
stefane74eef12016-01-08 06:47:13 -0800893 test::PacketTransport* CreateSendTransport(Call* sender_call) override {
894 // At low RTT (< kLowRttNackMs) -> NACK only, no FEC.
895 // Configure some network delay.
896 const int kNetworkDelayMs = 50;
897 FakeNetworkPipe::Config config;
898 config.queue_delay_ms = kNetworkDelayMs;
899 return new test::PacketTransport(sender_call, this,
900 test::PacketTransport::kSender, config);
901 }
902
Stefan Holmere5904162015-03-26 11:11:06 +0100903 // TODO(holmer): Investigate why we don't send FEC packets when the bitrate
904 // is 10 kbps.
905 Call::Config GetSenderCallConfig() override {
skvlad11a9cbf2016-10-07 11:53:05 -0700906 Call::Config config(&event_log_);
Stefan Holmere5904162015-03-26 11:11:06 +0100907 const int kMinBitrateBps = 30000;
908 config.bitrate_config.min_bitrate_bps = kMinBitrateBps;
909 return config;
910 }
911
stefanff483612015-12-21 03:14:00 -0800912 void ModifyVideoConfigs(
913 VideoSendStream::Config* send_config,
914 std::vector<VideoReceiveStream::Config>* receive_configs,
915 VideoEncoderConfig* encoder_config) override {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000916 // Configure hybrid NACK/FEC.
917 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
brandtrb5f2c3f2016-10-04 23:28:39 -0700918 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
919 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200920 // Set codec to VP8, otherwise NACK/FEC hybrid will be disabled.
921 send_config->encoder_settings.encoder = encoder_.get();
922 send_config->encoder_settings.payload_name = "VP8";
923 send_config->encoder_settings.payload_type = kFakeVideoSendPayloadType;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200924
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000925 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
brandtrb5f2c3f2016-10-04 23:28:39 -0700926 (*receive_configs)[0].rtp.ulpfec.red_payload_type = kRedPayloadType;
927 (*receive_configs)[0].rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200928
929 (*receive_configs)[0].decoders.resize(1);
930 (*receive_configs)[0].decoders[0].payload_type =
931 send_config->encoder_settings.payload_type;
932 (*receive_configs)[0].decoders[0].payload_name =
933 send_config->encoder_settings.payload_name;
934 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
asapersson@webrtc.org37c05592015-01-28 13:58:27 +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())
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000939 << "Timed out while waiting for FEC packets to be received.";
940 }
941
942 enum {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000943 kFirstPacket,
brandtr535830e2016-10-31 03:45:58 -0700944 kDropEveryOtherPacketUntilUlpfec,
945 kDropAllMediaPacketsUntilUlpfec,
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200946 kDropOneMediaPacket,
947 kPassOneMediaPacket,
brandtr535830e2016-10-31 03:45:58 -0700948 kVerifyUlpfecPacketNotInNackList,
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000949 } state_;
950
stefan608213e2015-11-01 14:56:10 -0800951 rtc::CriticalSection crit_;
brandtr535830e2016-10-31 03:45:58 -0700952 uint16_t ulpfec_sequence_number_ GUARDED_BY(&crit_);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000953 bool has_last_sequence_number_;
954 uint16_t last_sequence_number_;
Danil Chapovalov895a2d22016-05-27 14:12:09 +0200955 std::unique_ptr<webrtc::VideoEncoder> encoder_;
956 std::unique_ptr<webrtc::VideoDecoder> decoder_;
stefanf116bd02015-10-27 08:29:42 -0700957 } test;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000958
stefane74eef12016-01-08 06:47:13 -0800959 RunBaseTest(&test);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000960}
961
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000962// This test drops second RTP packet with a marker bit set, makes sure it's
963// retransmitted and renders. Retransmission SSRCs are also checked.
Peter Boström39593972016-02-15 11:27:15 +0100964void EndToEndTest::DecodesRetransmittedFrame(bool enable_rtx, bool enable_red) {
Peter Boström67680c12016-02-17 11:10:04 +0100965 static const int kDroppedFrameNumber = 10;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000966 class RetransmissionObserver : public test::EndToEndTest,
967 public I420FrameCallback {
968 public:
Peter Boström39593972016-02-15 11:27:15 +0100969 RetransmissionObserver(bool enable_rtx, bool enable_red)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000970 : EndToEndTest(kDefaultTimeoutMs),
Peter Boström39593972016-02-15 11:27:15 +0100971 payload_type_(GetPayloadType(false, enable_red)),
972 retransmission_ssrc_(enable_rtx ? kSendRtxSsrcs[0]
973 : kVideoSendSsrcs[0]),
974 retransmission_payload_type_(GetPayloadType(enable_rtx, enable_red)),
magjed509e4fe2016-11-18 01:34:11 -0800975 encoder_(VP8Encoder::Create()),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000976 marker_bits_observed_(0),
danilchap192717e2016-07-25 08:20:51 -0700977 retransmitted_timestamp_(0) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000978
979 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000980 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -0700981 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000982 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000983 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000984
Peter Boström67680c12016-02-17 11:10:04 +0100985 // Ignore padding-only packets over RTX.
986 if (header.payloadType != payload_type_) {
987 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
988 if (length == header.headerLength + header.paddingLength)
989 return SEND_PACKET;
Stefan Holmer586b19b2015-09-18 11:14:31 +0200990 }
Peter Boström67680c12016-02-17 11:10:04 +0100991
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000992 if (header.timestamp == retransmitted_timestamp_) {
993 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
994 EXPECT_EQ(retransmission_payload_type_, header.payloadType);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000995 return SEND_PACKET;
996 }
997
Stefan Holmer586b19b2015-09-18 11:14:31 +0200998 // Found the final packet of the frame to inflict loss to, drop this and
999 // expect a retransmission.
danilchapfdd381c2016-07-25 04:03:20 -07001000 if (header.payloadType == payload_type_ && header.markerBit &&
1001 ++marker_bits_observed_ == kDroppedFrameNumber) {
Danil Chapovalov18c65a42016-06-29 15:29:34 +02001002 // This should be the only dropped packet.
1003 EXPECT_EQ(0u, retransmitted_timestamp_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001004 retransmitted_timestamp_ = header.timestamp;
danilchap192717e2016-07-25 08:20:51 -07001005 if (std::find(rendered_timestamps_.begin(), rendered_timestamps_.end(),
1006 retransmitted_timestamp_) != rendered_timestamps_.end()) {
1007 // Frame was rendered before last packet was scheduled for sending.
1008 // This is extremly rare but possible scenario because prober able to
1009 // resend packet before it was send.
1010 // TODO(danilchap): Remove this corner case when prober would not be
1011 // able to sneak in between packet saved to history for resending and
1012 // pacer notified about existance of that packet for sending.
1013 // See https://bugs.chromium.org/p/webrtc/issues/detail?id=5540 for
1014 // details.
1015 observation_complete_.Set();
1016 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001017 return DROP_PACKET;
1018 }
1019
1020 return SEND_PACKET;
1021 }
1022
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001023 void FrameCallback(VideoFrame* frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02001024 rtc::CritScope lock(&crit_);
danilchap192717e2016-07-25 08:20:51 -07001025 if (frame->timestamp() == retransmitted_timestamp_)
Peter Boström5811a392015-12-10 13:02:50 +01001026 observation_complete_.Set();
danilchap192717e2016-07-25 08:20:51 -07001027 rendered_timestamps_.push_back(frame->timestamp());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001028 }
1029
stefanff483612015-12-21 03:14:00 -08001030 void ModifyVideoConfigs(
1031 VideoSendStream::Config* send_config,
1032 std::vector<VideoReceiveStream::Config>* receive_configs,
1033 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001034 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001035 (*receive_configs)[0].pre_render_callback = this;
1036 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
Shao Changbine62202f2015-04-21 20:24:50 +08001037
1038 if (payload_type_ == kRedPayloadType) {
brandtrb5f2c3f2016-10-04 23:28:39 -07001039 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
1040 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
Stefan Holmer10880012016-02-03 13:29:59 +01001041 if (retransmission_ssrc_ == kSendRtxSsrcs[0])
brandtrb5f2c3f2016-10-04 23:28:39 -07001042 send_config->rtp.ulpfec.red_rtx_payload_type = kRtxRedPayloadType;
1043 (*receive_configs)[0].rtp.ulpfec.ulpfec_payload_type =
1044 send_config->rtp.ulpfec.ulpfec_payload_type;
1045 (*receive_configs)[0].rtp.ulpfec.red_payload_type =
1046 send_config->rtp.ulpfec.red_payload_type;
1047 (*receive_configs)[0].rtp.ulpfec.red_rtx_payload_type =
1048 send_config->rtp.ulpfec.red_rtx_payload_type;
Shao Changbine62202f2015-04-21 20:24:50 +08001049 }
1050
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001051 if (retransmission_ssrc_ == kSendRtxSsrcs[0]) {
1052 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001053 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
Stefan Holmer10880012016-02-03 13:29:59 +01001054 (*receive_configs)[0].rtp.rtx[payload_type_].ssrc = kSendRtxSsrcs[0];
1055 (*receive_configs)[0].rtp.rtx[payload_type_].payload_type =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001056 kSendRtxPayloadType;
1057 }
Peter Boström39593972016-02-15 11:27:15 +01001058 // Configure encoding and decoding with VP8, since generic packetization
1059 // doesn't support FEC with NACK.
kwibergaf476c72016-11-28 15:21:39 -08001060 RTC_DCHECK_EQ(1, (*receive_configs)[0].decoders.size());
Peter Boström39593972016-02-15 11:27:15 +01001061 send_config->encoder_settings.encoder = encoder_.get();
1062 send_config->encoder_settings.payload_name = "VP8";
1063 (*receive_configs)[0].decoders[0].payload_name = "VP8";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001064 }
1065
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001066 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001067 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001068 << "Timed out while waiting for retransmission to render.";
1069 }
1070
Shao Changbine62202f2015-04-21 20:24:50 +08001071 int GetPayloadType(bool use_rtx, bool use_red) {
Stefan Holmer10880012016-02-03 13:29:59 +01001072 if (use_red) {
1073 if (use_rtx)
1074 return kRtxRedPayloadType;
1075 return kRedPayloadType;
1076 }
1077 if (use_rtx)
1078 return kSendRtxPayloadType;
1079 return kFakeVideoSendPayloadType;
Shao Changbine62202f2015-04-21 20:24:50 +08001080 }
1081
stefanf116bd02015-10-27 08:29:42 -07001082 rtc::CriticalSection crit_;
Shao Changbine62202f2015-04-21 20:24:50 +08001083 const int payload_type_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001084 const uint32_t retransmission_ssrc_;
1085 const int retransmission_payload_type_;
kwiberg27f982b2016-03-01 11:52:33 -08001086 std::unique_ptr<VideoEncoder> encoder_;
Peter Boström39593972016-02-15 11:27:15 +01001087 const std::string payload_name_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001088 int marker_bits_observed_;
stefanf116bd02015-10-27 08:29:42 -07001089 uint32_t retransmitted_timestamp_ GUARDED_BY(&crit_);
danilchap192717e2016-07-25 08:20:51 -07001090 std::vector<uint32_t> rendered_timestamps_ GUARDED_BY(&crit_);
Peter Boström39593972016-02-15 11:27:15 +01001091 } test(enable_rtx, enable_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001092
stefane74eef12016-01-08 06:47:13 -08001093 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001094}
1095
philipel266f0a42016-11-28 08:49:07 -08001096TEST_P(EndToEndTest, DecodesRetransmittedFrame) {
Shao Changbine62202f2015-04-21 20:24:50 +08001097 DecodesRetransmittedFrame(false, false);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001098}
1099
philipel266f0a42016-11-28 08:49:07 -08001100TEST_P(EndToEndTest, DecodesRetransmittedFrameOverRtx) {
Shao Changbine62202f2015-04-21 20:24:50 +08001101 DecodesRetransmittedFrame(true, false);
1102}
1103
philipel266f0a42016-11-28 08:49:07 -08001104TEST_P(EndToEndTest, DecodesRetransmittedFrameByRed) {
Shao Changbine62202f2015-04-21 20:24:50 +08001105 DecodesRetransmittedFrame(false, true);
1106}
1107
philipel266f0a42016-11-28 08:49:07 -08001108TEST_P(EndToEndTest, DecodesRetransmittedFrameByRedOverRtx) {
Shao Changbine62202f2015-04-21 20:24:50 +08001109 DecodesRetransmittedFrame(true, true);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001110}
1111
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001112void EndToEndTest::ReceivesPliAndRecovers(int rtp_history_ms) {
1113 static const int kPacketsToDrop = 1;
1114
nisse7ade7b32016-03-23 04:48:10 -07001115 class PliObserver : public test::EndToEndTest,
1116 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001117 public:
1118 explicit PliObserver(int rtp_history_ms)
1119 : EndToEndTest(kLongTimeoutMs),
1120 rtp_history_ms_(rtp_history_ms),
1121 nack_enabled_(rtp_history_ms > 0),
1122 highest_dropped_timestamp_(0),
1123 frames_to_drop_(0),
1124 received_pli_(false) {}
1125
1126 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001127 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -07001128 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001129 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001130 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001131
1132 // Drop all retransmitted packets to force a PLI.
1133 if (header.timestamp <= highest_dropped_timestamp_)
1134 return DROP_PACKET;
1135
1136 if (frames_to_drop_ > 0) {
1137 highest_dropped_timestamp_ = header.timestamp;
1138 --frames_to_drop_;
1139 return DROP_PACKET;
1140 }
1141
1142 return SEND_PACKET;
1143 }
1144
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001145 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefanf116bd02015-10-27 08:29:42 -07001146 rtc::CritScope lock(&crit_);
danilchap3dc929e2016-11-02 08:21:59 -07001147 test::RtcpPacketParser parser;
1148 EXPECT_TRUE(parser.Parse(packet, length));
1149 if (!nack_enabled_)
1150 EXPECT_EQ(0, parser.nack()->num_packets());
1151 if (parser.pli()->num_packets() > 0)
1152 received_pli_ = true;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001153 return SEND_PACKET;
1154 }
1155
nisseeb83a1a2016-03-21 01:27:56 -07001156 void OnFrame(const VideoFrame& video_frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02001157 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001158 if (received_pli_ &&
1159 video_frame.timestamp() > highest_dropped_timestamp_) {
Peter Boström5811a392015-12-10 13:02:50 +01001160 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001161 }
1162 if (!received_pli_)
1163 frames_to_drop_ = kPacketsToDrop;
1164 }
1165
stefanff483612015-12-21 03:14:00 -08001166 void ModifyVideoConfigs(
1167 VideoSendStream::Config* send_config,
1168 std::vector<VideoReceiveStream::Config>* receive_configs,
1169 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001170 send_config->rtp.nack.rtp_history_ms = rtp_history_ms_;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001171 (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms_;
1172 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001173 }
1174
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001175 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001176 EXPECT_TRUE(Wait()) << "Timed out waiting for PLI to be "
1177 "received and a frame to be "
1178 "rendered afterwards.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001179 }
1180
stefanf116bd02015-10-27 08:29:42 -07001181 rtc::CriticalSection crit_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001182 int rtp_history_ms_;
1183 bool nack_enabled_;
stefanf116bd02015-10-27 08:29:42 -07001184 uint32_t highest_dropped_timestamp_ GUARDED_BY(&crit_);
1185 int frames_to_drop_ GUARDED_BY(&crit_);
1186 bool received_pli_ GUARDED_BY(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001187 } test(rtp_history_ms);
1188
stefane74eef12016-01-08 06:47:13 -08001189 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001190}
1191
philipel266f0a42016-11-28 08:49:07 -08001192TEST_P(EndToEndTest, ReceivesPliAndRecoversWithNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001193 ReceivesPliAndRecovers(1000);
1194}
1195
philipel266f0a42016-11-28 08:49:07 -08001196TEST_P(EndToEndTest, ReceivesPliAndRecoversWithoutNack) {
1197 // This test makes no sense for the new video jitter buffer.
1198 if (GetParam() == new_jb_enabled)
1199 return;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001200 ReceivesPliAndRecovers(0);
1201}
1202
philipel266f0a42016-11-28 08:49:07 -08001203TEST_P(EndToEndTest, UnknownRtpPacketGivesUnknownSsrcReturnCode) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001204 class PacketInputObserver : public PacketReceiver {
1205 public:
1206 explicit PacketInputObserver(PacketReceiver* receiver)
Peter Boström5811a392015-12-10 13:02:50 +01001207 : receiver_(receiver), delivered_packet_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001208
Peter Boström5811a392015-12-10 13:02:50 +01001209 bool Wait() { return delivered_packet_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001210
1211 private:
stefan68786d22015-09-08 05:36:15 -07001212 DeliveryStatus DeliverPacket(MediaType media_type,
1213 const uint8_t* packet,
1214 size_t length,
1215 const PacketTime& packet_time) override {
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001216 if (RtpHeaderParser::IsRtcp(packet, length)) {
stefan68786d22015-09-08 05:36:15 -07001217 return receiver_->DeliverPacket(media_type, packet, length,
1218 packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001219 } else {
1220 DeliveryStatus delivery_status =
stefan68786d22015-09-08 05:36:15 -07001221 receiver_->DeliverPacket(media_type, packet, length, packet_time);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001222 EXPECT_EQ(DELIVERY_UNKNOWN_SSRC, delivery_status);
Peter Boström5811a392015-12-10 13:02:50 +01001223 delivered_packet_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001224 return delivery_status;
1225 }
1226 }
1227
1228 PacketReceiver* receiver_;
Peter Boström5811a392015-12-10 13:02:50 +01001229 rtc::Event delivered_packet_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001230 };
1231
skvlad11a9cbf2016-10-07 11:53:05 -07001232 CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_));
solenberg4fbae2b2015-08-28 04:07:10 -07001233
stefanf116bd02015-10-27 08:29:42 -07001234 test::DirectTransport send_transport(sender_call_.get());
1235 test::DirectTransport receive_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001236 PacketInputObserver input_observer(receiver_call_->Receiver());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001237 send_transport.SetReceiver(&input_observer);
1238 receive_transport.SetReceiver(sender_call_->Receiver());
1239
brandtr841de6a2016-11-15 07:10:52 -08001240 CreateSendConfig(1, 0, 0, &send_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07001241 CreateMatchingReceiveConfigs(&receive_transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001242
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001243 CreateVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07001244 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
1245 kDefaultHeight);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001246 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001247
stefanff483612015-12-21 03:14:00 -08001248 receiver_call_->DestroyVideoReceiveStream(video_receive_streams_[0]);
1249 video_receive_streams_.clear();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001250
1251 // Wait() waits for a received packet.
Peter Boström5811a392015-12-10 13:02:50 +01001252 EXPECT_TRUE(input_observer.Wait());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001253
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001254 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001255
1256 DestroyStreams();
1257
1258 send_transport.StopSending();
1259 receive_transport.StopSending();
1260}
1261
pbosda903ea2015-10-02 02:36:56 -07001262void EndToEndTest::RespectsRtcpMode(RtcpMode rtcp_mode) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001263 static const int kNumCompoundRtcpPacketsToObserve = 10;
1264 class RtcpModeObserver : public test::EndToEndTest {
1265 public:
pbosda903ea2015-10-02 02:36:56 -07001266 explicit RtcpModeObserver(RtcpMode rtcp_mode)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001267 : EndToEndTest(kDefaultTimeoutMs),
1268 rtcp_mode_(rtcp_mode),
1269 sent_rtp_(0),
1270 sent_rtcp_(0) {}
1271
1272 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001273 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001274 if (++sent_rtp_ % 3 == 0)
1275 return DROP_PACKET;
1276
1277 return SEND_PACKET;
1278 }
1279
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001280 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001281 ++sent_rtcp_;
danilchap3dc929e2016-11-02 08:21:59 -07001282 test::RtcpPacketParser parser;
1283 EXPECT_TRUE(parser.Parse(packet, length));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001284
danilchap3dc929e2016-11-02 08:21:59 -07001285 EXPECT_EQ(0, parser.sender_report()->num_packets());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001286
1287 switch (rtcp_mode_) {
pbosda903ea2015-10-02 02:36:56 -07001288 case RtcpMode::kCompound:
danilchap3dc929e2016-11-02 08:21:59 -07001289 if (parser.receiver_report()->num_packets() == 0) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001290 ADD_FAILURE() << "Received RTCP packet without receiver report for "
pbosda903ea2015-10-02 02:36:56 -07001291 "RtcpMode::kCompound.";
Peter Boström5811a392015-12-10 13:02:50 +01001292 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001293 }
1294
1295 if (sent_rtcp_ >= kNumCompoundRtcpPacketsToObserve)
Peter Boström5811a392015-12-10 13:02:50 +01001296 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001297
1298 break;
pbosda903ea2015-10-02 02:36:56 -07001299 case RtcpMode::kReducedSize:
danilchap3dc929e2016-11-02 08:21:59 -07001300 if (parser.receiver_report()->num_packets() == 0)
Peter Boström5811a392015-12-10 13:02:50 +01001301 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001302 break;
pbosda903ea2015-10-02 02:36:56 -07001303 case RtcpMode::kOff:
1304 RTC_NOTREACHED();
1305 break;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001306 }
1307
1308 return SEND_PACKET;
1309 }
1310
stefanff483612015-12-21 03:14:00 -08001311 void ModifyVideoConfigs(
1312 VideoSendStream::Config* send_config,
1313 std::vector<VideoReceiveStream::Config>* receive_configs,
1314 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001315 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001316 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
1317 (*receive_configs)[0].rtp.rtcp_mode = rtcp_mode_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001318 }
1319
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001320 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001321 EXPECT_TRUE(Wait())
pbosda903ea2015-10-02 02:36:56 -07001322 << (rtcp_mode_ == RtcpMode::kCompound
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001323 ? "Timed out before observing enough compound packets."
1324 : "Timed out before receiving a non-compound RTCP packet.");
1325 }
1326
pbosda903ea2015-10-02 02:36:56 -07001327 RtcpMode rtcp_mode_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001328 int sent_rtp_;
1329 int sent_rtcp_;
1330 } test(rtcp_mode);
1331
stefane74eef12016-01-08 06:47:13 -08001332 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001333}
1334
philipel266f0a42016-11-28 08:49:07 -08001335TEST_P(EndToEndTest, UsesRtcpCompoundMode) {
pbosda903ea2015-10-02 02:36:56 -07001336 RespectsRtcpMode(RtcpMode::kCompound);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001337}
1338
philipel266f0a42016-11-28 08:49:07 -08001339TEST_P(EndToEndTest, UsesRtcpReducedSizeMode) {
pbosda903ea2015-10-02 02:36:56 -07001340 RespectsRtcpMode(RtcpMode::kReducedSize);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001341}
1342
1343// Test sets up a Call multiple senders with different resolutions and SSRCs.
1344// Another is set up to receive all three of these with different renderers.
sprang867fb522015-08-03 04:38:41 -07001345class MultiStreamTest {
1346 public:
1347 static const size_t kNumStreams = 3;
1348 struct CodecSettings {
1349 uint32_t ssrc;
1350 int width;
1351 int height;
1352 } codec_settings[kNumStreams];
1353
1354 MultiStreamTest() {
1355 // TODO(sprang): Cleanup when msvc supports explicit initializers for array.
1356 codec_settings[0] = {1, 640, 480};
1357 codec_settings[1] = {2, 320, 240};
1358 codec_settings[2] = {3, 240, 160};
1359 }
1360
1361 virtual ~MultiStreamTest() {}
1362
1363 void RunTest() {
skvlad11a9cbf2016-10-07 11:53:05 -07001364 webrtc::RtcEventLogNullImpl event_log;
1365 Call::Config config(&event_log);
1366 std::unique_ptr<Call> sender_call(Call::Create(config));
1367 std::unique_ptr<Call> receiver_call(Call::Create(config));
kwiberg27f982b2016-03-01 11:52:33 -08001368 std::unique_ptr<test::DirectTransport> sender_transport(
stefanf116bd02015-10-27 08:29:42 -07001369 CreateSendTransport(sender_call.get()));
kwiberg27f982b2016-03-01 11:52:33 -08001370 std::unique_ptr<test::DirectTransport> receiver_transport(
stefanf116bd02015-10-27 08:29:42 -07001371 CreateReceiveTransport(receiver_call.get()));
sprang867fb522015-08-03 04:38:41 -07001372 sender_transport->SetReceiver(receiver_call->Receiver());
1373 receiver_transport->SetReceiver(sender_call->Receiver());
1374
kwiberg27f982b2016-03-01 11:52:33 -08001375 std::unique_ptr<VideoEncoder> encoders[kNumStreams];
sprang867fb522015-08-03 04:38:41 -07001376 for (size_t i = 0; i < kNumStreams; ++i)
magjed509e4fe2016-11-18 01:34:11 -08001377 encoders[i].reset(VP8Encoder::Create());
sprang867fb522015-08-03 04:38:41 -07001378
1379 VideoSendStream* send_streams[kNumStreams];
1380 VideoReceiveStream* receive_streams[kNumStreams];
1381
1382 test::FrameGeneratorCapturer* frame_generators[kNumStreams];
kwiberg4a206a92016-03-31 10:24:26 -07001383 std::vector<std::unique_ptr<VideoDecoder>> allocated_decoders;
sprang867fb522015-08-03 04:38:41 -07001384 for (size_t i = 0; i < kNumStreams; ++i) {
1385 uint32_t ssrc = codec_settings[i].ssrc;
1386 int width = codec_settings[i].width;
1387 int height = codec_settings[i].height;
1388
solenberg4fbae2b2015-08-28 04:07:10 -07001389 VideoSendStream::Config send_config(sender_transport.get());
sprang867fb522015-08-03 04:38:41 -07001390 send_config.rtp.ssrcs.push_back(ssrc);
1391 send_config.encoder_settings.encoder = encoders[i].get();
1392 send_config.encoder_settings.payload_name = "VP8";
1393 send_config.encoder_settings.payload_type = 124;
1394 VideoEncoderConfig encoder_config;
perkjfa10b552016-10-02 23:45:26 -07001395 test::FillEncoderConfiguration(1, &encoder_config);
1396 encoder_config.max_bitrate_bps = 100000;
sprang867fb522015-08-03 04:38:41 -07001397
1398 UpdateSendConfig(i, &send_config, &encoder_config, &frame_generators[i]);
1399
perkj26091b12016-09-01 01:17:40 -07001400 send_streams[i] = sender_call->CreateVideoSendStream(
1401 send_config.Copy(), encoder_config.Copy());
sprang867fb522015-08-03 04:38:41 -07001402 send_streams[i]->Start();
1403
solenberg4fbae2b2015-08-28 04:07:10 -07001404 VideoReceiveStream::Config receive_config(receiver_transport.get());
sprang867fb522015-08-03 04:38:41 -07001405 receive_config.rtp.remote_ssrc = ssrc;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001406 receive_config.rtp.local_ssrc = test::CallTest::kReceiverLocalVideoSsrc;
sprang867fb522015-08-03 04:38:41 -07001407 VideoReceiveStream::Decoder decoder =
1408 test::CreateMatchingDecoder(send_config.encoder_settings);
kwiberg4a206a92016-03-31 10:24:26 -07001409 allocated_decoders.push_back(
1410 std::unique_ptr<VideoDecoder>(decoder.decoder));
sprang867fb522015-08-03 04:38:41 -07001411 receive_config.decoders.push_back(decoder);
1412
1413 UpdateReceiveConfig(i, &receive_config);
1414
1415 receive_streams[i] =
Tommi733b5472016-06-10 17:58:01 +02001416 receiver_call->CreateVideoReceiveStream(std::move(receive_config));
sprang867fb522015-08-03 04:38:41 -07001417 receive_streams[i]->Start();
1418
1419 frame_generators[i] = test::FrameGeneratorCapturer::Create(
perkja49cbd32016-09-16 07:53:41 -07001420 width, height, 30, Clock::GetRealTimeClock());
perkj803d97f2016-11-01 11:45:46 -07001421 send_streams[i]->SetSource(
1422 frame_generators[i],
1423 VideoSendStream::DegradationPreference::kBalanced);
sprang867fb522015-08-03 04:38:41 -07001424 frame_generators[i]->Start();
1425 }
1426
1427 Wait();
1428
1429 for (size_t i = 0; i < kNumStreams; ++i) {
1430 frame_generators[i]->Stop();
1431 sender_call->DestroyVideoSendStream(send_streams[i]);
1432 receiver_call->DestroyVideoReceiveStream(receive_streams[i]);
1433 delete frame_generators[i];
1434 }
1435
1436 sender_transport->StopSending();
1437 receiver_transport->StopSending();
1438 }
1439
1440 protected:
1441 virtual void Wait() = 0;
1442 // Note: frame_generator is a point-to-pointer, since the actual instance
1443 // hasn't been created at the time of this call. Only when packets/frames
1444 // start flowing should this be dereferenced.
1445 virtual void UpdateSendConfig(
1446 size_t stream_index,
1447 VideoSendStream::Config* send_config,
1448 VideoEncoderConfig* encoder_config,
1449 test::FrameGeneratorCapturer** frame_generator) {}
1450 virtual void UpdateReceiveConfig(size_t stream_index,
1451 VideoReceiveStream::Config* receive_config) {
1452 }
stefanf116bd02015-10-27 08:29:42 -07001453 virtual test::DirectTransport* CreateSendTransport(Call* sender_call) {
1454 return new test::DirectTransport(sender_call);
sprang867fb522015-08-03 04:38:41 -07001455 }
stefanf116bd02015-10-27 08:29:42 -07001456 virtual test::DirectTransport* CreateReceiveTransport(Call* receiver_call) {
1457 return new test::DirectTransport(receiver_call);
sprang867fb522015-08-03 04:38:41 -07001458 }
1459};
1460
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001461// Each renderer verifies that it receives the expected resolution, and as soon
1462// as every renderer has received a frame, the test finishes.
philipel266f0a42016-11-28 08:49:07 -08001463TEST_P(EndToEndTest, SendsAndReceivesMultipleStreams) {
nisse7ade7b32016-03-23 04:48:10 -07001464 class VideoOutputObserver : public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001465 public:
sprang867fb522015-08-03 04:38:41 -07001466 VideoOutputObserver(const MultiStreamTest::CodecSettings& settings,
1467 uint32_t ssrc,
1468 test::FrameGeneratorCapturer** frame_generator)
1469 : settings_(settings),
1470 ssrc_(ssrc),
1471 frame_generator_(frame_generator),
Peter Boström5811a392015-12-10 13:02:50 +01001472 done_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001473
nisseeb83a1a2016-03-21 01:27:56 -07001474 void OnFrame(const VideoFrame& video_frame) override {
sprang867fb522015-08-03 04:38:41 -07001475 EXPECT_EQ(settings_.width, video_frame.width());
1476 EXPECT_EQ(settings_.height, video_frame.height());
1477 (*frame_generator_)->Stop();
Peter Boström5811a392015-12-10 13:02:50 +01001478 done_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001479 }
1480
sprang867fb522015-08-03 04:38:41 -07001481 uint32_t Ssrc() { return ssrc_; }
1482
Peter Boström5811a392015-12-10 13:02:50 +01001483 bool Wait() { return done_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001484
1485 private:
sprang867fb522015-08-03 04:38:41 -07001486 const MultiStreamTest::CodecSettings& settings_;
1487 const uint32_t ssrc_;
1488 test::FrameGeneratorCapturer** const frame_generator_;
Peter Boström5811a392015-12-10 13:02:50 +01001489 rtc::Event done_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001490 };
1491
sprang867fb522015-08-03 04:38:41 -07001492 class Tester : public MultiStreamTest {
1493 public:
1494 Tester() {}
1495 virtual ~Tester() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001496
sprang867fb522015-08-03 04:38:41 -07001497 protected:
1498 void Wait() override {
1499 for (const auto& observer : observers_) {
Peter Boström5811a392015-12-10 13:02:50 +01001500 EXPECT_TRUE(observer->Wait()) << "Time out waiting for from on ssrc "
1501 << observer->Ssrc();
sprang867fb522015-08-03 04:38:41 -07001502 }
1503 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001504
sprang867fb522015-08-03 04:38:41 -07001505 void UpdateSendConfig(
1506 size_t stream_index,
1507 VideoSendStream::Config* send_config,
1508 VideoEncoderConfig* encoder_config,
1509 test::FrameGeneratorCapturer** frame_generator) override {
1510 observers_[stream_index].reset(new VideoOutputObserver(
1511 codec_settings[stream_index], send_config->rtp.ssrcs.front(),
1512 frame_generator));
1513 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001514
sprang867fb522015-08-03 04:38:41 -07001515 void UpdateReceiveConfig(
1516 size_t stream_index,
1517 VideoReceiveStream::Config* receive_config) override {
1518 receive_config->renderer = observers_[stream_index].get();
1519 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001520
sprang867fb522015-08-03 04:38:41 -07001521 private:
kwiberg27f982b2016-03-01 11:52:33 -08001522 std::unique_ptr<VideoOutputObserver> observers_[kNumStreams];
sprang867fb522015-08-03 04:38:41 -07001523 } tester;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001524
sprang867fb522015-08-03 04:38:41 -07001525 tester.RunTest();
1526}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001527
philipel266f0a42016-11-28 08:49:07 -08001528TEST_P(EndToEndTest, AssignsTransportSequenceNumbers) {
sprang867fb522015-08-03 04:38:41 -07001529 static const int kExtensionId = 5;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001530
sprang867fb522015-08-03 04:38:41 -07001531 class RtpExtensionHeaderObserver : public test::DirectTransport {
1532 public:
stefanf116bd02015-10-27 08:29:42 -07001533 RtpExtensionHeaderObserver(Call* sender_call,
1534 const uint32_t& first_media_ssrc,
sprang861c55e2015-10-16 10:01:21 -07001535 const std::map<uint32_t, uint32_t>& ssrc_map)
stefanf116bd02015-10-27 08:29:42 -07001536 : DirectTransport(sender_call),
Peter Boström5811a392015-12-10 13:02:50 +01001537 done_(false, false),
sprang867fb522015-08-03 04:38:41 -07001538 parser_(RtpHeaderParser::Create()),
sprang861c55e2015-10-16 10:01:21 -07001539 first_media_ssrc_(first_media_ssrc),
1540 rtx_to_media_ssrcs_(ssrc_map),
sprang867fb522015-08-03 04:38:41 -07001541 padding_observed_(false),
sprang861c55e2015-10-16 10:01:21 -07001542 rtx_padding_observed_(false),
1543 retransmit_observed_(false),
1544 started_(false) {
sprang867fb522015-08-03 04:38:41 -07001545 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
1546 kExtensionId);
1547 }
1548 virtual ~RtpExtensionHeaderObserver() {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001549
stefan1d8a5062015-10-02 03:39:33 -07001550 bool SendRtp(const uint8_t* data,
1551 size_t length,
1552 const PacketOptions& options) override {
sprang861c55e2015-10-16 10:01:21 -07001553 {
1554 rtc::CritScope cs(&lock_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001555
Erik Språng8d629712015-08-04 16:24:03 +02001556 if (IsDone())
sprang861c55e2015-10-16 10:01:21 -07001557 return false;
1558
1559 if (started_) {
1560 RTPHeader header;
1561 EXPECT_TRUE(parser_->Parse(data, length, &header));
1562 bool drop_packet = false;
1563
1564 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
1565 EXPECT_EQ(options.packet_id,
1566 header.extension.transportSequenceNumber);
1567 if (!streams_observed_.empty()) {
1568 // Unwrap packet id and verify uniqueness.
1569 int64_t packet_id = unwrapper_.Unwrap(options.packet_id);
1570 EXPECT_TRUE(received_packed_ids_.insert(packet_id).second);
1571 }
1572
1573 // Drop (up to) every 17th packet, so we get retransmits.
1574 // Only drop media, and not on the first stream (otherwise it will be
1575 // hard to distinguish from padding, which is always sent on the first
1576 // stream).
1577 if (header.payloadType != kSendRtxPayloadType &&
1578 header.ssrc != first_media_ssrc_ &&
1579 header.extension.transportSequenceNumber % 17 == 0) {
1580 dropped_seq_[header.ssrc].insert(header.sequenceNumber);
1581 drop_packet = true;
1582 }
1583
1584 size_t payload_length =
1585 length - (header.headerLength + header.paddingLength);
1586 if (payload_length == 0) {
1587 padding_observed_ = true;
1588 } else if (header.payloadType == kSendRtxPayloadType) {
1589 uint16_t original_sequence_number =
1590 ByteReader<uint16_t>::ReadBigEndian(&data[header.headerLength]);
1591 uint32_t original_ssrc =
1592 rtx_to_media_ssrcs_.find(header.ssrc)->second;
1593 std::set<uint16_t>* seq_no_map = &dropped_seq_[original_ssrc];
1594 auto it = seq_no_map->find(original_sequence_number);
1595 if (it != seq_no_map->end()) {
1596 retransmit_observed_ = true;
1597 seq_no_map->erase(it);
1598 } else {
1599 rtx_padding_observed_ = true;
1600 }
1601 } else {
1602 streams_observed_.insert(header.ssrc);
1603 }
1604
1605 if (IsDone())
Peter Boström5811a392015-12-10 13:02:50 +01001606 done_.Set();
sprang861c55e2015-10-16 10:01:21 -07001607
1608 if (drop_packet)
1609 return true;
1610 }
sprang867fb522015-08-03 04:38:41 -07001611 }
sprang861c55e2015-10-16 10:01:21 -07001612
stefan1d8a5062015-10-02 03:39:33 -07001613 return test::DirectTransport::SendRtp(data, length, options);
sprang867fb522015-08-03 04:38:41 -07001614 }
1615
Erik Språng8d629712015-08-04 16:24:03 +02001616 bool IsDone() {
sprang861c55e2015-10-16 10:01:21 -07001617 bool observed_types_ok =
1618 streams_observed_.size() == MultiStreamTest::kNumStreams &&
1619 padding_observed_ && retransmit_observed_ && rtx_padding_observed_;
1620 if (!observed_types_ok)
1621 return false;
1622 // We should not have any gaps in the sequence number range.
1623 size_t seqno_range =
1624 *received_packed_ids_.rbegin() - *received_packed_ids_.begin() + 1;
1625 return seqno_range == received_packed_ids_.size();
Erik Språng8d629712015-08-04 16:24:03 +02001626 }
1627
Peter Boström5811a392015-12-10 13:02:50 +01001628 bool Wait() {
sprang861c55e2015-10-16 10:01:21 -07001629 {
1630 // Can't be sure until this point that rtx_to_media_ssrcs_ etc have
1631 // been initialized and are OK to read.
1632 rtc::CritScope cs(&lock_);
1633 started_ = true;
1634 }
Peter Boström5811a392015-12-10 13:02:50 +01001635 return done_.Wait(kDefaultTimeoutMs);
sprang861c55e2015-10-16 10:01:21 -07001636 }
sprang867fb522015-08-03 04:38:41 -07001637
sprang861c55e2015-10-16 10:01:21 -07001638 rtc::CriticalSection lock_;
Peter Boström5811a392015-12-10 13:02:50 +01001639 rtc::Event done_;
kwiberg27f982b2016-03-01 11:52:33 -08001640 std::unique_ptr<RtpHeaderParser> parser_;
sprang861c55e2015-10-16 10:01:21 -07001641 SequenceNumberUnwrapper unwrapper_;
1642 std::set<int64_t> received_packed_ids_;
sprang867fb522015-08-03 04:38:41 -07001643 std::set<uint32_t> streams_observed_;
sprang861c55e2015-10-16 10:01:21 -07001644 std::map<uint32_t, std::set<uint16_t>> dropped_seq_;
1645 const uint32_t& first_media_ssrc_;
1646 const std::map<uint32_t, uint32_t>& rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001647 bool padding_observed_;
1648 bool rtx_padding_observed_;
sprang861c55e2015-10-16 10:01:21 -07001649 bool retransmit_observed_;
1650 bool started_;
sprang867fb522015-08-03 04:38:41 -07001651 };
1652
1653 class TransportSequenceNumberTester : public MultiStreamTest {
1654 public:
sprang861c55e2015-10-16 10:01:21 -07001655 TransportSequenceNumberTester()
1656 : first_media_ssrc_(0), observer_(nullptr) {}
sprang867fb522015-08-03 04:38:41 -07001657 virtual ~TransportSequenceNumberTester() {}
1658
1659 protected:
1660 void Wait() override {
Peter Boström74f6e9e2016-04-04 17:56:10 +02001661 RTC_DCHECK(observer_);
Peter Boström5811a392015-12-10 13:02:50 +01001662 EXPECT_TRUE(observer_->Wait());
sprang867fb522015-08-03 04:38:41 -07001663 }
1664
1665 void UpdateSendConfig(
1666 size_t stream_index,
1667 VideoSendStream::Config* send_config,
1668 VideoEncoderConfig* encoder_config,
1669 test::FrameGeneratorCapturer** frame_generator) override {
1670 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07001671 send_config->rtp.extensions.push_back(RtpExtension(
1672 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
sprang867fb522015-08-03 04:38:41 -07001673
1674 // Force some padding to be sent.
1675 const int kPaddingBitrateBps = 50000;
perkjfa10b552016-10-02 23:45:26 -07001676 encoder_config->max_bitrate_bps = 1000000;
sprang867fb522015-08-03 04:38:41 -07001677 encoder_config->min_transmit_bitrate_bps =
perkjfa10b552016-10-02 23:45:26 -07001678 encoder_config->max_bitrate_bps + kPaddingBitrateBps;
sprang867fb522015-08-03 04:38:41 -07001679
1680 // Configure RTX for redundant payload padding.
1681 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang861c55e2015-10-16 10:01:21 -07001682 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[stream_index]);
sprang867fb522015-08-03 04:38:41 -07001683 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
sprang861c55e2015-10-16 10:01:21 -07001684 rtx_to_media_ssrcs_[kSendRtxSsrcs[stream_index]] =
1685 send_config->rtp.ssrcs[0];
1686
1687 if (stream_index == 0)
1688 first_media_ssrc_ = send_config->rtp.ssrcs[0];
sprang867fb522015-08-03 04:38:41 -07001689 }
1690
1691 void UpdateReceiveConfig(
1692 size_t stream_index,
1693 VideoReceiveStream::Config* receive_config) override {
sprang861c55e2015-10-16 10:01:21 -07001694 receive_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sprang867fb522015-08-03 04:38:41 -07001695 receive_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07001696 receive_config->rtp.extensions.push_back(RtpExtension(
1697 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
sakal55d932b2016-09-30 06:19:08 -07001698 receive_config->renderer = &fake_renderer_;
sprang867fb522015-08-03 04:38:41 -07001699 }
1700
stefanf116bd02015-10-27 08:29:42 -07001701 test::DirectTransport* CreateSendTransport(Call* sender_call) override {
1702 observer_ = new RtpExtensionHeaderObserver(sender_call, first_media_ssrc_,
sprang861c55e2015-10-16 10:01:21 -07001703 rtx_to_media_ssrcs_);
sprang867fb522015-08-03 04:38:41 -07001704 return observer_;
1705 }
1706
1707 private:
sakal55d932b2016-09-30 06:19:08 -07001708 test::FakeVideoRenderer fake_renderer_;
sprang861c55e2015-10-16 10:01:21 -07001709 uint32_t first_media_ssrc_;
1710 std::map<uint32_t, uint32_t> rtx_to_media_ssrcs_;
sprang867fb522015-08-03 04:38:41 -07001711 RtpExtensionHeaderObserver* observer_;
1712 } tester;
1713
1714 tester.RunTest();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001715}
1716
Stefan Holmer04cb7632016-01-14 20:34:30 +01001717class TransportFeedbackTester : public test::EndToEndTest {
1718 public:
1719 explicit TransportFeedbackTester(bool feedback_enabled,
1720 size_t num_video_streams,
1721 size_t num_audio_streams)
1722 : EndToEndTest(::webrtc::EndToEndTest::kDefaultTimeoutMs),
1723 feedback_enabled_(feedback_enabled),
1724 num_video_streams_(num_video_streams),
sprangcd349d92016-07-13 09:11:28 -07001725 num_audio_streams_(num_audio_streams),
1726 receiver_call_(nullptr) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001727 // Only one stream of each supported for now.
1728 EXPECT_LE(num_video_streams, 1u);
1729 EXPECT_LE(num_audio_streams, 1u);
1730 }
1731
1732 protected:
1733 Action OnSendRtcp(const uint8_t* data, size_t length) override {
1734 EXPECT_FALSE(HasTransportFeedback(data, length));
1735 return SEND_PACKET;
1736 }
1737
1738 Action OnReceiveRtcp(const uint8_t* data, size_t length) override {
1739 if (HasTransportFeedback(data, length))
1740 observation_complete_.Set();
1741 return SEND_PACKET;
1742 }
1743
1744 bool HasTransportFeedback(const uint8_t* data, size_t length) const {
danilchap3dc929e2016-11-02 08:21:59 -07001745 test::RtcpPacketParser parser;
1746 EXPECT_TRUE(parser.Parse(data, length));
1747 return parser.transport_feedback()->num_packets() > 0;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001748 }
1749
1750 void PerformTest() override {
1751 const int64_t kDisabledFeedbackTimeoutMs = 5000;
1752 EXPECT_EQ(feedback_enabled_,
1753 observation_complete_.Wait(feedback_enabled_
1754 ? test::CallTest::kDefaultTimeoutMs
1755 : kDisabledFeedbackTimeoutMs));
1756 }
1757
1758 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
1759 receiver_call_ = receiver_call;
1760 }
1761
1762 size_t GetNumVideoStreams() const override { return num_video_streams_; }
1763 size_t GetNumAudioStreams() const override { return num_audio_streams_; }
1764
1765 void ModifyVideoConfigs(
1766 VideoSendStream::Config* send_config,
1767 std::vector<VideoReceiveStream::Config>* receive_configs,
1768 VideoEncoderConfig* encoder_config) override {
1769 send_config->rtp.extensions.clear();
1770 send_config->rtp.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001771 RtpExtension(RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer04cb7632016-01-14 20:34:30 +01001772 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1773 (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
1774 }
1775
1776 void ModifyAudioConfigs(
1777 AudioSendStream::Config* send_config,
1778 std::vector<AudioReceiveStream::Config>* receive_configs) override {
1779 send_config->rtp.extensions.clear();
1780 send_config->rtp.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001781 RtpExtension(RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer04cb7632016-01-14 20:34:30 +01001782 (*receive_configs)[0].rtp.extensions.clear();
1783 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1784 (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001785 }
1786
1787 private:
Erik Språng6b8d3552015-09-24 15:06:57 +02001788 static const int kExtensionId = 5;
Stefan Holmer04cb7632016-01-14 20:34:30 +01001789 const bool feedback_enabled_;
1790 const size_t num_video_streams_;
1791 const size_t num_audio_streams_;
1792 Call* receiver_call_;
1793};
Erik Språng6b8d3552015-09-24 15:06:57 +02001794
philipel266f0a42016-11-28 08:49:07 -08001795TEST_P(EndToEndTest, VideoReceivesTransportFeedback) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001796 TransportFeedbackTester test(true, 1, 0);
1797 RunBaseTest(&test);
Erik Språng6b8d3552015-09-24 15:06:57 +02001798}
stefan43edf0f2015-11-20 18:05:48 -08001799
philipel266f0a42016-11-28 08:49:07 -08001800TEST_P(EndToEndTest, VideoTransportFeedbackNotConfigured) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001801 TransportFeedbackTester test(false, 1, 0);
1802 RunBaseTest(&test);
stefan43edf0f2015-11-20 18:05:48 -08001803}
1804
philipel266f0a42016-11-28 08:49:07 -08001805TEST_P(EndToEndTest, AudioReceivesTransportFeedback) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001806 TransportFeedbackTester test(true, 0, 1);
1807 RunBaseTest(&test);
1808}
1809
philipel266f0a42016-11-28 08:49:07 -08001810TEST_P(EndToEndTest, AudioTransportFeedbackNotConfigured) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001811 TransportFeedbackTester test(false, 0, 1);
1812 RunBaseTest(&test);
1813}
1814
philipel266f0a42016-11-28 08:49:07 -08001815TEST_P(EndToEndTest, AudioVideoReceivesTransportFeedback) {
Stefan Holmer04cb7632016-01-14 20:34:30 +01001816 TransportFeedbackTester test(true, 1, 1);
1817 RunBaseTest(&test);
stefan43edf0f2015-11-20 18:05:48 -08001818}
1819
philipel266f0a42016-11-28 08:49:07 -08001820TEST_P(EndToEndTest, ObserversEncodedFrames) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001821 class EncodedFrameTestObserver : public EncodedFrameObserver {
1822 public:
1823 EncodedFrameTestObserver()
Peter Boström5811a392015-12-10 13:02:50 +01001824 : length_(0), frame_type_(kEmptyFrame), called_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001825 virtual ~EncodedFrameTestObserver() {}
1826
1827 virtual void EncodedFrameCallback(const EncodedFrame& encoded_frame) {
1828 frame_type_ = encoded_frame.frame_type_;
1829 length_ = encoded_frame.length_;
1830 buffer_.reset(new uint8_t[length_]);
1831 memcpy(buffer_.get(), encoded_frame.data_, length_);
Peter Boström5811a392015-12-10 13:02:50 +01001832 called_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001833 }
1834
Peter Boström5811a392015-12-10 13:02:50 +01001835 bool Wait() { return called_.Wait(kDefaultTimeoutMs); }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001836
1837 void ExpectEqualFrames(const EncodedFrameTestObserver& observer) {
1838 ASSERT_EQ(length_, observer.length_)
1839 << "Observed frames are of different lengths.";
1840 EXPECT_EQ(frame_type_, observer.frame_type_)
1841 << "Observed frames have different frame types.";
1842 EXPECT_EQ(0, memcmp(buffer_.get(), observer.buffer_.get(), length_))
1843 << "Observed encoded frames have different content.";
1844 }
1845
1846 private:
kwiberg27f982b2016-03-01 11:52:33 -08001847 std::unique_ptr<uint8_t[]> buffer_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001848 size_t length_;
1849 FrameType frame_type_;
Peter Boström5811a392015-12-10 13:02:50 +01001850 rtc::Event called_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001851 };
1852
1853 EncodedFrameTestObserver post_encode_observer;
1854 EncodedFrameTestObserver pre_decode_observer;
1855
skvlad11a9cbf2016-10-07 11:53:05 -07001856 CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_));
solenberg4fbae2b2015-08-28 04:07:10 -07001857
stefanf116bd02015-10-27 08:29:42 -07001858 test::DirectTransport sender_transport(sender_call_.get());
1859 test::DirectTransport receiver_transport(receiver_call_.get());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001860 sender_transport.SetReceiver(receiver_call_->Receiver());
1861 receiver_transport.SetReceiver(sender_call_->Receiver());
1862
brandtr841de6a2016-11-15 07:10:52 -08001863 CreateSendConfig(1, 0, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07001864 CreateMatchingReceiveConfigs(&receiver_transport);
stefanff483612015-12-21 03:14:00 -08001865 video_send_config_.post_encode_callback = &post_encode_observer;
1866 video_receive_configs_[0].pre_decode_callback = &pre_decode_observer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001867
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001868 CreateVideoStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001869 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001870
kwiberg27f982b2016-03-01 11:52:33 -08001871 std::unique_ptr<test::FrameGenerator> frame_generator(
perkjfa10b552016-10-02 23:45:26 -07001872 test::FrameGenerator::CreateChromaGenerator(kDefaultWidth,
1873 kDefaultHeight));
perkja49cbd32016-09-16 07:53:41 -07001874 test::FrameForwarder forwarder;
perkj803d97f2016-11-01 11:45:46 -07001875 video_send_stream_->SetSource(
1876 &forwarder, VideoSendStream::DegradationPreference::kBalanced);
perkja49cbd32016-09-16 07:53:41 -07001877 forwarder.IncomingCapturedFrame(*frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001878
Peter Boström5811a392015-12-10 13:02:50 +01001879 EXPECT_TRUE(post_encode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001880 << "Timed out while waiting for send-side encoded-frame callback.";
1881
Peter Boström5811a392015-12-10 13:02:50 +01001882 EXPECT_TRUE(pre_decode_observer.Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001883 << "Timed out while waiting for pre-decode encoded-frame callback.";
1884
1885 post_encode_observer.ExpectEqualFrames(pre_decode_observer);
1886
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001887 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001888
1889 sender_transport.StopSending();
1890 receiver_transport.StopSending();
1891
1892 DestroyStreams();
1893}
1894
philipel266f0a42016-11-28 08:49:07 -08001895TEST_P(EndToEndTest, ReceiveStreamSendsRemb) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001896 class RembObserver : public test::EndToEndTest {
1897 public:
1898 RembObserver() : EndToEndTest(kDefaultTimeoutMs) {}
1899
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001900 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
danilchap3dc929e2016-11-02 08:21:59 -07001901 test::RtcpPacketParser parser;
1902 EXPECT_TRUE(parser.Parse(packet, length));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001903
danilchap3dc929e2016-11-02 08:21:59 -07001904 if (parser.remb()->num_packets() > 0) {
1905 EXPECT_EQ(kReceiverLocalVideoSsrc, parser.remb()->sender_ssrc());
1906 EXPECT_LT(0U, parser.remb()->bitrate_bps());
1907 EXPECT_EQ(1U, parser.remb()->ssrcs().size());
1908 EXPECT_EQ(kVideoSendSsrcs[0], parser.remb()->ssrcs()[0]);
Peter Boström5811a392015-12-10 13:02:50 +01001909 observation_complete_.Set();
danilchap3dc929e2016-11-02 08:21:59 -07001910 }
1911
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001912 return SEND_PACKET;
1913 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001914 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001915 EXPECT_TRUE(Wait()) << "Timed out while waiting for a "
1916 "receiver RTCP REMB packet to be "
1917 "sent.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001918 }
1919 } test;
1920
stefane74eef12016-01-08 06:47:13 -08001921 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001922}
1923
philipel266f0a42016-11-28 08:49:07 -08001924TEST_P(EndToEndTest, VerifyBandwidthStats) {
stefanf116bd02015-10-27 08:29:42 -07001925 class RtcpObserver : public test::EndToEndTest {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001926 public:
1927 RtcpObserver()
1928 : EndToEndTest(kDefaultTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00001929 sender_call_(nullptr),
1930 receiver_call_(nullptr),
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001931 has_seen_pacer_delay_(false) {}
1932
stefanf116bd02015-10-27 08:29:42 -07001933 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001934 Call::Stats sender_stats = sender_call_->GetStats();
1935 Call::Stats receiver_stats = receiver_call_->GetStats();
1936 if (!has_seen_pacer_delay_)
1937 has_seen_pacer_delay_ = sender_stats.pacer_delay_ms > 0;
1938 if (sender_stats.send_bandwidth_bps > 0 &&
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00001939 receiver_stats.recv_bandwidth_bps > 0 && has_seen_pacer_delay_) {
Peter Boström5811a392015-12-10 13:02:50 +01001940 observation_complete_.Set();
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00001941 }
stefanf116bd02015-10-27 08:29:42 -07001942 return SEND_PACKET;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001943 }
1944
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001945 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001946 sender_call_ = sender_call;
1947 receiver_call_ = receiver_call;
1948 }
1949
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001950 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001951 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
1952 "non-zero bandwidth stats.";
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001953 }
1954
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001955 private:
1956 Call* sender_call_;
1957 Call* receiver_call_;
1958 bool has_seen_pacer_delay_;
1959 } test;
1960
stefane74eef12016-01-08 06:47:13 -08001961 RunBaseTest(&test);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001962}
1963
stefan32f81542016-01-20 07:13:58 -08001964
1965// Verifies that it's possible to limit the send BWE by sending a REMB.
1966// This is verified by allowing the send BWE to ramp-up to >1000 kbps,
1967// then have the test generate a REMB of 500 kbps and verify that the send BWE
1968// is reduced to exactly 500 kbps. Then a REMB of 1000 kbps is generated and the
1969// test verifies that the send BWE ramps back up to exactly 1000 kbps.
philipel266f0a42016-11-28 08:49:07 -08001970TEST_P(EndToEndTest, RembWithSendSideBwe) {
stefan32f81542016-01-20 07:13:58 -08001971 class BweObserver : public test::EndToEndTest {
1972 public:
1973 BweObserver()
1974 : EndToEndTest(kDefaultTimeoutMs),
1975 sender_call_(nullptr),
1976 clock_(Clock::GetRealTimeClock()),
1977 sender_ssrc_(0),
1978 remb_bitrate_bps_(1000000),
1979 receive_transport_(nullptr),
1980 event_(false, false),
1981 poller_thread_(&BitrateStatsPollingThread,
1982 this,
1983 "BitrateStatsPollingThread"),
Erik Språng737336d2016-07-29 12:59:36 +02001984 state_(kWaitForFirstRampUp),
1985 retransmission_rate_limiter_(clock_, 1000) {}
stefan32f81542016-01-20 07:13:58 -08001986
1987 ~BweObserver() {}
1988
nisseef8b61e2016-04-29 06:09:15 -07001989 test::PacketTransport* CreateReceiveTransport() override {
stefan32f81542016-01-20 07:13:58 -08001990 receive_transport_ = new test::PacketTransport(
1991 nullptr, this, test::PacketTransport::kReceiver,
1992 FakeNetworkPipe::Config());
1993 return receive_transport_;
1994 }
1995
1996 Call::Config GetSenderCallConfig() override {
skvlad11a9cbf2016-10-07 11:53:05 -07001997 Call::Config config(&event_log_);
stefan32f81542016-01-20 07:13:58 -08001998 // Set a high start bitrate to reduce the test completion time.
1999 config.bitrate_config.start_bitrate_bps = remb_bitrate_bps_;
2000 return config;
2001 }
2002
2003 void ModifyVideoConfigs(
2004 VideoSendStream::Config* send_config,
2005 std::vector<VideoReceiveStream::Config>* receive_configs,
2006 VideoEncoderConfig* encoder_config) override {
2007 ASSERT_EQ(1u, send_config->rtp.ssrcs.size());
2008 send_config->rtp.extensions.clear();
2009 send_config->rtp.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07002010 RtpExtension(RtpExtension::kTransportSequenceNumberUri,
stefan32f81542016-01-20 07:13:58 -08002011 test::kTransportSequenceNumberExtensionId));
2012 sender_ssrc_ = send_config->rtp.ssrcs[0];
2013
perkjfa10b552016-10-02 23:45:26 -07002014 encoder_config->max_bitrate_bps = 2000000;
stefan32f81542016-01-20 07:13:58 -08002015
2016 ASSERT_EQ(1u, receive_configs->size());
2017 (*receive_configs)[0].rtp.remb = false;
2018 (*receive_configs)[0].rtp.transport_cc = true;
2019 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
2020 RtpRtcp::Configuration config;
2021 config.receiver_only = true;
2022 config.clock = clock_;
2023 config.outgoing_transport = receive_transport_;
Erik Språng737336d2016-07-29 12:59:36 +02002024 config.retransmission_rate_limiter = &retransmission_rate_limiter_;
stefan32f81542016-01-20 07:13:58 -08002025 rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(config));
2026 rtp_rtcp_->SetRemoteSSRC((*receive_configs)[0].rtp.remote_ssrc);
2027 rtp_rtcp_->SetSSRC((*receive_configs)[0].rtp.local_ssrc);
2028 rtp_rtcp_->SetREMBStatus(true);
2029 rtp_rtcp_->SetSendingStatus(true);
2030 rtp_rtcp_->SetRTCPStatus(RtcpMode::kReducedSize);
2031 }
2032
2033 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2034 sender_call_ = sender_call;
2035 }
2036
2037 static bool BitrateStatsPollingThread(void* obj) {
2038 return static_cast<BweObserver*>(obj)->PollStats();
2039 }
2040
2041 bool PollStats() {
2042 if (sender_call_) {
2043 Call::Stats stats = sender_call_->GetStats();
2044 switch (state_) {
2045 case kWaitForFirstRampUp:
2046 if (stats.send_bandwidth_bps >= remb_bitrate_bps_) {
2047 state_ = kWaitForRemb;
2048 remb_bitrate_bps_ /= 2;
2049 rtp_rtcp_->SetREMBData(
2050 remb_bitrate_bps_,
2051 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
2052 rtp_rtcp_->SendRTCP(kRtcpRr);
2053 }
2054 break;
2055
2056 case kWaitForRemb:
2057 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
2058 state_ = kWaitForSecondRampUp;
2059 remb_bitrate_bps_ *= 2;
2060 rtp_rtcp_->SetREMBData(
2061 remb_bitrate_bps_,
2062 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
2063 rtp_rtcp_->SendRTCP(kRtcpRr);
2064 }
2065 break;
2066
2067 case kWaitForSecondRampUp:
2068 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
2069 observation_complete_.Set();
2070 }
2071 break;
2072 }
2073 }
2074
2075 return !event_.Wait(1000);
2076 }
2077
2078 void PerformTest() override {
2079 poller_thread_.Start();
2080 EXPECT_TRUE(Wait())
2081 << "Timed out while waiting for bitrate to change according to REMB.";
2082 poller_thread_.Stop();
2083 }
2084
2085 private:
2086 enum TestState { kWaitForFirstRampUp, kWaitForRemb, kWaitForSecondRampUp };
2087
2088 Call* sender_call_;
2089 Clock* const clock_;
2090 uint32_t sender_ssrc_;
2091 int remb_bitrate_bps_;
kwiberg27f982b2016-03-01 11:52:33 -08002092 std::unique_ptr<RtpRtcp> rtp_rtcp_;
stefan32f81542016-01-20 07:13:58 -08002093 test::PacketTransport* receive_transport_;
2094 rtc::Event event_;
2095 rtc::PlatformThread poller_thread_;
2096 TestState state_;
Erik Språng737336d2016-07-29 12:59:36 +02002097 RateLimiter retransmission_rate_limiter_;
stefan32f81542016-01-20 07:13:58 -08002098 } test;
2099
2100 RunBaseTest(&test);
2101}
2102
philipel266f0a42016-11-28 08:49:07 -08002103TEST_P(EndToEndTest, VerifyNackStats) {
Åsa Persson352b2d72015-04-15 18:00:40 +02002104 static const int kPacketNumberToDrop = 200;
2105 class NackObserver : public test::EndToEndTest {
2106 public:
2107 NackObserver()
2108 : EndToEndTest(kLongTimeoutMs),
2109 sent_rtp_packets_(0),
2110 dropped_rtp_packet_(0),
2111 dropped_rtp_packet_requested_(false),
2112 send_stream_(nullptr),
2113 start_runtime_ms_(-1) {}
2114
2115 private:
2116 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002117 rtc::CritScope lock(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02002118 if (++sent_rtp_packets_ == kPacketNumberToDrop) {
kwiberg27f982b2016-03-01 11:52:33 -08002119 std::unique_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
Åsa Persson352b2d72015-04-15 18:00:40 +02002120 RTPHeader header;
2121 EXPECT_TRUE(parser->Parse(packet, length, &header));
2122 dropped_rtp_packet_ = header.sequenceNumber;
2123 return DROP_PACKET;
2124 }
2125 VerifyStats();
2126 return SEND_PACKET;
2127 }
2128
2129 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
stefan608213e2015-11-01 14:56:10 -08002130 rtc::CritScope lock(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02002131 test::RtcpPacketParser rtcp_parser;
2132 rtcp_parser.Parse(packet, length);
Danil Chapovalovba6f7be2016-09-02 18:29:10 +02002133 const std::vector<uint16_t>& nacks = rtcp_parser.nack()->packet_ids();
Åsa Persson352b2d72015-04-15 18:00:40 +02002134 if (!nacks.empty() && std::find(
2135 nacks.begin(), nacks.end(), dropped_rtp_packet_) != nacks.end()) {
2136 dropped_rtp_packet_requested_ = true;
2137 }
2138 return SEND_PACKET;
2139 }
2140
stefan608213e2015-11-01 14:56:10 -08002141 void VerifyStats() EXCLUSIVE_LOCKS_REQUIRED(&crit_) {
Åsa Persson352b2d72015-04-15 18:00:40 +02002142 if (!dropped_rtp_packet_requested_)
2143 return;
2144 int send_stream_nack_packets = 0;
2145 int receive_stream_nack_packets = 0;
2146 VideoSendStream::Stats stats = send_stream_->GetStats();
2147 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
2148 stats.substreams.begin(); it != stats.substreams.end(); ++it) {
2149 const VideoSendStream::StreamStats& stream_stats = it->second;
2150 send_stream_nack_packets +=
2151 stream_stats.rtcp_packet_type_counts.nack_packets;
2152 }
2153 for (size_t i = 0; i < receive_streams_.size(); ++i) {
2154 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
2155 receive_stream_nack_packets +=
2156 stats.rtcp_packet_type_counts.nack_packets;
2157 }
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002158 if (send_stream_nack_packets >= 1 && receive_stream_nack_packets >= 1) {
Åsa Persson352b2d72015-04-15 18:00:40 +02002159 // NACK packet sent on receive stream and received on sent stream.
2160 if (MinMetricRunTimePassed())
Peter Boström5811a392015-12-10 13:02:50 +01002161 observation_complete_.Set();
Åsa Persson352b2d72015-04-15 18:00:40 +02002162 }
2163 }
2164
2165 bool MinMetricRunTimePassed() {
2166 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
2167 if (start_runtime_ms_ == -1) {
2168 start_runtime_ms_ = now;
2169 return false;
2170 }
2171 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
2172 return elapsed_sec > metrics::kMinRunTimeInSeconds;
2173 }
2174
stefanff483612015-12-21 03:14:00 -08002175 void ModifyVideoConfigs(
2176 VideoSendStream::Config* send_config,
2177 std::vector<VideoReceiveStream::Config>* receive_configs,
2178 VideoEncoderConfig* encoder_config) override {
Åsa Persson352b2d72015-04-15 18:00:40 +02002179 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2180 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
sakal55d932b2016-09-30 06:19:08 -07002181 (*receive_configs)[0].renderer = &fake_renderer_;
Åsa Persson352b2d72015-04-15 18:00:40 +02002182 }
2183
stefanff483612015-12-21 03:14:00 -08002184 void OnVideoStreamsCreated(
Åsa Persson352b2d72015-04-15 18:00:40 +02002185 VideoSendStream* send_stream,
2186 const std::vector<VideoReceiveStream*>& receive_streams) override {
2187 send_stream_ = send_stream;
2188 receive_streams_ = receive_streams;
2189 }
2190
2191 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002192 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Åsa Persson352b2d72015-04-15 18:00:40 +02002193 }
2194
sakal55d932b2016-09-30 06:19:08 -07002195 test::FakeVideoRenderer fake_renderer_;
stefan608213e2015-11-01 14:56:10 -08002196 rtc::CriticalSection crit_;
Åsa Persson352b2d72015-04-15 18:00:40 +02002197 uint64_t sent_rtp_packets_;
stefan608213e2015-11-01 14:56:10 -08002198 uint16_t dropped_rtp_packet_ GUARDED_BY(&crit_);
2199 bool dropped_rtp_packet_requested_ GUARDED_BY(&crit_);
Åsa Persson352b2d72015-04-15 18:00:40 +02002200 std::vector<VideoReceiveStream*> receive_streams_;
2201 VideoSendStream* send_stream_;
2202 int64_t start_runtime_ms_;
2203 } test;
2204
asapersson01d70a32016-05-20 06:29:46 -07002205 metrics::Reset();
stefane74eef12016-01-08 06:47:13 -08002206 RunBaseTest(&test);
Åsa Persson352b2d72015-04-15 18:00:40 +02002207
asapersson01d70a32016-05-20 06:29:46 -07002208 EXPECT_EQ(
2209 1, metrics::NumSamples("WebRTC.Video.UniqueNackRequestsSentInPercent"));
2210 EXPECT_EQ(1, metrics::NumSamples(
2211 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
2212 EXPECT_GT(metrics::MinSample("WebRTC.Video.NackPacketsSentPerMinute"), 0);
Åsa Persson352b2d72015-04-15 18:00:40 +02002213}
2214
sprangb4a1ae52015-12-03 08:10:08 -08002215void EndToEndTest::VerifyHistogramStats(bool use_rtx,
2216 bool use_red,
2217 bool screenshare) {
tommi2e82f382016-06-21 00:26:43 -07002218 class StatsObserver : public test::EndToEndTest,
2219 public rtc::VideoSinkInterface<VideoFrame> {
Åsa Persson3c391cb2015-04-27 10:09:49 +02002220 public:
sprangb4a1ae52015-12-03 08:10:08 -08002221 StatsObserver(bool use_rtx, bool use_red, bool screenshare)
Åsa Persson3c391cb2015-04-27 10:09:49 +02002222 : EndToEndTest(kLongTimeoutMs),
2223 use_rtx_(use_rtx),
2224 use_red_(use_red),
sprangb4a1ae52015-12-03 08:10:08 -08002225 screenshare_(screenshare),
Peter Boström39593972016-02-15 11:27:15 +01002226 // This test uses NACK, so to send FEC we can't use a fake encoder.
magjed509e4fe2016-11-18 01:34:11 -08002227 vp8_encoder_(use_red ? VP8Encoder::Create() : nullptr),
Åsa Persson3c391cb2015-04-27 10:09:49 +02002228 sender_call_(nullptr),
2229 receiver_call_(nullptr),
asapersson1394c7b2016-10-18 11:50:50 -07002230 start_runtime_ms_(-1),
2231 num_frames_received_(0) {}
Åsa Persson3c391cb2015-04-27 10:09:49 +02002232
2233 private:
asapersson1394c7b2016-10-18 11:50:50 -07002234 void OnFrame(const VideoFrame& video_frame) override {
2235 // The RTT is needed to estimate |ntp_time_ms| which is used by
2236 // end-to-end delay stats. Therefore, start counting received frames once
2237 // |ntp_time_ms| is valid.
2238 if (video_frame.ntp_time_ms() > 0 &&
2239 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds() >=
2240 video_frame.ntp_time_ms()) {
2241 rtc::CritScope lock(&crit_);
2242 ++num_frames_received_;
2243 }
2244 }
tommi2e82f382016-06-21 00:26:43 -07002245
Åsa Persson3c391cb2015-04-27 10:09:49 +02002246 Action OnSendRtp(const uint8_t* packet, size_t length) override {
asapersson1394c7b2016-10-18 11:50:50 -07002247 if (MinMetricRunTimePassed() && MinNumberOfFramesReceived())
Peter Boström5811a392015-12-10 13:02:50 +01002248 observation_complete_.Set();
Åsa Persson3c391cb2015-04-27 10:09:49 +02002249
stefanf116bd02015-10-27 08:29:42 -07002250 return SEND_PACKET;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002251 }
2252
2253 bool MinMetricRunTimePassed() {
2254 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
2255 if (start_runtime_ms_ == -1) {
2256 start_runtime_ms_ = now;
2257 return false;
2258 }
2259 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
2260 return elapsed_sec > metrics::kMinRunTimeInSeconds * 2;
2261 }
2262
asapersson1394c7b2016-10-18 11:50:50 -07002263 bool MinNumberOfFramesReceived() const {
2264 const int kMinRequiredHistogramSamples = 200;
2265 rtc::CritScope lock(&crit_);
2266 return num_frames_received_ > kMinRequiredHistogramSamples;
2267 }
2268
stefanff483612015-12-21 03:14:00 -08002269 void ModifyVideoConfigs(
2270 VideoSendStream::Config* send_config,
2271 std::vector<VideoReceiveStream::Config>* receive_configs,
2272 VideoEncoderConfig* encoder_config) override {
stefana23fc622016-07-28 07:56:38 -07002273 static const int kExtensionId = 8;
2274 send_config->rtp.extensions.push_back(RtpExtension(
2275 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
2276 (*receive_configs)[0].rtp.extensions.push_back(RtpExtension(
2277 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002278 // NACK
2279 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2280 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
tommi2e82f382016-06-21 00:26:43 -07002281 (*receive_configs)[0].renderer = this;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002282 // FEC
2283 if (use_red_) {
brandtrb5f2c3f2016-10-04 23:28:39 -07002284 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
2285 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
Peter Boström39593972016-02-15 11:27:15 +01002286 send_config->encoder_settings.encoder = vp8_encoder_.get();
2287 send_config->encoder_settings.payload_name = "VP8";
2288 (*receive_configs)[0].decoders[0].payload_name = "VP8";
brandtrb5f2c3f2016-10-04 23:28:39 -07002289 (*receive_configs)[0].rtp.ulpfec.red_payload_type = kRedPayloadType;
2290 (*receive_configs)[0].rtp.ulpfec.ulpfec_payload_type =
2291 kUlpfecPayloadType;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002292 }
2293 // RTX
2294 if (use_rtx_) {
2295 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
2296 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002297 (*receive_configs)[0].rtp.rtx[kFakeVideoSendPayloadType].ssrc =
Åsa Persson3c391cb2015-04-27 10:09:49 +02002298 kSendRtxSsrcs[0];
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002299 (*receive_configs)[0].rtp.rtx[kFakeVideoSendPayloadType].payload_type =
Åsa Persson3c391cb2015-04-27 10:09:49 +02002300 kSendRtxPayloadType;
2301 }
asapersson1490f7a2016-09-23 02:09:46 -07002302 // RTT needed for RemoteNtpTimeEstimator for the receive stream.
2303 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report = true;
sprangb4a1ae52015-12-03 08:10:08 -08002304 encoder_config->content_type =
2305 screenshare_ ? VideoEncoderConfig::ContentType::kScreen
2306 : VideoEncoderConfig::ContentType::kRealtimeVideo;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002307 }
2308
2309 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2310 sender_call_ = sender_call;
2311 receiver_call_ = receiver_call;
2312 }
2313
Åsa Persson3c391cb2015-04-27 10:09:49 +02002314 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002315 EXPECT_TRUE(Wait()) << "Timed out waiting for packet to be NACKed.";
Åsa Persson3c391cb2015-04-27 10:09:49 +02002316 }
2317
asapersson1394c7b2016-10-18 11:50:50 -07002318 rtc::CriticalSection crit_;
sprangb4a1ae52015-12-03 08:10:08 -08002319 const bool use_rtx_;
2320 const bool use_red_;
2321 const bool screenshare_;
kwiberg27f982b2016-03-01 11:52:33 -08002322 const std::unique_ptr<VideoEncoder> vp8_encoder_;
Åsa Persson3c391cb2015-04-27 10:09:49 +02002323 Call* sender_call_;
2324 Call* receiver_call_;
2325 int64_t start_runtime_ms_;
asapersson1394c7b2016-10-18 11:50:50 -07002326 int num_frames_received_ GUARDED_BY(&crit_);
sprangb4a1ae52015-12-03 08:10:08 -08002327 } test(use_rtx, use_red, screenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002328
asapersson01d70a32016-05-20 06:29:46 -07002329 metrics::Reset();
stefane74eef12016-01-08 06:47:13 -08002330 RunBaseTest(&test);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002331
stefan91d92602015-11-11 10:13:02 -08002332 // Delete the call for Call stats to be reported.
stefan18adf0a2015-11-17 06:24:56 -08002333 sender_call_.reset();
stefan91d92602015-11-11 10:13:02 -08002334 receiver_call_.reset();
2335
sprangb4a1ae52015-12-03 08:10:08 -08002336 std::string video_prefix =
2337 screenshare ? "WebRTC.Video.Screenshare." : "WebRTC.Video.";
2338
Åsa Persson3c391cb2015-04-27 10:09:49 +02002339 // Verify that stats have been updated once.
asapersson4374a092016-07-27 00:39:09 -07002340 EXPECT_EQ(2, metrics::NumSamples("WebRTC.Call.LifetimeInSeconds"));
asapersson01d70a32016-05-20 06:29:46 -07002341 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.VideoBitrateReceivedInKbps"));
2342 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.RtcpBitrateReceivedInBps"));
2343 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.BitrateReceivedInKbps"));
2344 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.EstimatedSendBitrateInKbps"));
2345 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Call.PacerBitrateInKbps"));
2346
asapersson4374a092016-07-27 00:39:09 -07002347 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SendStreamLifetimeInSeconds"));
2348 EXPECT_EQ(1,
2349 metrics::NumSamples("WebRTC.Video.ReceiveStreamLifetimeInSeconds"));
2350
asapersson01d70a32016-05-20 06:29:46 -07002351 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
stefan91d92602015-11-11 10:13:02 -08002352 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002353 metrics::NumSamples(video_prefix + "NackPacketsReceivedPerMinute"));
2354 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
asaperssond89920b2015-07-22 06:52:00 -07002355 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002356 metrics::NumSamples(video_prefix + "FirPacketsReceivedPerMinute"));
2357 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
sprangb4a1ae52015-12-03 08:10:08 -08002358 EXPECT_EQ(1,
asapersson01d70a32016-05-20 06:29:46 -07002359 metrics::NumSamples(video_prefix + "PliPacketsReceivedPerMinute"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002360
asapersson01d70a32016-05-20 06:29:46 -07002361 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "KeyFramesSentInPermille"));
2362 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
2363
2364 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentPacketsLostInPercent"));
2365 EXPECT_EQ(1,
2366 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
2367
2368 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputWidthInPixels"));
2369 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputHeightInPixels"));
2370 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentWidthInPixels"));
2371 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentHeightInPixels"));
2372 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedWidthInPixels"));
2373 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedHeightInPixels"));
2374
perkjfa10b552016-10-02 23:45:26 -07002375 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "InputWidthInPixels",
2376 kDefaultWidth));
2377 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "InputHeightInPixels",
2378 kDefaultHeight));
2379 EXPECT_EQ(
2380 1, metrics::NumEvents(video_prefix + "SentWidthInPixels", kDefaultWidth));
2381 EXPECT_EQ(1, metrics::NumEvents(video_prefix + "SentHeightInPixels",
2382 kDefaultHeight));
2383 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.ReceivedWidthInPixels",
2384 kDefaultWidth));
2385 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.ReceivedHeightInPixels",
2386 kDefaultHeight));
asapersson01d70a32016-05-20 06:29:46 -07002387
2388 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "InputFramesPerSecond"));
2389 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SentFramesPerSecond"));
2390 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
2391 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
2392
2393 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
2394 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
2395 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
2396 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
2397
asapersson1490f7a2016-09-23 02:09:46 -07002398 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.EndToEndDelayInMs"));
asapersson01d70a32016-05-20 06:29:46 -07002399 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
2400
2401 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "EncodeTimeInMs"));
2402 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodeTimeInMs"));
2403
2404 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "BitrateSentInKbps"));
2405 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateReceivedInKbps"));
2406 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "MediaBitrateSentInKbps"));
2407 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.MediaBitrateReceivedInKbps"));
2408 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "PaddingBitrateSentInKbps"));
2409 EXPECT_EQ(1,
2410 metrics::NumSamples("WebRTC.Video.PaddingBitrateReceivedInKbps"));
asapersson6f14be82015-11-16 00:40:49 -08002411 EXPECT_EQ(
asapersson01d70a32016-05-20 06:29:46 -07002412 1, metrics::NumSamples(video_prefix + "RetransmittedBitrateSentInKbps"));
2413 EXPECT_EQ(1, metrics::NumSamples(
2414 "WebRTC.Video.RetransmittedBitrateReceivedInKbps"));
asapersson6f14be82015-11-16 00:40:49 -08002415
asapersson01d70a32016-05-20 06:29:46 -07002416 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.SendDelayInMs"));
2417 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SendSideDelayInMs"));
2418 EXPECT_EQ(1, metrics::NumSamples(video_prefix + "SendSideDelayMaxInMs"));
asapersson6f14be82015-11-16 00:40:49 -08002419
Åsa Persson3c391cb2015-04-27 10:09:49 +02002420 int num_rtx_samples = use_rtx ? 1 : 0;
asapersson01d70a32016-05-20 06:29:46 -07002421 EXPECT_EQ(num_rtx_samples,
2422 metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2423 EXPECT_EQ(num_rtx_samples,
2424 metrics::NumSamples("WebRTC.Video.RtxBitrateReceivedInKbps"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002425
2426 int num_red_samples = use_red ? 1 : 0;
asapersson01d70a32016-05-20 06:29:46 -07002427 EXPECT_EQ(num_red_samples,
2428 metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2429 EXPECT_EQ(num_red_samples,
2430 metrics::NumSamples("WebRTC.Video.FecBitrateReceivedInKbps"));
2431 EXPECT_EQ(num_red_samples,
2432 metrics::NumSamples("WebRTC.Video.ReceivedFecPacketsInPercent"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02002433}
2434
philipel266f0a42016-11-28 08:49:07 -08002435TEST_P(EndToEndTest, VerifyHistogramStatsWithRtx) {
Åsa Persson3c391cb2015-04-27 10:09:49 +02002436 const bool kEnabledRtx = true;
2437 const bool kEnabledRed = false;
sprangb4a1ae52015-12-03 08:10:08 -08002438 const bool kScreenshare = false;
2439 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002440}
2441
philipel266f0a42016-11-28 08:49:07 -08002442TEST_P(EndToEndTest, VerifyHistogramStatsWithRed) {
Åsa Persson3c391cb2015-04-27 10:09:49 +02002443 const bool kEnabledRtx = false;
2444 const bool kEnabledRed = true;
sprangb4a1ae52015-12-03 08:10:08 -08002445 const bool kScreenshare = false;
2446 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
2447}
2448
philipel266f0a42016-11-28 08:49:07 -08002449TEST_P(EndToEndTest, VerifyHistogramStatsWithScreenshare) {
sprangb4a1ae52015-12-03 08:10:08 -08002450 const bool kEnabledRtx = false;
2451 const bool kEnabledRed = false;
2452 const bool kScreenshare = true;
2453 VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
Åsa Persson3c391cb2015-04-27 10:09:49 +02002454}
2455
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002456void EndToEndTest::TestSendsSetSsrcs(size_t num_ssrcs,
2457 bool send_single_ssrc_first) {
2458 class SendsSetSsrcs : public test::EndToEndTest {
2459 public:
2460 SendsSetSsrcs(const uint32_t* ssrcs,
2461 size_t num_ssrcs,
2462 bool send_single_ssrc_first)
2463 : EndToEndTest(kDefaultTimeoutMs),
2464 num_ssrcs_(num_ssrcs),
2465 send_single_ssrc_first_(send_single_ssrc_first),
2466 ssrcs_to_observe_(num_ssrcs),
sprang867fb522015-08-03 04:38:41 -07002467 expect_single_ssrc_(send_single_ssrc_first),
2468 send_stream_(nullptr) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002469 for (size_t i = 0; i < num_ssrcs; ++i)
2470 valid_ssrcs_[ssrcs[i]] = true;
2471 }
2472
2473 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002474 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002475 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002476 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002477
2478 EXPECT_TRUE(valid_ssrcs_[header.ssrc])
2479 << "Received unknown SSRC: " << header.ssrc;
2480
2481 if (!valid_ssrcs_[header.ssrc])
Peter Boström5811a392015-12-10 13:02:50 +01002482 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002483
2484 if (!is_observed_[header.ssrc]) {
2485 is_observed_[header.ssrc] = true;
2486 --ssrcs_to_observe_;
2487 if (expect_single_ssrc_) {
2488 expect_single_ssrc_ = false;
Peter Boström5811a392015-12-10 13:02:50 +01002489 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002490 }
2491 }
2492
2493 if (ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01002494 observation_complete_.Set();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002495
2496 return SEND_PACKET;
2497 }
2498
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002499 size_t GetNumVideoStreams() const override { return num_ssrcs_; }
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002500
perkjfa10b552016-10-02 23:45:26 -07002501 // This test use other VideoStream settings than the the default settings
2502 // implemented in DefaultVideoStreamFactory. Therefore this test implement
2503 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
2504 // in ModifyVideoConfigs.
2505 class VideoStreamFactory
2506 : public VideoEncoderConfig::VideoStreamFactoryInterface {
2507 public:
2508 VideoStreamFactory() {}
2509
2510 private:
2511 std::vector<VideoStream> CreateEncoderStreams(
2512 int width,
2513 int height,
2514 const VideoEncoderConfig& encoder_config) override {
2515 std::vector<VideoStream> streams =
2516 test::CreateVideoStreams(width, height, encoder_config);
2517 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
2518 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
2519 streams[i].min_bitrate_bps = 10000;
2520 streams[i].target_bitrate_bps = 15000;
2521 streams[i].max_bitrate_bps = 20000;
2522 }
2523 return streams;
2524 }
2525 };
2526
stefanff483612015-12-21 03:14:00 -08002527 void ModifyVideoConfigs(
2528 VideoSendStream::Config* send_config,
2529 std::vector<VideoReceiveStream::Config>* receive_configs,
2530 VideoEncoderConfig* encoder_config) override {
perkjfa10b552016-10-02 23:45:26 -07002531 encoder_config->video_stream_factory =
2532 new rtc::RefCountedObject<VideoStreamFactory>();
perkj26091b12016-09-01 01:17:40 -07002533 video_encoder_config_all_streams_ = encoder_config->Copy();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002534 if (send_single_ssrc_first_)
perkjfa10b552016-10-02 23:45:26 -07002535 encoder_config->number_of_streams = 1;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002536 }
2537
stefanff483612015-12-21 03:14:00 -08002538 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002539 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002540 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002541 send_stream_ = send_stream;
2542 }
2543
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002544 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002545 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
2546 << (send_single_ssrc_first_ ? "first SSRC."
2547 : "SSRCs.");
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002548
2549 if (send_single_ssrc_first_) {
2550 // Set full simulcast and continue with the rest of the SSRCs.
stefanff483612015-12-21 03:14:00 -08002551 send_stream_->ReconfigureVideoEncoder(
perkj26091b12016-09-01 01:17:40 -07002552 std::move(video_encoder_config_all_streams_));
Peter Boström5811a392015-12-10 13:02:50 +01002553 EXPECT_TRUE(Wait()) << "Timed out while waiting on additional SSRCs.";
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002554 }
2555 }
2556
2557 private:
2558 std::map<uint32_t, bool> valid_ssrcs_;
2559 std::map<uint32_t, bool> is_observed_;
2560
2561 const size_t num_ssrcs_;
2562 const bool send_single_ssrc_first_;
2563
2564 size_t ssrcs_to_observe_;
2565 bool expect_single_ssrc_;
2566
2567 VideoSendStream* send_stream_;
stefanff483612015-12-21 03:14:00 -08002568 VideoEncoderConfig video_encoder_config_all_streams_;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002569 } test(kVideoSendSsrcs, num_ssrcs, send_single_ssrc_first);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002570
stefane74eef12016-01-08 06:47:13 -08002571 RunBaseTest(&test);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002572}
2573
philipel266f0a42016-11-28 08:49:07 -08002574TEST_P(EndToEndTest, ReportsSetEncoderRates) {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002575 class EncoderRateStatsTest : public test::EndToEndTest,
2576 public test::FakeEncoder {
2577 public:
2578 EncoderRateStatsTest()
2579 : EndToEndTest(kDefaultTimeoutMs),
sprang867fb522015-08-03 04:38:41 -07002580 FakeEncoder(Clock::GetRealTimeClock()),
2581 send_stream_(nullptr),
2582 bitrate_kbps_(0) {}
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002583
stefanff483612015-12-21 03:14:00 -08002584 void OnVideoStreamsCreated(
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002585 VideoSendStream* send_stream,
2586 const std::vector<VideoReceiveStream*>& receive_streams) override {
2587 send_stream_ = send_stream;
2588 }
2589
stefanff483612015-12-21 03:14:00 -08002590 void ModifyVideoConfigs(
2591 VideoSendStream::Config* send_config,
2592 std::vector<VideoReceiveStream::Config>* receive_configs,
2593 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002594 send_config->encoder_settings.encoder = this;
kwibergaf476c72016-11-28 15:21:39 -08002595 RTC_DCHECK_EQ(1, encoder_config->number_of_streams);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002596 }
2597
Erik Språng08127a92016-11-16 16:41:30 +01002598 int32_t SetRateAllocation(const BitrateAllocation& rate_allocation,
2599 uint32_t framerate) override {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002600 // Make sure not to trigger on any default zero bitrates.
Erik Språng08127a92016-11-16 16:41:30 +01002601 if (rate_allocation.get_sum_bps() == 0)
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002602 return 0;
Peter Boströmf2f82832015-05-01 13:00:41 +02002603 rtc::CritScope lock(&crit_);
Erik Språng08127a92016-11-16 16:41:30 +01002604 bitrate_kbps_ = rate_allocation.get_sum_kbps();
Peter Boström5811a392015-12-10 13:02:50 +01002605 observation_complete_.Set();
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002606 return 0;
2607 }
2608
2609 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002610 ASSERT_TRUE(Wait())
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002611 << "Timed out while waiting for encoder SetRates() call.";
perkjf5b2e512016-07-05 08:34:04 -07002612 WaitForEncoderTargetBitrateMatchStats();
2613 send_stream_->Stop();
2614 WaitForStatsReportZeroTargetBitrate();
2615 send_stream_->Start();
2616 WaitForEncoderTargetBitrateMatchStats();
2617 }
2618
2619 void WaitForEncoderTargetBitrateMatchStats() {
Peter Boström5811a392015-12-10 13:02:50 +01002620 for (int i = 0; i < kDefaultTimeoutMs; ++i) {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002621 VideoSendStream::Stats stats = send_stream_->GetStats();
2622 {
Peter Boströmf2f82832015-05-01 13:00:41 +02002623 rtc::CritScope lock(&crit_);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002624 if ((stats.target_media_bitrate_bps + 500) / 1000 ==
2625 static_cast<int>(bitrate_kbps_)) {
2626 return;
2627 }
2628 }
2629 SleepMs(1);
2630 }
2631 FAIL()
2632 << "Timed out waiting for stats reporting the currently set bitrate.";
2633 }
2634
perkjf5b2e512016-07-05 08:34:04 -07002635 void WaitForStatsReportZeroTargetBitrate() {
2636 for (int i = 0; i < kDefaultTimeoutMs; ++i) {
2637 if (send_stream_->GetStats().target_media_bitrate_bps == 0) {
2638 return;
2639 }
2640 SleepMs(1);
2641 }
2642 FAIL() << "Timed out waiting for stats reporting zero bitrate.";
2643 }
2644
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002645 private:
stefanf116bd02015-10-27 08:29:42 -07002646 rtc::CriticalSection crit_;
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002647 VideoSendStream* send_stream_;
2648 uint32_t bitrate_kbps_ GUARDED_BY(crit_);
2649 } test;
2650
stefane74eef12016-01-08 06:47:13 -08002651 RunBaseTest(&test);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00002652}
2653
philipel266f0a42016-11-28 08:49:07 -08002654TEST_P(EndToEndTest, GetStats) {
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002655 static const int kStartBitrateBps = 3000000;
Peter Boströmdef398832015-05-27 17:59:11 +02002656 static const int kExpectedRenderDelayMs = 20;
tommi2e82f382016-06-21 00:26:43 -07002657
2658 class ReceiveStreamRenderer : public rtc::VideoSinkInterface<VideoFrame> {
2659 public:
2660 ReceiveStreamRenderer() {}
2661
2662 private:
2663 void OnFrame(const VideoFrame& video_frame) override {}
2664 };
2665
nissed30a1112016-04-18 05:15:22 -07002666 class StatsObserver : public test::EndToEndTest,
2667 public rtc::VideoSinkInterface<VideoFrame> {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002668 public:
stefanf116bd02015-10-27 08:29:42 -07002669 StatsObserver()
2670 : EndToEndTest(kLongTimeoutMs),
Peter Boströmc6e16e32016-02-05 14:15:53 +01002671 encoder_(Clock::GetRealTimeClock(), 10),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00002672 send_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002673 expected_send_ssrcs_(),
Peter Boström5811a392015-12-10 13:02:50 +01002674 check_stats_event_(false, false) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002675
2676 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002677 Action OnSendRtp(const uint8_t* packet, size_t length) override {
sprangcd349d92016-07-13 09:11:28 -07002678 // Drop every 25th packet => 4% loss.
2679 static const int kPacketLossFrac = 25;
2680 RTPHeader header;
2681 RtpUtility::RtpHeaderParser parser(packet, length);
2682 if (parser.Parse(&header) &&
2683 expected_send_ssrcs_.find(header.ssrc) !=
2684 expected_send_ssrcs_.end() &&
2685 header.sequenceNumber % kPacketLossFrac == 0) {
2686 return DROP_PACKET;
2687 }
Peter Boström5811a392015-12-10 13:02:50 +01002688 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002689 return SEND_PACKET;
2690 }
2691
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002692 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002693 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002694 return SEND_PACKET;
2695 }
2696
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002697 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002698 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002699 return SEND_PACKET;
2700 }
2701
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002702 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boström5811a392015-12-10 13:02:50 +01002703 check_stats_event_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002704 return SEND_PACKET;
2705 }
2706
nissed30a1112016-04-18 05:15:22 -07002707 void OnFrame(const VideoFrame& video_frame) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002708 // Ensure that we have at least 5ms send side delay.
nissed30a1112016-04-18 05:15:22 -07002709 SleepMs(5);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002710 }
2711
2712 bool CheckReceiveStats() {
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002713 for (size_t i = 0; i < receive_streams_.size(); ++i) {
2714 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
2715 EXPECT_EQ(expected_receive_ssrcs_[i], stats.ssrc);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002716
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002717 // Make sure all fields have been populated.
2718 // TODO(pbos): Use CompoundKey if/when we ever know that all stats are
2719 // always filled for all receivers.
2720 receive_stats_filled_["IncomingRate"] |=
2721 stats.network_frame_rate != 0 || stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002722
Peter Boströmb7d9a972015-12-18 16:01:11 +01002723 send_stats_filled_["DecoderImplementationName"] |=
2724 stats.decoder_implementation_name ==
2725 test::FakeDecoder::kImplementationName;
Peter Boströmdef398832015-05-27 17:59:11 +02002726 receive_stats_filled_["RenderDelayAsHighAsExpected"] |=
2727 stats.render_delay_ms >= kExpectedRenderDelayMs;
2728
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002729 receive_stats_filled_["FrameCallback"] |= stats.decode_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002730
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002731 receive_stats_filled_["FrameRendered"] |= stats.render_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002732
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002733 receive_stats_filled_["StatisticsUpdated"] |=
2734 stats.rtcp_stats.cumulative_lost != 0 ||
2735 stats.rtcp_stats.extended_max_sequence_number != 0 ||
2736 stats.rtcp_stats.fraction_lost != 0 || stats.rtcp_stats.jitter != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002737
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002738 receive_stats_filled_["DataCountersUpdated"] |=
2739 stats.rtp_stats.transmitted.payload_bytes != 0 ||
2740 stats.rtp_stats.fec.packets != 0 ||
2741 stats.rtp_stats.transmitted.header_bytes != 0 ||
2742 stats.rtp_stats.transmitted.packets != 0 ||
2743 stats.rtp_stats.transmitted.padding_bytes != 0 ||
2744 stats.rtp_stats.retransmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002745
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002746 receive_stats_filled_["CodecStats"] |=
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002747 stats.target_delay_ms != 0 || stats.discarded_packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002748
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002749 receive_stats_filled_["FrameCounts"] |=
2750 stats.frame_counts.key_frames != 0 ||
2751 stats.frame_counts.delta_frames != 0;
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002752
pbosbb36fdf2015-07-09 07:48:14 -07002753 receive_stats_filled_["CName"] |= !stats.c_name.empty();
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002754
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002755 receive_stats_filled_["RtcpPacketTypeCount"] |=
2756 stats.rtcp_packet_type_counts.fir_packets != 0 ||
2757 stats.rtcp_packet_type_counts.nack_packets != 0 ||
2758 stats.rtcp_packet_type_counts.pli_packets != 0 ||
2759 stats.rtcp_packet_type_counts.nack_requests != 0 ||
2760 stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbosf42376c2015-08-28 07:35:32 -07002761
2762 assert(stats.current_payload_type == -1 ||
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002763 stats.current_payload_type == kFakeVideoSendPayloadType);
pbosf42376c2015-08-28 07:35:32 -07002764 receive_stats_filled_["IncomingPayloadType"] |=
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002765 stats.current_payload_type == kFakeVideoSendPayloadType;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002766 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002767
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002768 return AllStatsFilled(receive_stats_filled_);
2769 }
2770
2771 bool CheckSendStats() {
Peter Boström74f6e9e2016-04-04 17:56:10 +02002772 RTC_DCHECK(send_stream_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002773 VideoSendStream::Stats stats = send_stream_->GetStats();
2774
2775 send_stats_filled_["NumStreams"] |=
2776 stats.substreams.size() == expected_send_ssrcs_.size();
2777
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00002778 send_stats_filled_["CpuOveruseMetrics"] |=
Peter Boströme4499152016-02-05 11:13:28 +01002779 stats.avg_encode_time_ms != 0 && stats.encode_usage_percent != 0;
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00002780
Peter Boströmb7d9a972015-12-18 16:01:11 +01002781 send_stats_filled_["EncoderImplementationName"] |=
2782 stats.encoder_implementation_name ==
2783 test::FakeEncoder::kImplementationName;
2784
Pera48ddb72016-09-29 11:48:50 +02002785 send_stats_filled_["EncoderPreferredBitrate"] |=
2786 stats.preferred_media_bitrate_bps > 0;
2787
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002788 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002789 stats.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002790 it != stats.substreams.end(); ++it) {
sprangcd349d92016-07-13 09:11:28 -07002791 if (expected_send_ssrcs_.find(it->first) == expected_send_ssrcs_.end())
2792 continue; // Probably RTX.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002793
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002794 send_stats_filled_[CompoundKey("CapturedFrameRate", it->first)] |=
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002795 stats.input_frame_rate != 0;
2796
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002797 const VideoSendStream::StreamStats& stream_stats = it->second;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002798
2799 send_stats_filled_[CompoundKey("StatisticsUpdated", it->first)] |=
2800 stream_stats.rtcp_stats.cumulative_lost != 0 ||
2801 stream_stats.rtcp_stats.extended_max_sequence_number != 0 ||
2802 stream_stats.rtcp_stats.fraction_lost != 0;
2803
2804 send_stats_filled_[CompoundKey("DataCountersUpdated", it->first)] |=
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00002805 stream_stats.rtp_stats.fec.packets != 0 ||
2806 stream_stats.rtp_stats.transmitted.padding_bytes != 0 ||
2807 stream_stats.rtp_stats.retransmitted.packets != 0 ||
2808 stream_stats.rtp_stats.transmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002809
sprangcd349d92016-07-13 09:11:28 -07002810 send_stats_filled_[CompoundKey("BitrateStatisticsObserver.Total",
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002811 it->first)] |=
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002812 stream_stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002813
sprangcd349d92016-07-13 09:11:28 -07002814 send_stats_filled_[CompoundKey("BitrateStatisticsObserver.Retransmit",
2815 it->first)] |=
2816 stream_stats.retransmit_bitrate_bps != 0;
2817
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002818 send_stats_filled_[CompoundKey("FrameCountObserver", it->first)] |=
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002819 stream_stats.frame_counts.delta_frames != 0 ||
2820 stream_stats.frame_counts.key_frames != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002821
2822 send_stats_filled_[CompoundKey("OutgoingRate", it->first)] |=
2823 stats.encode_frame_rate != 0;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +00002824
2825 send_stats_filled_[CompoundKey("Delay", it->first)] |=
2826 stream_stats.avg_delay_ms != 0 || stream_stats.max_delay_ms != 0;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002827
2828 // TODO(pbos): Use CompoundKey when the test makes sure that all SSRCs
2829 // report dropped packets.
2830 send_stats_filled_["RtcpPacketTypeCount"] |=
2831 stream_stats.rtcp_packet_type_counts.fir_packets != 0 ||
2832 stream_stats.rtcp_packet_type_counts.nack_packets != 0 ||
2833 stream_stats.rtcp_packet_type_counts.pli_packets != 0 ||
2834 stream_stats.rtcp_packet_type_counts.nack_requests != 0 ||
2835 stream_stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002836 }
2837
2838 return AllStatsFilled(send_stats_filled_);
2839 }
2840
2841 std::string CompoundKey(const char* name, uint32_t ssrc) {
2842 std::ostringstream oss;
2843 oss << name << "_" << ssrc;
2844 return oss.str();
2845 }
2846
2847 bool AllStatsFilled(const std::map<std::string, bool>& stats_map) {
sprangcd349d92016-07-13 09:11:28 -07002848 for (const auto& stat : stats_map) {
2849 if (!stat.second)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002850 return false;
2851 }
2852 return true;
2853 }
2854
stefane74eef12016-01-08 06:47:13 -08002855 test::PacketTransport* CreateSendTransport(Call* sender_call) override {
2856 FakeNetworkPipe::Config network_config;
2857 network_config.loss_percent = 5;
2858 return new test::PacketTransport(
2859 sender_call, this, test::PacketTransport::kSender, network_config);
2860 }
2861
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002862 Call::Config GetSenderCallConfig() override {
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002863 Call::Config config = EndToEndTest::GetSenderCallConfig();
Stefan Holmere5904162015-03-26 11:11:06 +01002864 config.bitrate_config.start_bitrate_bps = kStartBitrateBps;
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002865 return config;
2866 }
2867
perkjfa10b552016-10-02 23:45:26 -07002868 // This test use other VideoStream settings than the the default settings
2869 // implemented in DefaultVideoStreamFactory. Therefore this test implement
2870 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
2871 // in ModifyVideoConfigs.
2872 class VideoStreamFactory
2873 : public VideoEncoderConfig::VideoStreamFactoryInterface {
2874 public:
2875 VideoStreamFactory() {}
2876
2877 private:
2878 std::vector<VideoStream> CreateEncoderStreams(
2879 int width,
2880 int height,
2881 const VideoEncoderConfig& encoder_config) override {
2882 std::vector<VideoStream> streams =
2883 test::CreateVideoStreams(width, height, encoder_config);
2884 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
2885 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
2886 streams[i].min_bitrate_bps = 10000;
2887 streams[i].target_bitrate_bps = 15000;
2888 streams[i].max_bitrate_bps = 20000;
2889 }
2890 return streams;
2891 }
2892 };
2893
stefanff483612015-12-21 03:14:00 -08002894 void ModifyVideoConfigs(
2895 VideoSendStream::Config* send_config,
2896 std::vector<VideoReceiveStream::Config>* receive_configs,
2897 VideoEncoderConfig* encoder_config) override {
perkjfa10b552016-10-02 23:45:26 -07002898 encoder_config->video_stream_factory =
2899 new rtc::RefCountedObject<VideoStreamFactory>();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002900 send_config->pre_encode_callback = this; // Used to inject delay.
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002901 expected_cname_ = send_config->rtp.c_name = "SomeCName";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002902
sprangcd349d92016-07-13 09:11:28 -07002903 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2904 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
2905
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002906 const std::vector<uint32_t>& ssrcs = send_config->rtp.ssrcs;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002907 for (size_t i = 0; i < ssrcs.size(); ++i) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002908 expected_send_ssrcs_.insert(ssrcs[i]);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002909 expected_receive_ssrcs_.push_back(
2910 (*receive_configs)[i].rtp.remote_ssrc);
Peter Boströmdef398832015-05-27 17:59:11 +02002911 (*receive_configs)[i].render_delay_ms = kExpectedRenderDelayMs;
tommi2e82f382016-06-21 00:26:43 -07002912 (*receive_configs)[i].renderer = &receive_stream_renderer_;
sprangcd349d92016-07-13 09:11:28 -07002913 (*receive_configs)[i].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
2914
2915 (*receive_configs)[i].rtp.rtx[kFakeVideoSendPayloadType].ssrc =
2916 kSendRtxSsrcs[i];
2917 (*receive_configs)[i].rtp.rtx[kFakeVideoSendPayloadType].payload_type =
2918 kSendRtxPayloadType;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002919 }
sprangcd349d92016-07-13 09:11:28 -07002920
2921 for (size_t i = 0; i < kNumSsrcs; ++i)
2922 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
2923
Peter Boströmc6e16e32016-02-05 14:15:53 +01002924 // Use a delayed encoder to make sure we see CpuOveruseMetrics stats that
2925 // are non-zero.
2926 send_config->encoder_settings.encoder = &encoder_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002927 }
2928
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002929 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.orgece38902014-11-14 11:52:04 +00002930
stefanff483612015-12-21 03:14:00 -08002931 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002932 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002933 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002934 send_stream_ = send_stream;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002935 receive_streams_ = receive_streams;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002936 }
2937
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002938 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002939 Clock* clock = Clock::GetRealTimeClock();
2940 int64_t now = clock->TimeInMilliseconds();
2941 int64_t stop_time = now + test::CallTest::kLongTimeoutMs;
2942 bool receive_ok = false;
2943 bool send_ok = false;
2944
2945 while (now < stop_time) {
2946 if (!receive_ok)
2947 receive_ok = CheckReceiveStats();
2948 if (!send_ok)
2949 send_ok = CheckSendStats();
2950
2951 if (receive_ok && send_ok)
2952 return;
2953
2954 int64_t time_until_timout_ = stop_time - now;
2955 if (time_until_timout_ > 0)
Peter Boström5811a392015-12-10 13:02:50 +01002956 check_stats_event_.Wait(time_until_timout_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002957 now = clock->TimeInMilliseconds();
2958 }
2959
2960 ADD_FAILURE() << "Timed out waiting for filled stats.";
2961 for (std::map<std::string, bool>::const_iterator it =
2962 receive_stats_filled_.begin();
2963 it != receive_stats_filled_.end();
2964 ++it) {
2965 if (!it->second) {
2966 ADD_FAILURE() << "Missing receive stats: " << it->first;
2967 }
2968 }
2969
2970 for (std::map<std::string, bool>::const_iterator it =
2971 send_stats_filled_.begin();
2972 it != send_stats_filled_.end();
2973 ++it) {
2974 if (!it->second) {
2975 ADD_FAILURE() << "Missing send stats: " << it->first;
2976 }
2977 }
2978 }
2979
Peter Boströmc6e16e32016-02-05 14:15:53 +01002980 test::DelayedEncoder encoder_;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002981 std::vector<VideoReceiveStream*> receive_streams_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002982 std::map<std::string, bool> receive_stats_filled_;
2983
2984 VideoSendStream* send_stream_;
2985 std::map<std::string, bool> send_stats_filled_;
2986
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002987 std::vector<uint32_t> expected_receive_ssrcs_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002988 std::set<uint32_t> expected_send_ssrcs_;
2989 std::string expected_cname_;
2990
Peter Boström5811a392015-12-10 13:02:50 +01002991 rtc::Event check_stats_event_;
tommi2e82f382016-06-21 00:26:43 -07002992 ReceiveStreamRenderer receive_stream_renderer_;
stefanf116bd02015-10-27 08:29:42 -07002993 } test;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002994
philipel266f0a42016-11-28 08:49:07 -08002995 // TODO(philipel): Implement statistics for the new video jitter buffer.
2996 if (GetParam() == new_jb_enabled)
2997 return;
2998
stefane74eef12016-01-08 06:47:13 -08002999 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003000}
3001
sprang1a646ee2016-12-01 06:34:11 -08003002class RtcpXrObserver : public test::EndToEndTest {
3003 public:
3004 explicit RtcpXrObserver(bool enable_rrtr)
3005 : EndToEndTest(test::CallTest::kDefaultTimeoutMs),
3006 enable_rrtr_(enable_rrtr),
3007 sent_rtcp_sr_(0),
3008 sent_rtcp_rr_(0),
3009 sent_rtcp_rrtr_(0),
3010 sent_rtcp_target_bitrate_(false),
3011 sent_rtcp_dlrr_(0) {}
3012
3013 private:
3014 // Receive stream should send RR packets (and RRTR packets if enabled).
3015 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
3016 rtc::CritScope lock(&crit_);
3017 test::RtcpPacketParser parser;
3018 EXPECT_TRUE(parser.Parse(packet, length));
3019
3020 sent_rtcp_rr_ += parser.receiver_report()->num_packets();
3021 EXPECT_EQ(0, parser.sender_report()->num_packets());
3022 EXPECT_GE(1, parser.xr()->num_packets());
3023 if (parser.xr()->num_packets() > 0) {
3024 if (parser.xr()->rrtr())
3025 ++sent_rtcp_rrtr_;
3026 EXPECT_FALSE(parser.xr()->dlrr());
3027 }
3028
3029 return SEND_PACKET;
3030 }
3031 // Send stream should send SR packets (and DLRR packets if enabled).
3032 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
3033 rtc::CritScope lock(&crit_);
3034 test::RtcpPacketParser parser;
3035 EXPECT_TRUE(parser.Parse(packet, length));
3036
3037 sent_rtcp_sr_ += parser.sender_report()->num_packets();
3038 EXPECT_LE(parser.xr()->num_packets(), 1);
3039 if (parser.xr()->num_packets() > 0) {
3040 EXPECT_FALSE(parser.xr()->rrtr());
3041 if (parser.xr()->dlrr())
3042 ++sent_rtcp_dlrr_;
3043 if (parser.xr()->target_bitrate())
3044 sent_rtcp_target_bitrate_ = true;
3045 }
3046
3047 if (sent_rtcp_sr_ > kNumRtcpReportPacketsToObserve &&
3048 sent_rtcp_rr_ > kNumRtcpReportPacketsToObserve &&
3049 sent_rtcp_target_bitrate_) {
3050 if (enable_rrtr_) {
3051 EXPECT_GT(sent_rtcp_rrtr_, 0);
3052 EXPECT_GT(sent_rtcp_dlrr_, 0);
3053 } else {
3054 EXPECT_EQ(sent_rtcp_rrtr_, 0);
3055 EXPECT_EQ(sent_rtcp_dlrr_, 0);
3056 }
3057 observation_complete_.Set();
3058 }
3059 return SEND_PACKET;
3060 }
3061
3062 void ModifyVideoConfigs(
3063 VideoSendStream::Config* send_config,
3064 std::vector<VideoReceiveStream::Config>* receive_configs,
3065 VideoEncoderConfig* encoder_config) override {
3066 (*receive_configs)[0].rtp.rtcp_mode = RtcpMode::kReducedSize;
3067 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report =
3068 enable_rrtr_;
3069 }
3070
3071 void PerformTest() override {
3072 EXPECT_TRUE(Wait())
3073 << "Timed out while waiting for RTCP SR/RR packets to be sent.";
3074 }
3075
3076 static const int kNumRtcpReportPacketsToObserve = 5;
3077
3078 rtc::CriticalSection crit_;
3079 bool enable_rrtr_;
3080 int sent_rtcp_sr_;
3081 int sent_rtcp_rr_ GUARDED_BY(&crit_);
3082 int sent_rtcp_rrtr_ GUARDED_BY(&crit_);
3083 bool sent_rtcp_target_bitrate_ GUARDED_BY(&crit_);
3084 int sent_rtcp_dlrr_;
3085};
3086
3087TEST_P(EndToEndTest, TestExtendedReportsWithRrtr) {
3088 RtcpXrObserver test(true);
3089 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003090}
3091
sprang1a646ee2016-12-01 06:34:11 -08003092TEST_P(EndToEndTest, TestExtendedReportsWithoutRrtr) {
3093 RtcpXrObserver test(false);
3094 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003095}
3096
philipel266f0a42016-11-28 08:49:07 -08003097TEST_P(EndToEndTest, TestReceivedRtpPacketStats) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003098 static const size_t kNumRtpPacketsToSend = 5;
3099 class ReceivedRtpStatsObserver : public test::EndToEndTest {
3100 public:
3101 ReceivedRtpStatsObserver()
3102 : EndToEndTest(kDefaultTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00003103 receive_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003104 sent_rtp_(0) {}
3105
3106 private:
stefanff483612015-12-21 03:14:00 -08003107 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003108 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00003109 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003110 receive_stream_ = receive_streams[0];
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003111 }
3112
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003113 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003114 if (sent_rtp_ >= kNumRtpPacketsToSend) {
3115 VideoReceiveStream::Stats stats = receive_stream_->GetStats();
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00003116 if (kNumRtpPacketsToSend == stats.rtp_stats.transmitted.packets) {
Peter Boström5811a392015-12-10 13:02:50 +01003117 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003118 }
3119 return DROP_PACKET;
3120 }
3121 ++sent_rtp_;
3122 return SEND_PACKET;
3123 }
3124
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003125 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003126 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003127 << "Timed out while verifying number of received RTP packets.";
3128 }
3129
3130 VideoReceiveStream* receive_stream_;
3131 uint32_t sent_rtp_;
3132 } test;
3133
stefane74eef12016-01-08 06:47:13 -08003134 RunBaseTest(&test);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00003135}
3136
philipel266f0a42016-11-28 08:49:07 -08003137TEST_P(EndToEndTest, SendsSetSsrc) {
3138 TestSendsSetSsrcs(1, false);
3139}
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003140
philipel266f0a42016-11-28 08:49:07 -08003141TEST_P(EndToEndTest, SendsSetSimulcastSsrcs) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003142 TestSendsSetSsrcs(kNumSsrcs, false);
3143}
3144
philipel266f0a42016-11-28 08:49:07 -08003145TEST_P(EndToEndTest, CanSwitchToUseAllSsrcs) {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00003146 TestSendsSetSsrcs(kNumSsrcs, true);
3147}
3148
philipel266f0a42016-11-28 08:49:07 -08003149TEST_P(EndToEndTest, DISABLED_RedundantPayloadsTransmittedOnAllSsrcs) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003150 class ObserveRedundantPayloads: public test::EndToEndTest {
3151 public:
3152 ObserveRedundantPayloads()
3153 : EndToEndTest(kDefaultTimeoutMs), ssrcs_to_observe_(kNumSsrcs) {
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00003154 for (size_t i = 0; i < kNumSsrcs; ++i) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003155 registered_rtx_ssrc_[kSendRtxSsrcs[i]] = true;
3156 }
3157 }
3158
3159 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003160 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003161 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00003162 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003163
3164 if (!registered_rtx_ssrc_[header.ssrc])
3165 return SEND_PACKET;
3166
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00003167 EXPECT_LE(header.headerLength + header.paddingLength, length);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003168 const bool packet_is_redundant_payload =
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00003169 header.headerLength + header.paddingLength < length;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003170
3171 if (!packet_is_redundant_payload)
3172 return SEND_PACKET;
3173
3174 if (!observed_redundant_retransmission_[header.ssrc]) {
3175 observed_redundant_retransmission_[header.ssrc] = true;
3176 if (--ssrcs_to_observe_ == 0)
Peter Boström5811a392015-12-10 13:02:50 +01003177 observation_complete_.Set();
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003178 }
3179
3180 return SEND_PACKET;
3181 }
3182
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003183 size_t GetNumVideoStreams() const override { return kNumSsrcs; }
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003184
perkjfa10b552016-10-02 23:45:26 -07003185 // This test use other VideoStream settings than the the default settings
3186 // implemented in DefaultVideoStreamFactory. Therefore this test implement
3187 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
3188 // in ModifyVideoConfigs.
3189 class VideoStreamFactory
3190 : public VideoEncoderConfig::VideoStreamFactoryInterface {
3191 public:
3192 VideoStreamFactory() {}
3193
3194 private:
3195 std::vector<VideoStream> CreateEncoderStreams(
3196 int width,
3197 int height,
3198 const VideoEncoderConfig& encoder_config) override {
3199 std::vector<VideoStream> streams =
3200 test::CreateVideoStreams(width, height, encoder_config);
3201 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
3202 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
3203 streams[i].min_bitrate_bps = 10000;
3204 streams[i].target_bitrate_bps = 15000;
3205 streams[i].max_bitrate_bps = 20000;
3206 }
3207 return streams;
3208 }
3209 };
3210
stefanff483612015-12-21 03:14:00 -08003211 void ModifyVideoConfigs(
3212 VideoSendStream::Config* send_config,
3213 std::vector<VideoReceiveStream::Config>* receive_configs,
3214 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003215 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
perkjfa10b552016-10-02 23:45:26 -07003216 encoder_config->video_stream_factory =
3217 new rtc::RefCountedObject<VideoStreamFactory>();
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003218 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003219
3220 for (size_t i = 0; i < kNumSsrcs; ++i)
3221 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.orgad3b5a52014-10-24 09:23:21 +00003222
3223 // Significantly higher than max bitrates for all video streams -> forcing
3224 // padding to trigger redundant padding on all RTX SSRCs.
3225 encoder_config->min_transmit_bitrate_bps = 100000;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003226 }
3227
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003228 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003229 EXPECT_TRUE(Wait())
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003230 << "Timed out while waiting for redundant payloads on all SSRCs.";
3231 }
3232
3233 private:
3234 size_t ssrcs_to_observe_;
3235 std::map<uint32_t, bool> observed_redundant_retransmission_;
3236 std::map<uint32_t, bool> registered_rtx_ssrc_;
3237 } test;
3238
stefane74eef12016-01-08 06:47:13 -08003239 RunBaseTest(&test);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00003240}
3241
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003242void EndToEndTest::TestRtpStatePreservation(bool use_rtx,
3243 bool provoke_rtcpsr_before_rtp) {
perkjfa10b552016-10-02 23:45:26 -07003244 // This test use other VideoStream settings than the the default settings
3245 // implemented in DefaultVideoStreamFactory. Therefore this test implement
3246 // its own VideoEncoderConfig::VideoStreamFactoryInterface which is created
3247 // in ModifyVideoConfigs.
3248 class VideoStreamFactory
3249 : public VideoEncoderConfig::VideoStreamFactoryInterface {
3250 public:
3251 VideoStreamFactory() {}
3252
3253 private:
3254 std::vector<VideoStream> CreateEncoderStreams(
3255 int width,
3256 int height,
3257 const VideoEncoderConfig& encoder_config) override {
3258 std::vector<VideoStream> streams =
3259 test::CreateVideoStreams(width, height, encoder_config);
3260
3261 if (encoder_config.number_of_streams > 1) {
3262 // Lower bitrates so that all streams send initially.
kwibergaf476c72016-11-28 15:21:39 -08003263 RTC_DCHECK_EQ(3, encoder_config.number_of_streams);
perkjfa10b552016-10-02 23:45:26 -07003264 for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
3265 streams[i].min_bitrate_bps = 10000;
3266 streams[i].target_bitrate_bps = 15000;
3267 streams[i].max_bitrate_bps = 20000;
3268 }
3269 } else {
3270 // Use the same total bitrates when sending a single stream to avoid
3271 // lowering
3272 // the bitrate estimate and requiring a subsequent rampup.
3273 streams[0].min_bitrate_bps = 3 * 10000;
3274 streams[0].target_bitrate_bps = 3 * 15000;
3275 streams[0].max_bitrate_bps = 3 * 20000;
3276 }
3277 return streams;
3278 }
3279 };
3280
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003281 class RtpSequenceObserver : public test::RtpRtcpObserver {
3282 public:
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00003283 explicit RtpSequenceObserver(bool use_rtx)
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003284 : test::RtpRtcpObserver(kDefaultTimeoutMs),
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003285 ssrcs_to_observe_(kNumSsrcs) {
3286 for (size_t i = 0; i < kNumSsrcs; ++i) {
danilchap32cd2c42016-08-01 06:58:34 -07003287 ssrc_is_rtx_[kVideoSendSsrcs[i]] = false;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003288 if (use_rtx)
danilchap32cd2c42016-08-01 06:58:34 -07003289 ssrc_is_rtx_[kSendRtxSsrcs[i]] = true;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003290 }
3291 }
3292
3293 void ResetExpectedSsrcs(size_t num_expected_ssrcs) {
Peter Boströmf2f82832015-05-01 13:00:41 +02003294 rtc::CritScope lock(&crit_);
danilchap34877ee2016-02-01 08:25:04 -08003295 ssrc_observed_.clear();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003296 ssrcs_to_observe_ = num_expected_ssrcs;
3297 }
3298
3299 private:
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003300 void ValidateTimestampGap(uint32_t ssrc,
3301 uint32_t timestamp,
3302 bool only_padding)
3303 EXCLUSIVE_LOCKS_REQUIRED(crit_) {
3304 static const int32_t kMaxTimestampGap = kDefaultTimeoutMs * 90;
3305 auto timestamp_it = last_observed_timestamp_.find(ssrc);
3306 if (timestamp_it == last_observed_timestamp_.end()) {
3307 EXPECT_FALSE(only_padding);
3308 last_observed_timestamp_[ssrc] = timestamp;
3309 } else {
3310 // Verify timestamps are reasonably close.
3311 uint32_t latest_observed = timestamp_it->second;
3312 // Wraparound handling is unnecessary here as long as an int variable
3313 // is used to store the result.
3314 int32_t timestamp_gap = timestamp - latest_observed;
3315 EXPECT_LE(std::abs(timestamp_gap), kMaxTimestampGap)
3316 << "Gap in timestamps (" << latest_observed << " -> " << timestamp
3317 << ") too large for SSRC: " << ssrc << ".";
3318 timestamp_it->second = timestamp;
3319 }
3320 }
3321
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003322 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003323 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00003324 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003325 const uint32_t ssrc = header.ssrc;
danilchap5c35cf92016-02-03 14:14:49 -08003326 const int64_t sequence_number =
3327 seq_numbers_unwrapper_.Unwrap(header.sequenceNumber);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003328 const uint32_t timestamp = header.timestamp;
danilchap34877ee2016-02-01 08:25:04 -08003329 const bool only_padding =
3330 header.headerLength + header.paddingLength == length;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003331
danilchap32cd2c42016-08-01 06:58:34 -07003332 EXPECT_TRUE(ssrc_is_rtx_.find(ssrc) != ssrc_is_rtx_.end())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003333 << "Received SSRC that wasn't configured: " << ssrc;
3334
danilchap5c35cf92016-02-03 14:14:49 -08003335 static const int64_t kMaxSequenceNumberGap = 100;
3336 std::list<int64_t>* seq_numbers = &last_observed_seq_numbers_[ssrc];
3337 if (seq_numbers->empty()) {
3338 seq_numbers->push_back(sequence_number);
3339 } else {
3340 // We shouldn't get replays of previous sequence numbers.
3341 for (int64_t observed : *seq_numbers) {
3342 EXPECT_NE(observed, sequence_number)
3343 << "Received sequence number " << sequence_number
3344 << " for SSRC " << ssrc << " 2nd time.";
3345 }
3346 // Verify sequence numbers are reasonably close.
3347 int64_t latest_observed = seq_numbers->back();
3348 int64_t sequence_number_gap = sequence_number - latest_observed;
3349 EXPECT_LE(std::abs(sequence_number_gap), kMaxSequenceNumberGap)
3350 << "Gap in sequence numbers (" << latest_observed << " -> "
3351 << sequence_number << ") too large for SSRC: " << ssrc << ".";
3352 seq_numbers->push_back(sequence_number);
3353 if (seq_numbers->size() >= kMaxSequenceNumberGap) {
3354 seq_numbers->pop_front();
3355 }
3356 }
3357
danilchap32cd2c42016-08-01 06:58:34 -07003358 if (!ssrc_is_rtx_[ssrc]) {
3359 rtc::CritScope lock(&crit_);
3360 ValidateTimestampGap(ssrc, timestamp, only_padding);
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003361
danilchap32cd2c42016-08-01 06:58:34 -07003362 // Wait for media packets on all ssrcs.
3363 if (!ssrc_observed_[ssrc] && !only_padding) {
3364 ssrc_observed_[ssrc] = true;
3365 if (--ssrcs_to_observe_ == 0)
3366 observation_complete_.Set();
3367 }
danilchap34877ee2016-02-01 08:25:04 -08003368 }
3369
danilchapf4b9c772016-01-28 06:14:24 -08003370 return SEND_PACKET;
3371 }
3372
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003373 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
3374 test::RtcpPacketParser rtcp_parser;
3375 rtcp_parser.Parse(packet, length);
3376 if (rtcp_parser.sender_report()->num_packets() > 0) {
Danil Chapovalovba6f7be2016-09-02 18:29:10 +02003377 uint32_t ssrc = rtcp_parser.sender_report()->sender_ssrc();
3378 uint32_t rtcp_timestamp = rtcp_parser.sender_report()->rtp_timestamp();
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003379
3380 rtc::CritScope lock(&crit_);
3381 ValidateTimestampGap(ssrc, rtcp_timestamp, false);
3382 }
3383 return SEND_PACKET;
3384 }
3385
danilchap5c35cf92016-02-03 14:14:49 -08003386 SequenceNumberUnwrapper seq_numbers_unwrapper_;
3387 std::map<uint32_t, std::list<int64_t>> last_observed_seq_numbers_;
danilchap34877ee2016-02-01 08:25:04 -08003388 std::map<uint32_t, uint32_t> last_observed_timestamp_;
danilchap32cd2c42016-08-01 06:58:34 -07003389 std::map<uint32_t, bool> ssrc_is_rtx_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003390
Peter Boströmf2f82832015-05-01 13:00:41 +02003391 rtc::CriticalSection crit_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003392 size_t ssrcs_to_observe_ GUARDED_BY(crit_);
danilchap34877ee2016-02-01 08:25:04 -08003393 std::map<uint32_t, bool> ssrc_observed_ GUARDED_BY(crit_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003394 } observer(use_rtx);
3395
skvlad11a9cbf2016-10-07 11:53:05 -07003396 Call::Config config(&event_log_);
3397 CreateCalls(config, config);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003398
stefanf116bd02015-10-27 08:29:42 -07003399 test::PacketTransport send_transport(sender_call_.get(), &observer,
3400 test::PacketTransport::kSender,
3401 FakeNetworkPipe::Config());
3402 test::PacketTransport receive_transport(nullptr, &observer,
3403 test::PacketTransport::kReceiver,
3404 FakeNetworkPipe::Config());
3405 send_transport.SetReceiver(receiver_call_->Receiver());
3406 receive_transport.SetReceiver(sender_call_->Receiver());
3407
brandtr841de6a2016-11-15 07:10:52 -08003408 CreateSendConfig(kNumSsrcs, 0, 0, &send_transport);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003409
3410 if (use_rtx) {
3411 for (size_t i = 0; i < kNumSsrcs; ++i) {
stefanff483612015-12-21 03:14:00 -08003412 video_send_config_.rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003413 }
stefanff483612015-12-21 03:14:00 -08003414 video_send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003415 }
3416
perkjfa10b552016-10-02 23:45:26 -07003417 video_encoder_config_.video_stream_factory =
3418 new rtc::RefCountedObject<VideoStreamFactory>();
pbos@webrtc.org32452b22014-10-22 12:15:24 +00003419 // Use the same total bitrates when sending a single stream to avoid lowering
3420 // the bitrate estimate and requiring a subsequent rampup.
perkj26091b12016-09-01 01:17:40 -07003421 VideoEncoderConfig one_stream = video_encoder_config_.Copy();
perkjfa10b552016-10-02 23:45:26 -07003422 // one_stream.streams.resize(1);
3423 one_stream.number_of_streams = 1;
stefanf116bd02015-10-27 08:29:42 -07003424 CreateMatchingReceiveConfigs(&receive_transport);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003425
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003426 CreateVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07003427 CreateFrameGeneratorCapturer(30, 1280, 720);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003428
3429 Start();
Peter Boström5811a392015-12-10 13:02:50 +01003430 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003431 << "Timed out waiting for all SSRCs to send packets.";
3432
3433 // Test stream resetting more than once to make sure that the state doesn't
3434 // get set once (this could be due to using std::map::insert for instance).
3435 for (size_t i = 0; i < 3; ++i) {
3436 frame_generator_capturer_->Stop();
stefanff483612015-12-21 03:14:00 -08003437 sender_call_->DestroyVideoSendStream(video_send_stream_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003438
3439 // Re-create VideoSendStream with only one stream.
perkj26091b12016-09-01 01:17:40 -07003440 video_send_stream_ = sender_call_->CreateVideoSendStream(
3441 video_send_config_.Copy(), one_stream.Copy());
stefanff483612015-12-21 03:14:00 -08003442 video_send_stream_->Start();
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003443 if (provoke_rtcpsr_before_rtp) {
3444 // Rapid Resync Request forces sending RTCP Sender Report back.
3445 // Using this request speeds up this test because then there is no need
3446 // to wait for a second for periodic Sender Report.
3447 rtcp::RapidResyncRequest force_send_sr_back_request;
3448 rtc::Buffer packet = force_send_sr_back_request.Build();
3449 static_cast<webrtc::test::DirectTransport&>(receive_transport)
3450 .SendRtcp(packet.data(), packet.size());
3451 }
perkjfa10b552016-10-02 23:45:26 -07003452 CreateFrameGeneratorCapturer(30, 1280, 720);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003453 frame_generator_capturer_->Start();
3454
3455 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01003456 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003457
3458 // Reconfigure back to use all streams.
perkj26091b12016-09-01 01:17:40 -07003459 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_.Copy());
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003460 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01003461 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003462 << "Timed out waiting for all SSRCs to send packets.";
3463
3464 // Reconfigure down to one stream.
perkj26091b12016-09-01 01:17:40 -07003465 video_send_stream_->ReconfigureVideoEncoder(one_stream.Copy());
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003466 observer.ResetExpectedSsrcs(1);
Peter Boström5811a392015-12-10 13:02:50 +01003467 EXPECT_TRUE(observer.Wait()) << "Timed out waiting for single RTP packet.";
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003468
3469 // Reconfigure back to use all streams.
perkj26091b12016-09-01 01:17:40 -07003470 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_.Copy());
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003471 observer.ResetExpectedSsrcs(kNumSsrcs);
Peter Boström5811a392015-12-10 13:02:50 +01003472 EXPECT_TRUE(observer.Wait())
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003473 << "Timed out waiting for all SSRCs to send packets.";
3474 }
3475
stefanf116bd02015-10-27 08:29:42 -07003476 send_transport.StopSending();
3477 receive_transport.StopSending();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003478
3479 Stop();
3480 DestroyStreams();
3481}
3482
philipel266f0a42016-11-28 08:49:07 -08003483TEST_P(EndToEndTest, RestartingSendStreamPreservesRtpState) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003484 TestRtpStatePreservation(false, false);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003485}
3486
philipel266f0a42016-11-28 08:49:07 -08003487TEST_P(EndToEndTest, RestartingSendStreamPreservesRtpStatesWithRtx) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003488 TestRtpStatePreservation(true, false);
3489}
3490
philipel266f0a42016-11-28 08:49:07 -08003491TEST_P(EndToEndTest, RestartingSendStreamKeepsRtpAndRtcpTimestampsSynced) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +02003492 TestRtpStatePreservation(true, true);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00003493}
3494
philipel266f0a42016-11-28 08:49:07 -08003495TEST_P(EndToEndTest, RespectsNetworkState) {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003496 // TODO(pbos): Remove accepted downtime packets etc. when signaling network
3497 // down blocks until no more packets will be sent.
3498
3499 // Pacer will send from its packet list and then send required padding before
3500 // checking paused_ again. This should be enough for one round of pacing,
3501 // otherwise increase.
3502 static const int kNumAcceptedDowntimeRtp = 5;
3503 // A single RTCP may be in the pipeline.
3504 static const int kNumAcceptedDowntimeRtcp = 1;
3505 class NetworkStateTest : public test::EndToEndTest, public test::FakeEncoder {
3506 public:
3507 NetworkStateTest()
3508 : EndToEndTest(kDefaultTimeoutMs),
3509 FakeEncoder(Clock::GetRealTimeClock()),
Peter Boström5811a392015-12-10 13:02:50 +01003510 encoded_frames_(false, false),
3511 packet_event_(false, false),
sprang867fb522015-08-03 04:38:41 -07003512 sender_call_(nullptr),
3513 receiver_call_(nullptr),
Jelena Marusiccd670222015-07-16 09:30:09 +02003514 sender_state_(kNetworkUp),
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003515 sender_rtp_(0),
3516 sender_rtcp_(0),
3517 receiver_rtcp_(0),
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003518 down_frames_(0) {}
3519
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003520 Action OnSendRtp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003521 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003522 ++sender_rtp_;
Peter Boström5811a392015-12-10 13:02:50 +01003523 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003524 return SEND_PACKET;
3525 }
3526
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003527 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003528 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003529 ++sender_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01003530 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003531 return SEND_PACKET;
3532 }
3533
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003534 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003535 ADD_FAILURE() << "Unexpected receiver RTP, should not be sending.";
3536 return SEND_PACKET;
3537 }
3538
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003539 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02003540 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003541 ++receiver_rtcp_;
Peter Boström5811a392015-12-10 13:02:50 +01003542 packet_event_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003543 return SEND_PACKET;
3544 }
3545
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003546 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003547 sender_call_ = sender_call;
3548 receiver_call_ = receiver_call;
3549 }
3550
stefanff483612015-12-21 03:14:00 -08003551 void ModifyVideoConfigs(
3552 VideoSendStream::Config* send_config,
3553 std::vector<VideoReceiveStream::Config>* receive_configs,
3554 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003555 send_config->encoder_settings.encoder = this;
3556 }
3557
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003558 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01003559 EXPECT_TRUE(encoded_frames_.Wait(kDefaultTimeoutMs))
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003560 << "No frames received by the encoder.";
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003561 // Wait for packets from both sender/receiver.
3562 WaitForPacketsOrSilence(false, false);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003563
skvlad7a43d252016-03-22 15:32:27 -07003564 // Sender-side network down for audio; there should be no effect on video
3565 sender_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkDown);
3566 WaitForPacketsOrSilence(false, false);
3567
3568 // Receiver-side network down for audio; no change expected
3569 receiver_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkDown);
3570 WaitForPacketsOrSilence(false, false);
3571
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003572 // Sender-side network down.
skvlad7a43d252016-03-22 15:32:27 -07003573 sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkDown);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003574 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003575 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003576 // After network goes down we shouldn't be encoding more frames.
Jelena Marusiccd670222015-07-16 09:30:09 +02003577 sender_state_ = kNetworkDown;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003578 }
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003579 // Wait for receiver-packets and no sender packets.
3580 WaitForPacketsOrSilence(true, false);
3581
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003582 // Receiver-side network down.
skvlad7a43d252016-03-22 15:32:27 -07003583 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkDown);
3584 WaitForPacketsOrSilence(true, true);
3585
3586 // Network up for audio for both sides; video is still not expected to
3587 // start
3588 sender_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkUp);
3589 receiver_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkUp);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003590 WaitForPacketsOrSilence(true, true);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003591
3592 // Network back up again for both.
3593 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003594 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003595 // It's OK to encode frames again, as we're about to bring up the
3596 // network.
Jelena Marusiccd670222015-07-16 09:30:09 +02003597 sender_state_ = kNetworkUp;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003598 }
skvlad7a43d252016-03-22 15:32:27 -07003599 sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
3600 receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003601 WaitForPacketsOrSilence(false, false);
skvlad7a43d252016-03-22 15:32:27 -07003602
3603 // TODO(skvlad): add tests to verify that the audio streams are stopped
3604 // when the network goes down for audio once the workaround in
3605 // paced_sender.cc is removed.
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003606 }
3607
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07003608 int32_t Encode(const VideoFrame& input_image,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00003609 const CodecSpecificInfo* codec_specific_info,
pbos22993e12015-10-19 02:39:06 -07003610 const std::vector<FrameType>* frame_types) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003611 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003612 rtc::CritScope lock(&test_crit_);
Jelena Marusiccd670222015-07-16 09:30:09 +02003613 if (sender_state_ == kNetworkDown) {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003614 ++down_frames_;
3615 EXPECT_LE(down_frames_, 1)
3616 << "Encoding more than one frame while network is down.";
3617 if (down_frames_ > 1)
Peter Boström5811a392015-12-10 13:02:50 +01003618 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003619 } else {
Peter Boström5811a392015-12-10 13:02:50 +01003620 encoded_frames_.Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003621 }
3622 }
3623 return test::FakeEncoder::Encode(
3624 input_image, codec_specific_info, frame_types);
3625 }
3626
3627 private:
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003628 void WaitForPacketsOrSilence(bool sender_down, bool receiver_down) {
3629 int64_t initial_time_ms = clock_->TimeInMilliseconds();
3630 int initial_sender_rtp;
3631 int initial_sender_rtcp;
3632 int initial_receiver_rtcp;
3633 {
Peter Boströmf2f82832015-05-01 13:00:41 +02003634 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003635 initial_sender_rtp = sender_rtp_;
3636 initial_sender_rtcp = sender_rtcp_;
3637 initial_receiver_rtcp = receiver_rtcp_;
3638 }
3639 bool sender_done = false;
3640 bool receiver_done = false;
mflodmand1590b22015-12-09 07:07:59 -08003641 while (!sender_done || !receiver_done) {
Peter Boström5811a392015-12-10 13:02:50 +01003642 packet_event_.Wait(kSilenceTimeoutMs);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003643 int64_t time_now_ms = clock_->TimeInMilliseconds();
Peter Boströmf2f82832015-05-01 13:00:41 +02003644 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003645 if (sender_down) {
3646 ASSERT_LE(sender_rtp_ - initial_sender_rtp, kNumAcceptedDowntimeRtp)
3647 << "RTP sent during sender-side downtime.";
3648 ASSERT_LE(sender_rtcp_ - initial_sender_rtcp,
3649 kNumAcceptedDowntimeRtcp)
3650 << "RTCP sent during sender-side downtime.";
3651 if (time_now_ms - initial_time_ms >=
3652 static_cast<int64_t>(kSilenceTimeoutMs)) {
3653 sender_done = true;
3654 }
3655 } else {
skvlad7a43d252016-03-22 15:32:27 -07003656 if (sender_rtp_ > initial_sender_rtp + kNumAcceptedDowntimeRtp)
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003657 sender_done = true;
3658 }
3659 if (receiver_down) {
3660 ASSERT_LE(receiver_rtcp_ - initial_receiver_rtcp,
3661 kNumAcceptedDowntimeRtcp)
3662 << "RTCP sent during receiver-side downtime.";
3663 if (time_now_ms - initial_time_ms >=
3664 static_cast<int64_t>(kSilenceTimeoutMs)) {
3665 receiver_done = true;
3666 }
3667 } else {
skvlad7a43d252016-03-22 15:32:27 -07003668 if (receiver_rtcp_ > initial_receiver_rtcp + kNumAcceptedDowntimeRtcp)
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003669 receiver_done = true;
3670 }
3671 }
3672 }
3673
Peter Boströmf2f82832015-05-01 13:00:41 +02003674 rtc::CriticalSection test_crit_;
Peter Boström5811a392015-12-10 13:02:50 +01003675 rtc::Event encoded_frames_;
3676 rtc::Event packet_event_;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003677 Call* sender_call_;
3678 Call* receiver_call_;
Jelena Marusiccd670222015-07-16 09:30:09 +02003679 NetworkState sender_state_ GUARDED_BY(test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00003680 int sender_rtp_ GUARDED_BY(test_crit_);
3681 int sender_rtcp_ GUARDED_BY(test_crit_);
3682 int receiver_rtcp_ GUARDED_BY(test_crit_);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003683 int down_frames_ GUARDED_BY(test_crit_);
3684 } test;
3685
stefane74eef12016-01-08 06:47:13 -08003686 RunBaseTest(&test);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003687}
3688
philipel266f0a42016-11-28 08:49:07 -08003689TEST_P(EndToEndTest, CallReportsRttForSender) {
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003690 static const int kSendDelayMs = 30;
3691 static const int kReceiveDelayMs = 70;
skvlad11a9cbf2016-10-07 11:53:05 -07003692 CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_));
solenberg4fbae2b2015-08-28 04:07:10 -07003693
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003694 FakeNetworkPipe::Config config;
3695 config.queue_delay_ms = kSendDelayMs;
stefanf116bd02015-10-27 08:29:42 -07003696 test::DirectTransport sender_transport(config, sender_call_.get());
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003697 config.queue_delay_ms = kReceiveDelayMs;
stefanf116bd02015-10-27 08:29:42 -07003698 test::DirectTransport receiver_transport(config, receiver_call_.get());
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003699 sender_transport.SetReceiver(receiver_call_->Receiver());
3700 receiver_transport.SetReceiver(sender_call_->Receiver());
3701
brandtr841de6a2016-11-15 07:10:52 -08003702 CreateSendConfig(1, 0, 0, &sender_transport);
solenberg4fbae2b2015-08-28 04:07:10 -07003703 CreateMatchingReceiveConfigs(&receiver_transport);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003704
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003705 CreateVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07003706 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
3707 kDefaultHeight);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003708 Start();
3709
3710 int64_t start_time_ms = clock_->TimeInMilliseconds();
3711 while (true) {
3712 Call::Stats stats = sender_call_->GetStats();
3713 ASSERT_GE(start_time_ms + kDefaultTimeoutMs,
3714 clock_->TimeInMilliseconds())
3715 << "No RTT stats before timeout!";
3716 if (stats.rtt_ms != -1) {
Danil Chapovalov10e8f8e2016-09-07 15:05:29 +02003717 // To avoid failures caused by rounding or minor ntp clock adjustments,
3718 // relax expectation by 1ms.
3719 constexpr int kAllowedErrorMs = 1;
3720 EXPECT_GE(stats.rtt_ms, kSendDelayMs + kReceiveDelayMs - kAllowedErrorMs);
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003721 break;
3722 }
3723 SleepMs(10);
3724 }
3725
philipel266f0a42016-11-28 08:49:07 -08003726 sender_transport.StopSending();
3727 receiver_transport.StopSending();
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003728 Stop();
3729 DestroyStreams();
philipel266f0a42016-11-28 08:49:07 -08003730 DestroyCalls();
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003731}
3732
skvlad7a43d252016-03-22 15:32:27 -07003733void EndToEndTest::VerifyNewVideoSendStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -08003734 MediaType network_to_bring_up,
skvlad7a43d252016-03-22 15:32:27 -07003735 VideoEncoder* encoder,
3736 Transport* transport) {
skvlad11a9cbf2016-10-07 11:53:05 -07003737 CreateSenderCall(Call::Config(&event_log_));
Sergey Ulanove2b15012016-11-22 16:08:30 -08003738 sender_call_->SignalChannelNetworkState(network_to_bring_up, kNetworkUp);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003739
brandtr841de6a2016-11-15 07:10:52 -08003740 CreateSendConfig(1, 0, 0, transport);
skvlad7a43d252016-03-22 15:32:27 -07003741 video_send_config_.encoder_settings.encoder = encoder;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003742 CreateVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07003743 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
3744 kDefaultHeight);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003745
3746 Start();
3747 SleepMs(kSilenceTimeoutMs);
3748 Stop();
3749
3750 DestroyStreams();
3751}
3752
skvlad7a43d252016-03-22 15:32:27 -07003753void EndToEndTest::VerifyNewVideoReceiveStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -08003754 MediaType network_to_bring_up,
skvlad7a43d252016-03-22 15:32:27 -07003755 Transport* transport) {
skvlad11a9cbf2016-10-07 11:53:05 -07003756 Call::Config config(&event_log_);
3757 CreateCalls(config, config);
Sergey Ulanove2b15012016-11-22 16:08:30 -08003758 receiver_call_->SignalChannelNetworkState(network_to_bring_up, kNetworkUp);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003759
stefanf116bd02015-10-27 08:29:42 -07003760 test::DirectTransport sender_transport(sender_call_.get());
solenberg4fbae2b2015-08-28 04:07:10 -07003761 sender_transport.SetReceiver(receiver_call_->Receiver());
brandtr841de6a2016-11-15 07:10:52 -08003762 CreateSendConfig(1, 0, 0, &sender_transport);
skvlad7a43d252016-03-22 15:32:27 -07003763 CreateMatchingReceiveConfigs(transport);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003764 CreateVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07003765 CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
3766 kDefaultHeight);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003767
3768 Start();
3769 SleepMs(kSilenceTimeoutMs);
3770 Stop();
3771
3772 sender_transport.StopSending();
3773
3774 DestroyStreams();
3775}
pbos@webrtc.org09cc6862014-11-04 13:48:15 +00003776
philipel266f0a42016-11-28 08:49:07 -08003777TEST_P(EndToEndTest, NewVideoSendStreamsRespectVideoNetworkDown) {
skvlad7a43d252016-03-22 15:32:27 -07003778 class UnusedEncoder : public test::FakeEncoder {
3779 public:
3780 UnusedEncoder() : FakeEncoder(Clock::GetRealTimeClock()) {}
perkjfea93092016-05-14 00:58:48 -07003781
3782 int32_t InitEncode(const VideoCodec* config,
3783 int32_t number_of_cores,
3784 size_t max_payload_size) override {
3785 EXPECT_GT(config->startBitrate, 0u);
3786 return 0;
3787 }
skvlad7a43d252016-03-22 15:32:27 -07003788 int32_t Encode(const VideoFrame& input_image,
3789 const CodecSpecificInfo* codec_specific_info,
3790 const std::vector<FrameType>* frame_types) override {
3791 ADD_FAILURE() << "Unexpected frame encode.";
3792 return test::FakeEncoder::Encode(input_image, codec_specific_info,
3793 frame_types);
3794 }
3795 };
3796
3797 UnusedEncoder unused_encoder;
3798 UnusedTransport unused_transport;
3799 VerifyNewVideoSendStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -08003800 MediaType::AUDIO, &unused_encoder, &unused_transport);
skvlad7a43d252016-03-22 15:32:27 -07003801}
3802
philipel266f0a42016-11-28 08:49:07 -08003803TEST_P(EndToEndTest, NewVideoSendStreamsIgnoreAudioNetworkDown) {
skvlad7a43d252016-03-22 15:32:27 -07003804 class RequiredEncoder : public test::FakeEncoder {
3805 public:
3806 RequiredEncoder()
3807 : FakeEncoder(Clock::GetRealTimeClock()), encoded_frame_(false) {}
3808 ~RequiredEncoder() {
3809 if (!encoded_frame_) {
3810 ADD_FAILURE() << "Didn't encode an expected frame";
3811 }
3812 }
3813 int32_t Encode(const VideoFrame& input_image,
3814 const CodecSpecificInfo* codec_specific_info,
3815 const std::vector<FrameType>* frame_types) override {
3816 encoded_frame_ = true;
3817 return test::FakeEncoder::Encode(input_image, codec_specific_info,
3818 frame_types);
3819 }
3820
3821 private:
3822 bool encoded_frame_;
3823 };
3824
3825 RequiredTransport required_transport(true /*rtp*/, false /*rtcp*/);
3826 RequiredEncoder required_encoder;
3827 VerifyNewVideoSendStreamsRespectNetworkState(
Sergey Ulanove2b15012016-11-22 16:08:30 -08003828 MediaType::VIDEO, &required_encoder, &required_transport);
skvlad7a43d252016-03-22 15:32:27 -07003829}
3830
philipel266f0a42016-11-28 08:49:07 -08003831TEST_P(EndToEndTest, NewVideoReceiveStreamsRespectVideoNetworkDown) {
skvlad7a43d252016-03-22 15:32:27 -07003832 UnusedTransport transport;
Sergey Ulanove2b15012016-11-22 16:08:30 -08003833 VerifyNewVideoReceiveStreamsRespectNetworkState(MediaType::AUDIO, &transport);
skvlad7a43d252016-03-22 15:32:27 -07003834}
3835
philipel266f0a42016-11-28 08:49:07 -08003836TEST_P(EndToEndTest, NewVideoReceiveStreamsIgnoreAudioNetworkDown) {
skvlad7a43d252016-03-22 15:32:27 -07003837 RequiredTransport transport(false /*rtp*/, true /*rtcp*/);
Sergey Ulanove2b15012016-11-22 16:08:30 -08003838 VerifyNewVideoReceiveStreamsRespectNetworkState(MediaType::VIDEO, &transport);
skvlad7a43d252016-03-22 15:32:27 -07003839}
3840
Peter Boströmd7da1202015-06-05 14:09:38 +02003841void VerifyEmptyNackConfig(const NackConfig& config) {
3842 EXPECT_EQ(0, config.rtp_history_ms)
3843 << "Enabling NACK requires rtcp-fb: nack negotiation.";
3844}
3845
brandtrb5f2c3f2016-10-04 23:28:39 -07003846void VerifyEmptyUlpfecConfig(const UlpfecConfig& config) {
Peter Boströmd7da1202015-06-05 14:09:38 +02003847 EXPECT_EQ(-1, config.ulpfec_payload_type)
brandtr535830e2016-10-31 03:45:58 -07003848 << "Enabling ULPFEC requires rtpmap: ulpfec negotiation.";
Peter Boströmd7da1202015-06-05 14:09:38 +02003849 EXPECT_EQ(-1, config.red_payload_type)
brandtr535830e2016-10-31 03:45:58 -07003850 << "Enabling ULPFEC requires rtpmap: red negotiation.";
Peter Boströmd7da1202015-06-05 14:09:38 +02003851 EXPECT_EQ(-1, config.red_rtx_payload_type)
brandtr535830e2016-10-31 03:45:58 -07003852 << "Enabling RTX in ULPFEC requires rtpmap: rtx negotiation.";
Peter Boströmd7da1202015-06-05 14:09:38 +02003853}
3854
brandtr1e3dfbf2016-11-16 22:45:19 -08003855void VerifyEmptyFlexfecConfig(const FlexfecConfig& config) {
3856 EXPECT_EQ(-1, config.flexfec_payload_type)
3857 << "Enabling FlexFEC requires rtpmap: flexfec negotiation.";
3858 EXPECT_TRUE(config.protected_media_ssrcs.empty())
3859 << "Enabling FlexFEC requires ssrc-group: FEC-FR negotiation.";
3860}
3861
philipel266f0a42016-11-28 08:49:07 -08003862TEST_P(EndToEndTest, VerifyDefaultSendConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07003863 VideoSendStream::Config default_send_config(nullptr);
Peter Boströmd7da1202015-06-05 14:09:38 +02003864 EXPECT_EQ(0, default_send_config.rtp.nack.rtp_history_ms)
3865 << "Enabling NACK require rtcp-fb: nack negotiation.";
3866 EXPECT_TRUE(default_send_config.rtp.rtx.ssrcs.empty())
3867 << "Enabling RTX requires rtpmap: rtx negotiation.";
3868 EXPECT_TRUE(default_send_config.rtp.extensions.empty())
3869 << "Enabling RTP extensions require negotiation.";
3870
3871 VerifyEmptyNackConfig(default_send_config.rtp.nack);
brandtrb5f2c3f2016-10-04 23:28:39 -07003872 VerifyEmptyUlpfecConfig(default_send_config.rtp.ulpfec);
brandtr1e3dfbf2016-11-16 22:45:19 -08003873 VerifyEmptyFlexfecConfig(default_send_config.rtp.flexfec);
Peter Boströmd7da1202015-06-05 14:09:38 +02003874}
3875
philipel266f0a42016-11-28 08:49:07 -08003876TEST_P(EndToEndTest, VerifyDefaultVideoReceiveConfigParameters) {
solenberg4fbae2b2015-08-28 04:07:10 -07003877 VideoReceiveStream::Config default_receive_config(nullptr);
pbosda903ea2015-10-02 02:36:56 -07003878 EXPECT_EQ(RtcpMode::kCompound, default_receive_config.rtp.rtcp_mode)
Peter Boströmd7da1202015-06-05 14:09:38 +02003879 << "Reduced-size RTCP require rtcp-rsize to be negotiated.";
3880 EXPECT_FALSE(default_receive_config.rtp.remb)
3881 << "REMB require rtcp-fb: goog-remb to be negotiated.";
3882 EXPECT_FALSE(
3883 default_receive_config.rtp.rtcp_xr.receiver_reference_time_report)
3884 << "RTCP XR settings require rtcp-xr to be negotiated.";
3885 EXPECT_TRUE(default_receive_config.rtp.rtx.empty())
3886 << "Enabling RTX requires rtpmap: rtx negotiation.";
3887 EXPECT_TRUE(default_receive_config.rtp.extensions.empty())
3888 << "Enabling RTP extensions require negotiation.";
3889
3890 VerifyEmptyNackConfig(default_receive_config.rtp.nack);
brandtrb5f2c3f2016-10-04 23:28:39 -07003891 VerifyEmptyUlpfecConfig(default_receive_config.rtp.ulpfec);
Peter Boströmd7da1202015-06-05 14:09:38 +02003892}
3893
philipel266f0a42016-11-28 08:49:07 -08003894TEST_P(EndToEndTest, VerifyDefaultFlexfecReceiveConfigParameters) {
brandtr1e3dfbf2016-11-16 22:45:19 -08003895 FlexfecReceiveStream::Config default_receive_config;
3896 VerifyEmptyFlexfecConfig(default_receive_config);
3897}
3898
philipel266f0a42016-11-28 08:49:07 -08003899TEST_P(EndToEndTest, TransportSeqNumOnAudioAndVideo) {
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003900 static const int kExtensionId = 8;
3901 class TransportSequenceNumberTest : public test::EndToEndTest {
3902 public:
3903 TransportSequenceNumberTest()
3904 : EndToEndTest(kDefaultTimeoutMs),
3905 video_observed_(false),
3906 audio_observed_(false) {
3907 parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
3908 kExtensionId);
3909 }
3910
3911 size_t GetNumVideoStreams() const override { return 1; }
3912 size_t GetNumAudioStreams() const override { return 1; }
3913
3914 void ModifyVideoConfigs(
3915 VideoSendStream::Config* send_config,
3916 std::vector<VideoReceiveStream::Config>* receive_configs,
3917 VideoEncoderConfig* encoder_config) override {
3918 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07003919 send_config->rtp.extensions.push_back(RtpExtension(
3920 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003921 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
3922 }
3923
3924 void ModifyAudioConfigs(
3925 AudioSendStream::Config* send_config,
3926 std::vector<AudioReceiveStream::Config>* receive_configs) override {
3927 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -07003928 send_config->rtp.extensions.push_back(RtpExtension(
3929 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003930 (*receive_configs)[0].rtp.extensions.clear();
3931 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
3932 }
3933
3934 Action OnSendRtp(const uint8_t* packet, size_t length) override {
3935 RTPHeader header;
3936 EXPECT_TRUE(parser_->Parse(packet, length, &header));
3937 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
3938 // Unwrap packet id and verify uniqueness.
3939 int64_t packet_id =
3940 unwrapper_.Unwrap(header.extension.transportSequenceNumber);
3941 EXPECT_TRUE(received_packet_ids_.insert(packet_id).second);
3942
3943 if (header.ssrc == kVideoSendSsrcs[0])
3944 video_observed_ = true;
3945 if (header.ssrc == kAudioSendSsrc)
3946 audio_observed_ = true;
3947 if (audio_observed_ && video_observed_ &&
3948 received_packet_ids_.size() == 50) {
3949 size_t packet_id_range =
3950 *received_packet_ids_.rbegin() - *received_packet_ids_.begin() + 1;
3951 EXPECT_EQ(received_packet_ids_.size(), packet_id_range);
3952 observation_complete_.Set();
3953 }
3954 return SEND_PACKET;
3955 }
3956
3957 void PerformTest() override {
3958 EXPECT_TRUE(Wait()) << "Timed out while waiting for audio and video "
3959 "packets with transport sequence number.";
3960 }
3961
3962 private:
3963 bool video_observed_;
3964 bool audio_observed_;
3965 SequenceNumberUnwrapper unwrapper_;
3966 std::set<int64_t> received_packet_ids_;
3967 } test;
3968
stefane74eef12016-01-08 06:47:13 -08003969 RunBaseTest(&test);
Stefan Holmer9fea80f2016-01-07 17:43:18 +01003970}
palmkviste75f2042016-09-28 06:19:48 -07003971
3972class EndToEndLogTest : public EndToEndTest {
3973 void SetUp() { paths_.clear(); }
3974 void TearDown() {
3975 for (const auto& path : paths_) {
3976 rtc::RemoveFile(path);
3977 }
3978 }
3979
3980 public:
3981 int AddFile() {
3982 paths_.push_back(test::TempFilename(test::OutputPath(), "test_file"));
3983 return static_cast<int>(paths_.size()) - 1;
3984 }
3985
3986 rtc::PlatformFile OpenFile(int idx) {
3987 return rtc::OpenPlatformFile(paths_[idx]);
3988 }
3989
3990 void LogSend(bool open) {
3991 if (open) {
3992 video_send_stream_->EnableEncodedFrameRecording(
3993 std::vector<rtc::PlatformFile>(1, OpenFile(AddFile())), 0);
3994 } else {
3995 video_send_stream_->DisableEncodedFrameRecording();
3996 }
3997 }
3998 void LogReceive(bool open) {
3999 if (open) {
4000 video_receive_streams_[0]->EnableEncodedFrameRecording(
4001 OpenFile(AddFile()), 0);
4002 } else {
4003 video_receive_streams_[0]->DisableEncodedFrameRecording();
4004 }
4005 }
4006
4007 std::vector<std::string> paths_;
4008};
4009
philipel266f0a42016-11-28 08:49:07 -08004010TEST_P(EndToEndLogTest, LogsEncodedFramesWhenRequested) {
palmkviste75f2042016-09-28 06:19:48 -07004011 static const int kNumFramesToRecord = 10;
4012 class LogEncodingObserver : public test::EndToEndTest,
4013 public EncodedFrameObserver {
4014 public:
4015 explicit LogEncodingObserver(EndToEndLogTest* fixture)
4016 : EndToEndTest(kDefaultTimeoutMs),
4017 fixture_(fixture),
4018 recorded_frames_(0) {}
4019
4020 void PerformTest() override {
4021 fixture_->LogSend(true);
4022 fixture_->LogReceive(true);
4023 ASSERT_TRUE(Wait()) << "Timed out while waiting for frame logging.";
4024 }
4025
4026 void ModifyVideoConfigs(
4027 VideoSendStream::Config* send_config,
4028 std::vector<VideoReceiveStream::Config>* receive_configs,
4029 VideoEncoderConfig* encoder_config) override {
magjed509e4fe2016-11-18 01:34:11 -08004030 encoder_.reset(VP8Encoder::Create());
palmkviste75f2042016-09-28 06:19:48 -07004031 decoder_.reset(VP8Decoder::Create());
4032
4033 send_config->post_encode_callback = this;
4034 send_config->encoder_settings.payload_name = "VP8";
4035 send_config->encoder_settings.encoder = encoder_.get();
4036
4037 (*receive_configs)[0].decoders.resize(1);
4038 (*receive_configs)[0].decoders[0].payload_type =
4039 send_config->encoder_settings.payload_type;
4040 (*receive_configs)[0].decoders[0].payload_name =
4041 send_config->encoder_settings.payload_name;
4042 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
4043 }
4044
4045 void EncodedFrameCallback(const EncodedFrame& encoded_frame) override {
4046 rtc::CritScope lock(&crit_);
4047 if (recorded_frames_++ > kNumFramesToRecord) {
4048 fixture_->LogSend(false);
4049 fixture_->LogReceive(false);
4050 rtc::File send_file(fixture_->OpenFile(0));
4051 rtc::File receive_file(fixture_->OpenFile(1));
4052 uint8_t out[100];
4053 // If logging has worked correctly neither file should be empty, i.e.
4054 // we should be able to read something from them.
4055 EXPECT_LT(0u, send_file.Read(out, 100));
4056 EXPECT_LT(0u, receive_file.Read(out, 100));
4057 observation_complete_.Set();
4058 }
4059 }
4060
4061 private:
4062 EndToEndLogTest* const fixture_;
4063 std::unique_ptr<VideoEncoder> encoder_;
4064 std::unique_ptr<VideoDecoder> decoder_;
4065 rtc::CriticalSection crit_;
4066 int recorded_frames_ GUARDED_BY(crit_);
4067 } test(this);
4068
4069 RunBaseTest(&test);
4070}
4071
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00004072} // namespace webrtc