blob: 974f479380287080bf78ae89218b56a0d271db80 [file] [log] [blame]
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001/*
kjellander1afca732016-02-07 20:46:45 -08002 * Copyright (c) 2004 The WebRTC project authors. All Rights Reserved.
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00003 *
kjellander1afca732016-02-07 20:46:45 -08004 * 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.
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00009 */
10
pbos@webrtc.orgc37e72e2015-01-05 18:51:13 +000011#include <algorithm>
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +000012#include <map>
kwiberg686a8ef2016-02-26 03:00:35 -080013#include <memory>
pbos@webrtc.org86f613d2014-06-10 08:53:05 +000014#include <vector>
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +000015
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020016#include "api/video_codecs/sdp_video_format.h"
17#include "api/video_codecs/video_decoder_factory.h"
18#include "api/video_codecs/video_encoder.h"
19#include "api/video_codecs/video_encoder_factory.h"
20#include "call/flexfec_receive_stream.h"
21#include "common_video/h264/profile_level_id.h"
22#include "logging/rtc_event_log/rtc_event_log.h"
23#include "media/base/mediaconstants.h"
24#include "media/base/rtputils.h"
25#include "media/base/testutils.h"
26#include "media/base/videoengine_unittest.h"
27#include "media/engine/constants.h"
28#include "media/engine/fakewebrtccall.h"
29#include "media/engine/fakewebrtcvideoengine.h"
30#include "media/engine/simulcast.h"
31#include "media/engine/webrtcvideoengine.h"
32#include "media/engine/webrtcvoiceengine.h"
33#include "rtc_base/arraysize.h"
34#include "rtc_base/gunit.h"
35#include "rtc_base/stringutils.h"
36#include "test/field_trial.h"
37#include "test/gmock.h"
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +000038
isheriff6f8d6862016-05-26 11:24:55 -070039using webrtc::RtpExtension;
40
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +000041namespace {
buildbot@webrtc.orga8530772014-12-10 09:01:18 +000042static const int kDefaultQpMax = 56;
buildbot@webrtc.orga8530772014-12-10 09:01:18 +000043
noahricd10a68e2015-07-10 11:27:55 -070044static const uint8_t kRedRtxPayloadType = 125;
45
Peter Boström0c4e06b2015-10-07 12:23:21 +020046static const uint32_t kSsrcs1[] = {1};
47static const uint32_t kSsrcs3[] = {1, 2, 3};
48static const uint32_t kRtxSsrcs1[] = {4};
brandtr468da7c2016-11-22 02:16:47 -080049static const uint32_t kFlexfecSsrc = 5;
Peter Boström0c4e06b2015-10-07 12:23:21 +020050static const uint32_t kIncomingUnsignalledSsrc = 0xC0FFEE;
mzanaty8a855d62017-02-17 15:46:43 -080051static const uint32_t kDefaultRecvSsrc = 0;
52
pbos@webrtc.org3c107582014-07-20 15:27:35 +000053static const char kUnsupportedExtensionName[] =
54 "urn:ietf:params:rtp-hdrext:unsupported";
pbos@webrtc.orgf99c2f22014-06-13 12:27:38 +000055
magjed509e4fe2016-11-18 01:34:11 -080056cricket::VideoCodec RemoveFeedbackParams(cricket::VideoCodec&& codec) {
57 codec.feedback_params = cricket::FeedbackParams();
58 return codec;
59}
60
pbos@webrtc.orgf99c2f22014-06-13 12:27:38 +000061void VerifyCodecHasDefaultFeedbackParams(const cricket::VideoCodec& codec) {
62 EXPECT_TRUE(codec.HasFeedbackParam(cricket::FeedbackParam(
63 cricket::kRtcpFbParamNack, cricket::kParamValueEmpty)));
64 EXPECT_TRUE(codec.HasFeedbackParam(cricket::FeedbackParam(
65 cricket::kRtcpFbParamNack, cricket::kRtcpFbNackParamPli)));
66 EXPECT_TRUE(codec.HasFeedbackParam(cricket::FeedbackParam(
67 cricket::kRtcpFbParamRemb, cricket::kParamValueEmpty)));
68 EXPECT_TRUE(codec.HasFeedbackParam(cricket::FeedbackParam(
stefan43edf0f2015-11-20 18:05:48 -080069 cricket::kRtcpFbParamTransportCc, cricket::kParamValueEmpty)));
70 EXPECT_TRUE(codec.HasFeedbackParam(cricket::FeedbackParam(
pbos@webrtc.orgf99c2f22014-06-13 12:27:38 +000071 cricket::kRtcpFbParamCcm, cricket::kRtcpFbCcmParamFir)));
72}
73
magjed725e4842016-11-16 00:48:13 -080074// Return true if any codec in |codecs| is an RTX codec with associated payload
75// type |payload_type|.
76bool HasRtxCodec(const std::vector<cricket::VideoCodec>& codecs,
77 int payload_type) {
78 for (const cricket::VideoCodec& codec : codecs) {
79 int associated_payload_type;
80 if (cricket::CodecNamesEq(codec.name.c_str(), "rtx") &&
81 codec.GetParam(cricket::kCodecParamAssociatedPayloadType,
82 &associated_payload_type) &&
83 associated_payload_type == payload_type) {
84 return true;
85 }
86 }
87 return false;
88}
89
nisseca5706d2017-09-11 02:32:16 -070090// TODO(nisse): Duplicated in call.cc.
91const int* FindKeyByValue(const std::map<int, int>& m, int v) {
92 for (const auto& kv : m) {
93 if (kv.second == v)
94 return &kv.first;
95 }
96 return nullptr;
97}
98
99bool HasRtxReceiveAssociation(
100 const webrtc::VideoReceiveStream::Config& config,
101 int payload_type) {
102 return FindKeyByValue(config.rtp.rtx_associated_payload_types,
103 payload_type) != nullptr;
104}
105
106// Check that there's an Rtx payload type for each decoder.
107bool VerifyRtxReceiveAssociations(
108 const webrtc::VideoReceiveStream::Config& config) {
109 for (const auto& decoder : config.decoders) {
110 if (!HasRtxReceiveAssociation(config, decoder.payload_type))
111 return false;
112 }
113 return true;
114}
115
brandtrffc61182016-11-28 06:02:22 -0800116rtc::scoped_refptr<webrtc::VideoFrameBuffer> CreateBlackFrameBuffer(
nisse64ec8f82016-09-27 00:17:25 -0700117 int width,
118 int height) {
119 rtc::scoped_refptr<webrtc::I420Buffer> buffer =
120 webrtc::I420Buffer::Create(width, height);
nisseaf916892017-01-10 07:44:26 -0800121 webrtc::I420Buffer::SetBlack(buffer);
nisse64ec8f82016-09-27 00:17:25 -0700122 return buffer;
magjed@webrtc.orgfc5ad952015-01-27 09:57:01 +0000123}
124
Shao Changbine62202f2015-04-21 20:24:50 +0800125void VerifySendStreamHasRtxTypes(const webrtc::VideoSendStream::Config& config,
126 const std::map<int, int>& rtx_types) {
127 std::map<int, int>::const_iterator it;
128 it = rtx_types.find(config.encoder_settings.payload_type);
129 EXPECT_TRUE(it != rtx_types.end() &&
130 it->second == config.rtp.rtx.payload_type);
131
brandtrb5f2c3f2016-10-04 23:28:39 -0700132 if (config.rtp.ulpfec.red_rtx_payload_type != -1) {
133 it = rtx_types.find(config.rtp.ulpfec.red_payload_type);
Shao Changbine62202f2015-04-21 20:24:50 +0800134 EXPECT_TRUE(it != rtx_types.end() &&
brandtrb5f2c3f2016-10-04 23:28:39 -0700135 it->second == config.rtp.ulpfec.red_rtx_payload_type);
Shao Changbine62202f2015-04-21 20:24:50 +0800136 }
137}
kthelgason2bc68642017-02-07 07:02:22 -0800138
139cricket::MediaConfig GetMediaConfig() {
140 cricket::MediaConfig media_config;
141 media_config.video.enable_cpu_overuse_detection = false;
142 return media_config;
143}
nisse26e3abb2017-08-25 04:44:25 -0700144
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +0000145} // namespace
146
147namespace cricket {
eladalonf1841382017-06-12 01:16:46 -0700148class WebRtcVideoEngineTest : public ::testing::Test {
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +0000149 public:
eladalonf1841382017-06-12 01:16:46 -0700150 WebRtcVideoEngineTest() : WebRtcVideoEngineTest("") {}
151 explicit WebRtcVideoEngineTest(const char* field_trials)
stefanc1aeaf02015-10-15 07:26:07 -0700152 : override_field_trials_(field_trials),
skvlad11a9cbf2016-10-07 11:53:05 -0700153 call_(webrtc::Call::Create(webrtc::Call::Config(&event_log_))),
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200154 encoder_factory_(new cricket::FakeWebRtcVideoEncoderFactory),
155 decoder_factory_(new cricket::FakeWebRtcVideoDecoderFactory),
156 engine_(std::unique_ptr<cricket::WebRtcVideoEncoderFactory>(
157 encoder_factory_),
158 std::unique_ptr<cricket::WebRtcVideoDecoderFactory>(
159 decoder_factory_)) {
pbos@webrtc.org9fbb7172014-06-13 09:34:13 +0000160 std::vector<VideoCodec> engine_codecs = engine_.codecs();
henrikg91d6ede2015-09-17 00:24:34 -0700161 RTC_DCHECK(!engine_codecs.empty());
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +0000162 bool codec_set = false;
magjed509e4fe2016-11-18 01:34:11 -0800163 for (const cricket::VideoCodec& codec : engine_codecs) {
164 if (codec.name == "rtx") {
Shao Changbine62202f2015-04-21 20:24:50 +0800165 int associated_payload_type;
magjed509e4fe2016-11-18 01:34:11 -0800166 if (codec.GetParam(kCodecParamAssociatedPayloadType,
167 &associated_payload_type)) {
168 default_apt_rtx_types_[associated_payload_type] = codec.id;
Shao Changbine62202f2015-04-21 20:24:50 +0800169 }
magjed509e4fe2016-11-18 01:34:11 -0800170 } else if (!codec_set && codec.name != "red" && codec.name != "ulpfec") {
171 default_codec_ = codec;
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +0000172 codec_set = true;
173 }
174 }
175
henrikg91d6ede2015-09-17 00:24:34 -0700176 RTC_DCHECK(codec_set);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +0000177 }
178
179 protected:
magjed509e4fe2016-11-18 01:34:11 -0800180 // Find the codec in the engine with the given name. The codec must be
181 // present.
182 cricket::VideoCodec GetEngineCodec(const std::string& name);
183
magjed2475ae22017-09-12 04:42:15 -0700184 VideoMediaChannel* SetUpForExternalEncoderFactory();
pbos@webrtc.orgfa553ef2014-10-20 11:07:07 +0000185
pbos@webrtc.org96a93252014-11-03 14:46:44 +0000186 VideoMediaChannel* SetUpForExternalDecoderFactory(
pbos@webrtc.org96a93252014-11-03 14:46:44 +0000187 const std::vector<VideoCodec>& codecs);
188
Peter Boströme4499152016-02-05 11:13:28 +0100189 void TestExtendedEncoderOveruse(bool use_external_encoder);
190
stefanc1aeaf02015-10-15 07:26:07 -0700191 webrtc::test::ScopedFieldTrials override_field_trials_;
skvlad11a9cbf2016-10-07 11:53:05 -0700192 webrtc::RtcEventLogNullImpl event_log_;
eladalonf1841382017-06-12 01:16:46 -0700193 // Used in WebRtcVideoEngineVoiceTest, but defined here so it's properly
pbos@webrtc.orgf1f0d9a2015-03-02 13:30:15 +0000194 // initialized when the constructor is called.
kwiberg686a8ef2016-02-26 03:00:35 -0800195 std::unique_ptr<webrtc::Call> call_;
Magnus Jedvertd4b0c052017-09-14 10:24:54 +0200196 // TODO(magjed): Update all tests to use new video codec factories once the
197 // old factories are deprecated,
198 // https://bugs.chromium.org/p/webrtc/issues/detail?id=7925.
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200199 // These factories are owned by the video engine.
200 cricket::FakeWebRtcVideoEncoderFactory* encoder_factory_;
201 cricket::FakeWebRtcVideoDecoderFactory* decoder_factory_;
eladalonf1841382017-06-12 01:16:46 -0700202 WebRtcVideoEngine engine_;
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +0000203 VideoCodec default_codec_;
Shao Changbine62202f2015-04-21 20:24:50 +0800204 std::map<int, int> default_apt_rtx_types_;
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +0000205};
206
eladalonf1841382017-06-12 01:16:46 -0700207TEST_F(WebRtcVideoEngineTest, AnnouncesVp9AccordingToBuildFlags) {
Peter Boström12996152016-05-14 02:03:18 +0200208 bool claims_vp9_support = false;
209 for (const cricket::VideoCodec& codec : engine_.codecs()) {
210 if (codec.name == "VP9") {
211 claims_vp9_support = true;
212 break;
213 }
214 }
215#if defined(RTC_DISABLE_VP9)
216 EXPECT_FALSE(claims_vp9_support);
217#else
218 EXPECT_TRUE(claims_vp9_support);
219#endif // defined(RTC_DISABLE_VP9)
220}
221
eladalonf1841382017-06-12 01:16:46 -0700222TEST_F(WebRtcVideoEngineTest, DefaultRtxCodecHasAssociatedPayloadTypeSet) {
pbos@webrtc.orge322a172014-06-13 11:47:28 +0000223 std::vector<VideoCodec> engine_codecs = engine_.codecs();
224 for (size_t i = 0; i < engine_codecs.size(); ++i) {
225 if (engine_codecs[i].name != kRtxCodecName)
226 continue;
227 int associated_payload_type;
228 EXPECT_TRUE(engine_codecs[i].GetParam(kCodecParamAssociatedPayloadType,
pbos@webrtc.org42684be2014-10-03 11:25:45 +0000229 &associated_payload_type));
pbos@webrtc.orge322a172014-06-13 11:47:28 +0000230 EXPECT_EQ(default_codec_.id, associated_payload_type);
231 return;
232 }
233 FAIL() << "No RTX codec found among default codecs.";
234}
235
eladalonf1841382017-06-12 01:16:46 -0700236TEST_F(WebRtcVideoEngineTest, SupportsTimestampOffsetHeaderExtension) {
Stefan Holmer9d69c3f2015-12-07 10:45:43 +0100237 RtpCapabilities capabilities = engine_.GetCapabilities();
238 ASSERT_FALSE(capabilities.header_extensions.empty());
isheriff6f8d6862016-05-26 11:24:55 -0700239 for (const RtpExtension& extension : capabilities.header_extensions) {
240 if (extension.uri == RtpExtension::kTimestampOffsetUri) {
241 EXPECT_EQ(RtpExtension::kTimestampOffsetDefaultId, extension.id);
pbos@webrtc.org587ef602014-06-16 17:32:02 +0000242 return;
243 }
244 }
245 FAIL() << "Timestamp offset extension not in header-extension list.";
246}
247
eladalonf1841382017-06-12 01:16:46 -0700248TEST_F(WebRtcVideoEngineTest, SupportsAbsoluteSenderTimeHeaderExtension) {
Stefan Holmer9d69c3f2015-12-07 10:45:43 +0100249 RtpCapabilities capabilities = engine_.GetCapabilities();
250 ASSERT_FALSE(capabilities.header_extensions.empty());
isheriff6f8d6862016-05-26 11:24:55 -0700251 for (const RtpExtension& extension : capabilities.header_extensions) {
252 if (extension.uri == RtpExtension::kAbsSendTimeUri) {
253 EXPECT_EQ(RtpExtension::kAbsSendTimeDefaultId, extension.id);
pbos@webrtc.org587ef602014-06-16 17:32:02 +0000254 return;
255 }
256 }
257 FAIL() << "Absolute Sender Time extension not in header-extension list.";
258}
259
eladalonf1841382017-06-12 01:16:46 -0700260TEST_F(WebRtcVideoEngineTest, SupportsTransportSequenceNumberHeaderExtension) {
Stefan Holmer9d69c3f2015-12-07 10:45:43 +0100261 RtpCapabilities capabilities = engine_.GetCapabilities();
262 ASSERT_FALSE(capabilities.header_extensions.empty());
isheriff6f8d6862016-05-26 11:24:55 -0700263 for (const RtpExtension& extension : capabilities.header_extensions) {
264 if (extension.uri == RtpExtension::kTransportSequenceNumberUri) {
265 EXPECT_EQ(RtpExtension::kTransportSequenceNumberDefaultId, extension.id);
stefanc1aeaf02015-10-15 07:26:07 -0700266 return;
267 }
268 }
269 FAIL() << "Transport sequence number extension not in header-extension list.";
270}
271
eladalonf1841382017-06-12 01:16:46 -0700272TEST_F(WebRtcVideoEngineTest, SupportsVideoRotationHeaderExtension) {
Stefan Holmer9d69c3f2015-12-07 10:45:43 +0100273 RtpCapabilities capabilities = engine_.GetCapabilities();
274 ASSERT_FALSE(capabilities.header_extensions.empty());
isheriff6f8d6862016-05-26 11:24:55 -0700275 for (const RtpExtension& extension : capabilities.header_extensions) {
276 if (extension.uri == RtpExtension::kVideoRotationUri) {
277 EXPECT_EQ(RtpExtension::kVideoRotationDefaultId, extension.id);
Guo-wei Shieh64c1e8c2015-04-01 15:33:06 -0700278 return;
279 }
280 }
281 FAIL() << "Video Rotation extension not in header-extension list.";
282}
283
eladalonf1841382017-06-12 01:16:46 -0700284TEST_F(WebRtcVideoEngineTest, CVOSetHeaderExtensionBeforeCapturer) {
Guo-wei Shieh64c1e8c2015-04-01 15:33:06 -0700285 // Allocate the capturer first to prevent early destruction before channel's
286 // dtor is called.
287 cricket::FakeVideoCapturer capturer;
288
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200289 encoder_factory_->AddSupportedVideoCodecType("VP8");
Guo-wei Shieh64c1e8c2015-04-01 15:33:06 -0700290
magjed2475ae22017-09-12 04:42:15 -0700291 std::unique_ptr<VideoMediaChannel> channel(SetUpForExternalEncoderFactory());
Guo-wei Shieh64c1e8c2015-04-01 15:33:06 -0700292 EXPECT_TRUE(channel->AddSendStream(StreamParams::CreateLegacy(kSsrc)));
293
294 // Add CVO extension.
295 const int id = 1;
magjed509e4fe2016-11-18 01:34:11 -0800296 cricket::VideoSendParameters parameters;
297 parameters.codecs.push_back(GetEngineCodec("VP8"));
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200298 parameters.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -0700299 RtpExtension(RtpExtension::kVideoRotationUri, id));
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200300 EXPECT_TRUE(channel->SetSendParameters(parameters));
Guo-wei Shieh64c1e8c2015-04-01 15:33:06 -0700301
302 // Set capturer.
deadbeef5a4a75a2016-06-02 16:23:38 -0700303 EXPECT_TRUE(channel->SetVideoSend(kSsrc, true, nullptr, &capturer));
Guo-wei Shieh64c1e8c2015-04-01 15:33:06 -0700304
305 // Verify capturer has turned off applying rotation.
nisse47ac4622016-05-25 08:47:01 -0700306 EXPECT_FALSE(capturer.apply_rotation());
Guo-wei Shieh64c1e8c2015-04-01 15:33:06 -0700307
308 // Verify removing header extension turns on applying rotation.
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200309 parameters.extensions.clear();
310 EXPECT_TRUE(channel->SetSendParameters(parameters));
nisse47ac4622016-05-25 08:47:01 -0700311 EXPECT_TRUE(capturer.apply_rotation());
Guo-wei Shieh64c1e8c2015-04-01 15:33:06 -0700312}
313
eladalonf1841382017-06-12 01:16:46 -0700314TEST_F(WebRtcVideoEngineTest, CVOSetHeaderExtensionBeforeAddSendStream) {
perkj91e1c152016-03-02 05:34:00 -0800315 // Allocate the capturer first to prevent early destruction before channel's
316 // dtor is called.
317 cricket::FakeVideoCapturer capturer;
318
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200319 encoder_factory_->AddSupportedVideoCodecType("VP8");
perkj91e1c152016-03-02 05:34:00 -0800320
magjed2475ae22017-09-12 04:42:15 -0700321 std::unique_ptr<VideoMediaChannel> channel(SetUpForExternalEncoderFactory());
perkj91e1c152016-03-02 05:34:00 -0800322 // Add CVO extension.
323 const int id = 1;
magjed509e4fe2016-11-18 01:34:11 -0800324 cricket::VideoSendParameters parameters;
325 parameters.codecs.push_back(GetEngineCodec("VP8"));
perkj91e1c152016-03-02 05:34:00 -0800326 parameters.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -0700327 RtpExtension(RtpExtension::kVideoRotationUri, id));
perkj91e1c152016-03-02 05:34:00 -0800328 EXPECT_TRUE(channel->SetSendParameters(parameters));
329 EXPECT_TRUE(channel->AddSendStream(StreamParams::CreateLegacy(kSsrc)));
330
331 // Set capturer.
deadbeef5a4a75a2016-06-02 16:23:38 -0700332 EXPECT_TRUE(channel->SetVideoSend(kSsrc, true, nullptr, &capturer));
perkj91e1c152016-03-02 05:34:00 -0800333
334 // Verify capturer has turned off applying rotation.
nisse47ac4622016-05-25 08:47:01 -0700335 EXPECT_FALSE(capturer.apply_rotation());
perkj91e1c152016-03-02 05:34:00 -0800336}
337
eladalonf1841382017-06-12 01:16:46 -0700338TEST_F(WebRtcVideoEngineTest, CVOSetHeaderExtensionAfterCapturer) {
Guo-wei Shieh64c1e8c2015-04-01 15:33:06 -0700339 cricket::FakeVideoCapturer capturer;
340
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200341 encoder_factory_->AddSupportedVideoCodecType("VP8");
342 encoder_factory_->AddSupportedVideoCodecType("VP9");
Guo-wei Shieh64c1e8c2015-04-01 15:33:06 -0700343
magjed2475ae22017-09-12 04:42:15 -0700344 std::unique_ptr<VideoMediaChannel> channel(SetUpForExternalEncoderFactory());
Guo-wei Shieh64c1e8c2015-04-01 15:33:06 -0700345 EXPECT_TRUE(channel->AddSendStream(StreamParams::CreateLegacy(kSsrc)));
346
347 // Set capturer.
deadbeef5a4a75a2016-06-02 16:23:38 -0700348 EXPECT_TRUE(channel->SetVideoSend(kSsrc, true, nullptr, &capturer));
Guo-wei Shieh64c1e8c2015-04-01 15:33:06 -0700349
perkjcaafdba2016-03-20 07:34:29 -0700350 // Verify capturer has turned on applying rotation.
nisse47ac4622016-05-25 08:47:01 -0700351 EXPECT_TRUE(capturer.apply_rotation());
perkjcaafdba2016-03-20 07:34:29 -0700352
Guo-wei Shieh64c1e8c2015-04-01 15:33:06 -0700353 // Add CVO extension.
354 const int id = 1;
magjed509e4fe2016-11-18 01:34:11 -0800355 cricket::VideoSendParameters parameters;
356 parameters.codecs.push_back(GetEngineCodec("VP8"));
357 parameters.codecs.push_back(GetEngineCodec("VP9"));
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200358 parameters.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -0700359 RtpExtension(RtpExtension::kVideoRotationUri, id));
perkjcaafdba2016-03-20 07:34:29 -0700360 // Also remove the first codec to trigger a codec change as well.
361 parameters.codecs.erase(parameters.codecs.begin());
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200362 EXPECT_TRUE(channel->SetSendParameters(parameters));
Guo-wei Shieh64c1e8c2015-04-01 15:33:06 -0700363
364 // Verify capturer has turned off applying rotation.
nisse47ac4622016-05-25 08:47:01 -0700365 EXPECT_FALSE(capturer.apply_rotation());
Guo-wei Shieh64c1e8c2015-04-01 15:33:06 -0700366
367 // Verify removing header extension turns on applying rotation.
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200368 parameters.extensions.clear();
369 EXPECT_TRUE(channel->SetSendParameters(parameters));
nisse47ac4622016-05-25 08:47:01 -0700370 EXPECT_TRUE(capturer.apply_rotation());
Guo-wei Shieh64c1e8c2015-04-01 15:33:06 -0700371}
372
eladalonf1841382017-06-12 01:16:46 -0700373TEST_F(WebRtcVideoEngineTest, SetSendFailsBeforeSettingCodecs) {
kwiberg686a8ef2016-02-26 03:00:35 -0800374 std::unique_ptr<VideoMediaChannel> channel(
kthelgason2bc68642017-02-07 07:02:22 -0800375 engine_.CreateChannel(call_.get(), GetMediaConfig(), VideoOptions()));
pbos@webrtc.org5301b0f2014-07-17 08:51:46 +0000376
377 EXPECT_TRUE(channel->AddSendStream(StreamParams::CreateLegacy(123)));
378
379 EXPECT_FALSE(channel->SetSend(true))
380 << "Channel should not start without codecs.";
381 EXPECT_TRUE(channel->SetSend(false))
382 << "Channel should be stoppable even without set codecs.";
383}
384
eladalonf1841382017-06-12 01:16:46 -0700385TEST_F(WebRtcVideoEngineTest, GetStatsWithoutSendCodecsSetDoesNotCrash) {
kwiberg686a8ef2016-02-26 03:00:35 -0800386 std::unique_ptr<VideoMediaChannel> channel(
kthelgason2bc68642017-02-07 07:02:22 -0800387 engine_.CreateChannel(call_.get(), GetMediaConfig(), VideoOptions()));
pbos@webrtc.orgc3d2bd22014-08-12 20:55:10 +0000388 EXPECT_TRUE(channel->AddSendStream(StreamParams::CreateLegacy(123)));
389 VideoMediaInfo info;
390 channel->GetStats(&info);
391}
392
eladalonf1841382017-06-12 01:16:46 -0700393TEST_F(WebRtcVideoEngineTest, UseExternalFactoryForVp8WhenSupported) {
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200394 encoder_factory_->AddSupportedVideoCodecType("VP8");
pbos@webrtc.org7fe1e032014-10-14 04:25:33 +0000395
magjed2475ae22017-09-12 04:42:15 -0700396 std::unique_ptr<VideoMediaChannel> channel(SetUpForExternalEncoderFactory());
Sergey Ulanove2b15012016-11-22 16:08:30 -0800397 channel->OnReadyToSend(true);
pbos@webrtc.org7fe1e032014-10-14 04:25:33 +0000398
399 EXPECT_TRUE(
400 channel->AddSendStream(cricket::StreamParams::CreateLegacy(kSsrc)));
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200401 EXPECT_EQ(0, encoder_factory_->GetNumCreatedEncoders());
pbos@webrtc.org7fe1e032014-10-14 04:25:33 +0000402 EXPECT_TRUE(channel->SetSend(true));
pbos@webrtc.org7fe1e032014-10-14 04:25:33 +0000403 cricket::FakeVideoCapturer capturer;
deadbeef5a4a75a2016-06-02 16:23:38 -0700404 EXPECT_TRUE(channel->SetVideoSend(kSsrc, true, nullptr, &capturer));
pbos@webrtc.org7fe1e032014-10-14 04:25:33 +0000405 EXPECT_EQ(cricket::CS_RUNNING,
406 capturer.Start(capturer.GetSupportedFormats()->front()));
407 EXPECT_TRUE(capturer.CaptureFrame());
Per21d45d22016-10-30 21:37:57 +0100408 // Sending one frame will have allocate the encoder.
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200409 ASSERT_TRUE(encoder_factory_->WaitForCreatedVideoEncoders(1));
410 EXPECT_TRUE_WAIT(encoder_factory_->encoders()[0]->GetNumEncodedFrames() > 0,
pbos@webrtc.org7fe1e032014-10-14 04:25:33 +0000411 kTimeout);
412
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200413 int num_created_encoders = encoder_factory_->GetNumCreatedEncoders();
Per21d45d22016-10-30 21:37:57 +0100414 EXPECT_EQ(num_created_encoders, 1);
pbos@webrtc.org86196c42015-02-16 21:02:00 +0000415
416 // Setting codecs of the same type should not reallocate any encoders
417 // (expecting a no-op).
magjed509e4fe2016-11-18 01:34:11 -0800418 cricket::VideoSendParameters parameters;
419 parameters.codecs.push_back(GetEngineCodec("VP8"));
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200420 EXPECT_TRUE(channel->SetSendParameters(parameters));
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200421 EXPECT_EQ(num_created_encoders, encoder_factory_->GetNumCreatedEncoders());
pbos@webrtc.org7fe1e032014-10-14 04:25:33 +0000422
423 // Remove stream previously added to free the external encoder instance.
424 EXPECT_TRUE(channel->RemoveSendStream(kSsrc));
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200425 EXPECT_EQ(0u, encoder_factory_->encoders().size());
pbos@webrtc.org7fe1e032014-10-14 04:25:33 +0000426}
427
Taylor Brandstetter6c3e7882016-06-29 11:14:19 -0700428// Test that when an external encoder factory supports a codec we don't
429// internally support, we still add an RTX codec for it.
430// TODO(deadbeef): Currently this test is only effective if WebRTC is
431// built with no internal H264 support. This test should be updated
432// if/when we start adding RTX codecs for unrecognized codec names.
eladalonf1841382017-06-12 01:16:46 -0700433TEST_F(WebRtcVideoEngineTest, RtxCodecAddedForExternalCodec) {
magjed725e4842016-11-16 00:48:13 -0800434 using webrtc::H264::ProfileLevelIdToString;
435 using webrtc::H264::ProfileLevelId;
436 using webrtc::H264::kLevel1;
437 cricket::VideoCodec h264_constrained_baseline("H264");
438 h264_constrained_baseline.params[kH264FmtpProfileLevelId] =
439 *ProfileLevelIdToString(
440 ProfileLevelId(webrtc::H264::kProfileConstrainedBaseline, kLevel1));
441 cricket::VideoCodec h264_constrained_high("H264");
442 h264_constrained_high.params[kH264FmtpProfileLevelId] =
443 *ProfileLevelIdToString(
444 ProfileLevelId(webrtc::H264::kProfileConstrainedHigh, kLevel1));
445 cricket::VideoCodec h264_high("H264");
446 h264_high.params[kH264FmtpProfileLevelId] = *ProfileLevelIdToString(
447 ProfileLevelId(webrtc::H264::kProfileHigh, kLevel1));
448
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200449 encoder_factory_->AddSupportedVideoCodec(h264_constrained_baseline);
450 encoder_factory_->AddSupportedVideoCodec(h264_constrained_high);
451 encoder_factory_->AddSupportedVideoCodec(h264_high);
Taylor Brandstetter6c3e7882016-06-29 11:14:19 -0700452
magjed725e4842016-11-16 00:48:13 -0800453 // First figure out what payload types the test codecs got assigned.
454 const std::vector<cricket::VideoCodec> codecs = engine_.codecs();
magjed509e4fe2016-11-18 01:34:11 -0800455 // Now search for RTX codecs for them. Expect that they all have associated
456 // RTX codecs.
magjed725e4842016-11-16 00:48:13 -0800457 EXPECT_TRUE(HasRtxCodec(
458 codecs, FindMatchingCodec(codecs, h264_constrained_baseline)->id));
459 EXPECT_TRUE(HasRtxCodec(
460 codecs, FindMatchingCodec(codecs, h264_constrained_high)->id));
magjed509e4fe2016-11-18 01:34:11 -0800461 EXPECT_TRUE(HasRtxCodec(
magjed725e4842016-11-16 00:48:13 -0800462 codecs, FindMatchingCodec(codecs, h264_high)->id));
Taylor Brandstetter6c3e7882016-06-29 11:14:19 -0700463}
464
eladalonf1841382017-06-12 01:16:46 -0700465void WebRtcVideoEngineTest::TestExtendedEncoderOveruse(
Peter Boströme4499152016-02-05 11:13:28 +0100466 bool use_external_encoder) {
kwiberg686a8ef2016-02-26 03:00:35 -0800467 std::unique_ptr<VideoMediaChannel> channel;
skvlad11a9cbf2016-10-07 11:53:05 -0700468 FakeCall* fake_call = new FakeCall(webrtc::Call::Config(&event_log_));
Peter Boströme4499152016-02-05 11:13:28 +0100469 call_.reset(fake_call);
470 if (use_external_encoder) {
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200471 encoder_factory_->AddSupportedVideoCodecType("VP8");
magjed2475ae22017-09-12 04:42:15 -0700472 channel.reset(SetUpForExternalEncoderFactory());
Peter Boströme4499152016-02-05 11:13:28 +0100473 } else {
nisse51542be2016-02-12 02:27:06 -0800474 channel.reset(
kthelgason2bc68642017-02-07 07:02:22 -0800475 engine_.CreateChannel(call_.get(), GetMediaConfig(), VideoOptions()));
Peter Boströme4499152016-02-05 11:13:28 +0100476 }
477 ASSERT_TRUE(
478 channel->AddSendStream(cricket::StreamParams::CreateLegacy(kSsrc)));
magjed509e4fe2016-11-18 01:34:11 -0800479 cricket::VideoSendParameters parameters;
480 parameters.codecs.push_back(GetEngineCodec("VP8"));
Peter Boströme4499152016-02-05 11:13:28 +0100481 EXPECT_TRUE(channel->SetSendParameters(parameters));
482 EXPECT_TRUE(channel->SetSend(true));
483 FakeVideoSendStream* stream = fake_call->GetVideoSendStreams()[0];
484
485 EXPECT_EQ(use_external_encoder,
486 stream->GetConfig().encoder_settings.full_overuse_time);
487 // Remove stream previously added to free the external encoder instance.
488 EXPECT_TRUE(channel->RemoveSendStream(kSsrc));
489}
490
eladalonf1841382017-06-12 01:16:46 -0700491TEST_F(WebRtcVideoEngineTest, EnablesFullEncoderTimeForExternalEncoders) {
Peter Boströme4499152016-02-05 11:13:28 +0100492 TestExtendedEncoderOveruse(true);
493}
494
eladalonf1841382017-06-12 01:16:46 -0700495TEST_F(WebRtcVideoEngineTest, DisablesFullEncoderTimeForNonExternalEncoders) {
Peter Boströme4499152016-02-05 11:13:28 +0100496 TestExtendedEncoderOveruse(false);
497}
498
Peter Boström12996152016-05-14 02:03:18 +0200499#if !defined(RTC_DISABLE_VP9)
eladalonf1841382017-06-12 01:16:46 -0700500TEST_F(WebRtcVideoEngineTest, CanConstructDecoderForVp9EncoderFactory) {
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200501 encoder_factory_->AddSupportedVideoCodecType("VP9");
Peter Boström53eda3d2015-03-27 15:53:18 +0100502
magjed2475ae22017-09-12 04:42:15 -0700503 std::unique_ptr<VideoMediaChannel> channel(SetUpForExternalEncoderFactory());
Peter Boström53eda3d2015-03-27 15:53:18 +0100504
505 EXPECT_TRUE(
506 channel->AddRecvStream(cricket::StreamParams::CreateLegacy(kSsrc)));
507}
Peter Boström12996152016-05-14 02:03:18 +0200508#endif // !defined(RTC_DISABLE_VP9)
Peter Boström53eda3d2015-03-27 15:53:18 +0100509
eladalonf1841382017-06-12 01:16:46 -0700510TEST_F(WebRtcVideoEngineTest, PropagatesInputFrameTimestamp) {
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200511 encoder_factory_->AddSupportedVideoCodecType("VP8");
skvlad11a9cbf2016-10-07 11:53:05 -0700512 FakeCall* fake_call = new FakeCall(webrtc::Call::Config(&event_log_));
Fredrik Solenberg709ed672015-09-15 12:26:33 +0200513 call_.reset(fake_call);
magjed2475ae22017-09-12 04:42:15 -0700514 std::unique_ptr<VideoMediaChannel> channel(SetUpForExternalEncoderFactory());
qiangchenc27d89f2015-07-16 10:27:16 -0700515
516 EXPECT_TRUE(
517 channel->AddSendStream(cricket::StreamParams::CreateLegacy(kSsrc)));
518
519 FakeVideoCapturer capturer;
deadbeef5a4a75a2016-06-02 16:23:38 -0700520 EXPECT_TRUE(channel->SetVideoSend(kSsrc, true, nullptr, &capturer));
qiangchenc27d89f2015-07-16 10:27:16 -0700521 capturer.Start(cricket::VideoFormat(1280, 720,
522 cricket::VideoFormat::FpsToInterval(60),
523 cricket::FOURCC_I420));
524 channel->SetSend(true);
525
Fredrik Solenberg709ed672015-09-15 12:26:33 +0200526 FakeVideoSendStream* stream = fake_call->GetVideoSendStreams()[0];
qiangchenc27d89f2015-07-16 10:27:16 -0700527
528 EXPECT_TRUE(capturer.CaptureFrame());
pbos1cb121d2015-09-14 11:38:38 -0700529 int64_t last_timestamp = stream->GetLastTimestamp();
qiangchenc27d89f2015-07-16 10:27:16 -0700530 for (int i = 0; i < 10; i++) {
531 EXPECT_TRUE(capturer.CaptureFrame());
pbos1cb121d2015-09-14 11:38:38 -0700532 int64_t timestamp = stream->GetLastTimestamp();
qiangchenc27d89f2015-07-16 10:27:16 -0700533 int64_t interval = timestamp - last_timestamp;
534
535 // Precision changes from nanosecond to millisecond.
536 // Allow error to be no more than 1.
537 EXPECT_NEAR(cricket::VideoFormat::FpsToInterval(60) / 1E6, interval, 1);
538
539 last_timestamp = timestamp;
540 }
541
542 capturer.Start(cricket::VideoFormat(1280, 720,
543 cricket::VideoFormat::FpsToInterval(30),
544 cricket::FOURCC_I420));
545
546 EXPECT_TRUE(capturer.CaptureFrame());
547 last_timestamp = stream->GetLastTimestamp();
548 for (int i = 0; i < 10; i++) {
549 EXPECT_TRUE(capturer.CaptureFrame());
pbos1cb121d2015-09-14 11:38:38 -0700550 int64_t timestamp = stream->GetLastTimestamp();
qiangchenc27d89f2015-07-16 10:27:16 -0700551 int64_t interval = timestamp - last_timestamp;
552
553 // Precision changes from nanosecond to millisecond.
554 // Allow error to be no more than 1.
555 EXPECT_NEAR(cricket::VideoFormat::FpsToInterval(30) / 1E6, interval, 1);
556
557 last_timestamp = timestamp;
558 }
559
560 // Remove stream previously added to free the external encoder instance.
561 EXPECT_TRUE(channel->RemoveSendStream(kSsrc));
562}
563
eladalonf1841382017-06-12 01:16:46 -0700564cricket::VideoCodec WebRtcVideoEngineTest::GetEngineCodec(
magjed509e4fe2016-11-18 01:34:11 -0800565 const std::string& name) {
566 for (const cricket::VideoCodec& engine_codec : engine_.codecs()) {
567 if (CodecNamesEq(name, engine_codec.name))
568 return engine_codec;
569 }
570 // This point should never be reached.
571 ADD_FAILURE() << "Unrecognized codec name: " << name;
572 return cricket::VideoCodec();
573}
574
magjed2475ae22017-09-12 04:42:15 -0700575VideoMediaChannel* WebRtcVideoEngineTest::SetUpForExternalEncoderFactory() {
buildbot@webrtc.org1ecbe452014-10-14 20:29:28 +0000576 VideoMediaChannel* channel =
kthelgason2bc68642017-02-07 07:02:22 -0800577 engine_.CreateChannel(call_.get(), GetMediaConfig(), VideoOptions());
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200578 cricket::VideoSendParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -0800579 // We need to look up the codec in the engine to get the correct payload type.
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200580 for (const VideoCodec& codec : encoder_factory_->supported_codecs())
magjed509e4fe2016-11-18 01:34:11 -0800581 parameters.codecs.push_back(GetEngineCodec(codec.name));
582
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200583 EXPECT_TRUE(channel->SetSendParameters(parameters));
pbos@webrtc.org7fe1e032014-10-14 04:25:33 +0000584
585 return channel;
586}
587
eladalonf1841382017-06-12 01:16:46 -0700588VideoMediaChannel* WebRtcVideoEngineTest::SetUpForExternalDecoderFactory(
pbos@webrtc.org96a93252014-11-03 14:46:44 +0000589 const std::vector<VideoCodec>& codecs) {
pbos@webrtc.org96a93252014-11-03 14:46:44 +0000590 VideoMediaChannel* channel =
kthelgason2bc68642017-02-07 07:02:22 -0800591 engine_.CreateChannel(call_.get(), GetMediaConfig(), VideoOptions());
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200592 cricket::VideoRecvParameters parameters;
593 parameters.codecs = codecs;
594 EXPECT_TRUE(channel->SetRecvParameters(parameters));
pbos@webrtc.org96a93252014-11-03 14:46:44 +0000595
596 return channel;
597}
598
eladalonf1841382017-06-12 01:16:46 -0700599TEST_F(WebRtcVideoEngineTest, UsesSimulcastAdapterForVp8Factories) {
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200600 encoder_factory_->AddSupportedVideoCodecType("VP8");
pbos@webrtc.orgf18fba22015-01-14 16:26:23 +0000601
magjed2475ae22017-09-12 04:42:15 -0700602 std::unique_ptr<VideoMediaChannel> channel(SetUpForExternalEncoderFactory());
pbos@webrtc.orgf18fba22015-01-14 16:26:23 +0000603
Peter Boström0c4e06b2015-10-07 12:23:21 +0200604 std::vector<uint32_t> ssrcs = MAKE_VECTOR(kSsrcs3);
pbos@webrtc.orgf18fba22015-01-14 16:26:23 +0000605
606 EXPECT_TRUE(
607 channel->AddSendStream(CreateSimStreamParams("cname", ssrcs)));
608 EXPECT_TRUE(channel->SetSend(true));
609
pbos@webrtc.org86196c42015-02-16 21:02:00 +0000610 cricket::FakeVideoCapturer capturer;
deadbeef5a4a75a2016-06-02 16:23:38 -0700611 EXPECT_TRUE(channel->SetVideoSend(ssrcs.front(), true, nullptr, &capturer));
pbos@webrtc.org86196c42015-02-16 21:02:00 +0000612 EXPECT_EQ(cricket::CS_RUNNING,
613 capturer.Start(capturer.GetSupportedFormats()->front()));
614 EXPECT_TRUE(capturer.CaptureFrame());
615
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200616 ASSERT_TRUE(encoder_factory_->WaitForCreatedVideoEncoders(2));
pbos@webrtc.orgf18fba22015-01-14 16:26:23 +0000617
618 // Verify that encoders are configured for simulcast through adapter
619 // (increasing resolution and only configured to send one stream each).
620 int prev_width = -1;
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200621 for (size_t i = 0; i < encoder_factory_->encoders().size(); ++i) {
622 ASSERT_TRUE(encoder_factory_->encoders()[i]->WaitForInitEncode());
pbos@webrtc.orgf18fba22015-01-14 16:26:23 +0000623 webrtc::VideoCodec codec_settings =
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200624 encoder_factory_->encoders()[i]->GetCodecSettings();
pbos@webrtc.orgf18fba22015-01-14 16:26:23 +0000625 EXPECT_EQ(0, codec_settings.numberOfSimulcastStreams);
626 EXPECT_GT(codec_settings.width, prev_width);
627 prev_width = codec_settings.width;
628 }
pbos@webrtc.org86196c42015-02-16 21:02:00 +0000629
deadbeef5a4a75a2016-06-02 16:23:38 -0700630 EXPECT_TRUE(channel->SetVideoSend(ssrcs.front(), true, nullptr, nullptr));
pthatcher@webrtc.org818c4982015-03-06 02:20:58 +0000631
632 channel.reset();
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200633 ASSERT_EQ(0u, encoder_factory_->encoders().size());
pbos@webrtc.orgf18fba22015-01-14 16:26:23 +0000634}
635
eladalonf1841382017-06-12 01:16:46 -0700636TEST_F(WebRtcVideoEngineTest, ChannelWithExternalH264CanChangeToInternalVp8) {
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200637 encoder_factory_->AddSupportedVideoCodecType("H264");
pbos@webrtc.org7fe1e032014-10-14 04:25:33 +0000638
magjed2475ae22017-09-12 04:42:15 -0700639 std::unique_ptr<VideoMediaChannel> channel(SetUpForExternalEncoderFactory());
pbos@webrtc.org7fe1e032014-10-14 04:25:33 +0000640
641 EXPECT_TRUE(
642 channel->AddSendStream(cricket::StreamParams::CreateLegacy(kSsrc)));
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200643 ASSERT_EQ(1u, encoder_factory_->encoders().size());
pbos@webrtc.org7fe1e032014-10-14 04:25:33 +0000644
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200645 cricket::VideoSendParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -0800646 parameters.codecs.push_back(GetEngineCodec("VP8"));
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200647 EXPECT_TRUE(channel->SetSendParameters(parameters));
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200648 ASSERT_EQ(0u, encoder_factory_->encoders().size());
pbos@webrtc.org7fe1e032014-10-14 04:25:33 +0000649}
650
eladalonf1841382017-06-12 01:16:46 -0700651TEST_F(WebRtcVideoEngineTest,
pbos@webrtc.org7fe1e032014-10-14 04:25:33 +0000652 DontUseExternalEncoderFactoryForUnsupportedCodecs) {
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200653 encoder_factory_->AddSupportedVideoCodecType("H264");
pbos@webrtc.org7fe1e032014-10-14 04:25:33 +0000654
kwiberg686a8ef2016-02-26 03:00:35 -0800655 std::unique_ptr<VideoMediaChannel> channel(
kthelgason2bc68642017-02-07 07:02:22 -0800656 engine_.CreateChannel(call_.get(), GetMediaConfig(), VideoOptions()));
magjed509e4fe2016-11-18 01:34:11 -0800657 cricket::VideoSendParameters parameters;
658 parameters.codecs.push_back(GetEngineCodec("VP8"));
659 EXPECT_TRUE(channel->SetSendParameters(parameters));
pbos@webrtc.org7fe1e032014-10-14 04:25:33 +0000660
661 EXPECT_TRUE(
662 channel->AddSendStream(cricket::StreamParams::CreateLegacy(kSsrc)));
pthatcher@webrtc.org818c4982015-03-06 02:20:58 +0000663 // Make sure DestroyVideoEncoder was called on the factory.
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200664 ASSERT_EQ(0u, encoder_factory_->encoders().size());
pthatcher@webrtc.org818c4982015-03-06 02:20:58 +0000665}
666
eladalonf1841382017-06-12 01:16:46 -0700667TEST_F(WebRtcVideoEngineTest,
pthatcher@webrtc.org818c4982015-03-06 02:20:58 +0000668 UsesSimulcastAdapterForVp8WithCombinedVP8AndH264Factory) {
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200669 encoder_factory_->AddSupportedVideoCodecType("VP8");
670 encoder_factory_->AddSupportedVideoCodecType("H264");
pthatcher@webrtc.org818c4982015-03-06 02:20:58 +0000671
kwiberg686a8ef2016-02-26 03:00:35 -0800672 std::unique_ptr<VideoMediaChannel> channel(
kthelgason2bc68642017-02-07 07:02:22 -0800673 engine_.CreateChannel(call_.get(), GetMediaConfig(), VideoOptions()));
magjed509e4fe2016-11-18 01:34:11 -0800674 cricket::VideoSendParameters parameters;
675 parameters.codecs.push_back(GetEngineCodec("VP8"));
676 EXPECT_TRUE(channel->SetSendParameters(parameters));
pthatcher@webrtc.org818c4982015-03-06 02:20:58 +0000677
Peter Boström0c4e06b2015-10-07 12:23:21 +0200678 std::vector<uint32_t> ssrcs = MAKE_VECTOR(kSsrcs3);
pthatcher@webrtc.org818c4982015-03-06 02:20:58 +0000679
680 EXPECT_TRUE(
681 channel->AddSendStream(CreateSimStreamParams("cname", ssrcs)));
682 EXPECT_TRUE(channel->SetSend(true));
683
684 // Send a fake frame, or else the media engine will configure the simulcast
685 // encoder adapter at a low-enough size that it'll only create a single
686 // encoder layer.
687 cricket::FakeVideoCapturer capturer;
deadbeef5a4a75a2016-06-02 16:23:38 -0700688 EXPECT_TRUE(channel->SetVideoSend(ssrcs.front(), true, nullptr, &capturer));
pthatcher@webrtc.org818c4982015-03-06 02:20:58 +0000689 EXPECT_EQ(cricket::CS_RUNNING,
690 capturer.Start(capturer.GetSupportedFormats()->front()));
691 EXPECT_TRUE(capturer.CaptureFrame());
692
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200693 ASSERT_TRUE(encoder_factory_->WaitForCreatedVideoEncoders(2));
694 ASSERT_TRUE(encoder_factory_->encoders()[0]->WaitForInitEncode());
pthatcher@webrtc.org818c4982015-03-06 02:20:58 +0000695 EXPECT_EQ(webrtc::kVideoCodecVP8,
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200696 encoder_factory_->encoders()[0]->GetCodecSettings().codecType);
pthatcher@webrtc.org818c4982015-03-06 02:20:58 +0000697
698 channel.reset();
699 // Make sure DestroyVideoEncoder was called on the factory.
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200700 EXPECT_EQ(0u, encoder_factory_->encoders().size());
pthatcher@webrtc.org818c4982015-03-06 02:20:58 +0000701}
702
eladalonf1841382017-06-12 01:16:46 -0700703TEST_F(WebRtcVideoEngineTest,
pthatcher@webrtc.org818c4982015-03-06 02:20:58 +0000704 DestroysNonSimulcastEncoderFromCombinedVP8AndH264Factory) {
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200705 encoder_factory_->AddSupportedVideoCodecType("VP8");
706 encoder_factory_->AddSupportedVideoCodecType("H264");
pthatcher@webrtc.org818c4982015-03-06 02:20:58 +0000707
kwiberg686a8ef2016-02-26 03:00:35 -0800708 std::unique_ptr<VideoMediaChannel> channel(
kthelgason2bc68642017-02-07 07:02:22 -0800709 engine_.CreateChannel(call_.get(), GetMediaConfig(), VideoOptions()));
magjed509e4fe2016-11-18 01:34:11 -0800710 cricket::VideoSendParameters parameters;
711 parameters.codecs.push_back(GetEngineCodec("H264"));
712 EXPECT_TRUE(channel->SetSendParameters(parameters));
pthatcher@webrtc.org818c4982015-03-06 02:20:58 +0000713
714 EXPECT_TRUE(
715 channel->AddSendStream(cricket::StreamParams::CreateLegacy(kSsrc)));
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200716 ASSERT_EQ(1u, encoder_factory_->encoders().size());
Per21d45d22016-10-30 21:37:57 +0100717
718 // Send a frame of 720p. This should trigger a "real" encoder initialization.
719 cricket::VideoFormat format(
720 1280, 720, cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420);
721 cricket::FakeVideoCapturer capturer;
722 EXPECT_TRUE(channel->SetVideoSend(kSsrc, true, nullptr, &capturer));
723 EXPECT_EQ(cricket::CS_RUNNING, capturer.Start(format));
724 EXPECT_TRUE(capturer.CaptureFrame());
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200725 ASSERT_TRUE(encoder_factory_->encoders()[0]->WaitForInitEncode());
pthatcher@webrtc.org818c4982015-03-06 02:20:58 +0000726 EXPECT_EQ(webrtc::kVideoCodecH264,
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200727 encoder_factory_->encoders()[0]->GetCodecSettings().codecType);
pthatcher@webrtc.org818c4982015-03-06 02:20:58 +0000728
729 channel.reset();
730 // Make sure DestroyVideoEncoder was called on the factory.
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200731 ASSERT_EQ(0u, encoder_factory_->encoders().size());
pbos@webrtc.org7fe1e032014-10-14 04:25:33 +0000732}
733
eladalonf1841382017-06-12 01:16:46 -0700734TEST_F(WebRtcVideoEngineTest, SimulcastDisabledForH264) {
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200735 encoder_factory_->AddSupportedVideoCodecType("H264");
noahricfdac5162015-08-27 01:59:29 -0700736
magjed2475ae22017-09-12 04:42:15 -0700737 std::unique_ptr<VideoMediaChannel> channel(SetUpForExternalEncoderFactory());
noahricfdac5162015-08-27 01:59:29 -0700738
Peter Boström0c4e06b2015-10-07 12:23:21 +0200739 const std::vector<uint32_t> ssrcs = MAKE_VECTOR(kSsrcs3);
noahricfdac5162015-08-27 01:59:29 -0700740 EXPECT_TRUE(
741 channel->AddSendStream(cricket::CreateSimStreamParams("cname", ssrcs)));
Peter Boströmce23bee2016-02-02 14:14:30 +0100742
743 // Send a frame of 720p. This should trigger a "real" encoder initialization.
noahricfdac5162015-08-27 01:59:29 -0700744 cricket::VideoFormat format(
745 1280, 720, cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420);
Peter Boströmce23bee2016-02-02 14:14:30 +0100746 cricket::FakeVideoCapturer capturer;
deadbeef5a4a75a2016-06-02 16:23:38 -0700747 EXPECT_TRUE(channel->SetVideoSend(ssrcs[0], true, nullptr, &capturer));
Peter Boströmce23bee2016-02-02 14:14:30 +0100748 EXPECT_EQ(cricket::CS_RUNNING, capturer.Start(format));
749 EXPECT_TRUE(capturer.CaptureFrame());
750
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200751 ASSERT_EQ(1u, encoder_factory_->encoders().size());
752 FakeWebRtcVideoEncoder* encoder = encoder_factory_->encoders()[0];
753 ASSERT_TRUE(encoder_factory_->encoders()[0]->WaitForInitEncode());
noahricfdac5162015-08-27 01:59:29 -0700754 EXPECT_EQ(webrtc::kVideoCodecH264, encoder->GetCodecSettings().codecType);
755 EXPECT_EQ(1u, encoder->GetCodecSettings().numberOfSimulcastStreams);
deadbeef5a4a75a2016-06-02 16:23:38 -0700756 EXPECT_TRUE(channel->SetVideoSend(ssrcs[0], true, nullptr, nullptr));
noahricfdac5162015-08-27 01:59:29 -0700757}
758
brandtrffc61182016-11-28 06:02:22 -0800759// Test that the FlexFEC field trial properly alters the output of
eladalonf1841382017-06-12 01:16:46 -0700760// WebRtcVideoEngine::codecs(), for an existing |engine_| object.
brandtrffc61182016-11-28 06:02:22 -0800761//
762// TODO(brandtr): Remove this test, when the FlexFEC field trial is gone.
eladalonf1841382017-06-12 01:16:46 -0700763TEST_F(WebRtcVideoEngineTest,
brandtrffc61182016-11-28 06:02:22 -0800764 Flexfec03SupportedAsInternalCodecBehindFieldTrial) {
765 auto is_flexfec = [](const VideoCodec& codec) {
766 if (codec.name == "flexfec-03")
767 return true;
768 return false;
769 };
770
771 // FlexFEC is not active without field trial.
brandtrffc61182016-11-28 06:02:22 -0800772 const std::vector<VideoCodec> codecs_before = engine_.codecs();
773 EXPECT_EQ(codecs_before.end(), std::find_if(codecs_before.begin(),
774 codecs_before.end(), is_flexfec));
775
776 // FlexFEC is active with field trial.
777 webrtc::test::ScopedFieldTrials override_field_trials_(
brandtr340e3fd2017-02-28 15:43:10 -0800778 "WebRTC-FlexFEC-03-Advertised/Enabled/");
brandtrffc61182016-11-28 06:02:22 -0800779 const std::vector<VideoCodec> codecs_after = engine_.codecs();
780 EXPECT_NE(codecs_after.end(),
781 std::find_if(codecs_after.begin(), codecs_after.end(), is_flexfec));
782}
783
hbosbab934b2016-01-27 01:36:03 -0800784// Test that external codecs are added to the end of the supported codec list.
eladalonf1841382017-06-12 01:16:46 -0700785TEST_F(WebRtcVideoEngineTest, ReportSupportedExternalCodecs) {
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200786 encoder_factory_->AddSupportedVideoCodecType("FakeExternalCodec");
pbos@webrtc.org7fe1e032014-10-14 04:25:33 +0000787
788 std::vector<cricket::VideoCodec> codecs(engine_.codecs());
789 ASSERT_GE(codecs.size(), 2u);
minyuef032e402017-07-17 08:45:17 -0700790 cricket::VideoCodec internal_codec = codecs.front();
791 cricket::VideoCodec external_codec = codecs.back();
pbos@webrtc.org7fe1e032014-10-14 04:25:33 +0000792
minyuef032e402017-07-17 08:45:17 -0700793 // The external codec will appear last in the vector.
magjed06f3aae2017-07-14 10:36:23 -0700794 EXPECT_EQ("VP8", internal_codec.name);
minyuef032e402017-07-17 08:45:17 -0700795 EXPECT_EQ("FakeExternalCodec", external_codec.name);
pbos@webrtc.org7fe1e032014-10-14 04:25:33 +0000796}
797
brandtrffc61182016-11-28 06:02:22 -0800798// Test that an external codec that was added after the engine was initialized
799// does show up in the codec list after it was added.
eladalonf1841382017-06-12 01:16:46 -0700800TEST_F(WebRtcVideoEngineTest, ReportSupportedExternalCodecsWithAddedCodec) {
brandtrffc61182016-11-28 06:02:22 -0800801 // Set up external encoder factory with first codec, and initialize engine.
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200802 encoder_factory_->AddSupportedVideoCodecType("FakeExternalCodec1");
brandtrffc61182016-11-28 06:02:22 -0800803
minyuef032e402017-07-17 08:45:17 -0700804 // The first external codec will appear last in the vector.
brandtrffc61182016-11-28 06:02:22 -0800805 std::vector<cricket::VideoCodec> codecs_before(engine_.codecs());
minyuef032e402017-07-17 08:45:17 -0700806 EXPECT_EQ("FakeExternalCodec1", codecs_before.back().name);
brandtrffc61182016-11-28 06:02:22 -0800807
808 // Add second codec.
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200809 encoder_factory_->AddSupportedVideoCodecType("FakeExternalCodec2");
brandtrffc61182016-11-28 06:02:22 -0800810 std::vector<cricket::VideoCodec> codecs_after(engine_.codecs());
811 EXPECT_EQ(codecs_before.size() + 1, codecs_after.size());
minyuef032e402017-07-17 08:45:17 -0700812 EXPECT_EQ("FakeExternalCodec2", codecs_after.back().name);
brandtrffc61182016-11-28 06:02:22 -0800813}
814
eladalonf1841382017-06-12 01:16:46 -0700815TEST_F(WebRtcVideoEngineTest, RegisterExternalDecodersIfSupported) {
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200816 decoder_factory_->AddSupportedVideoCodecType(webrtc::kVideoCodecVP8);
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200817 cricket::VideoRecvParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -0800818 parameters.codecs.push_back(GetEngineCodec("VP8"));
pbos@webrtc.org96a93252014-11-03 14:46:44 +0000819
kwiberg686a8ef2016-02-26 03:00:35 -0800820 std::unique_ptr<VideoMediaChannel> channel(
magjed2475ae22017-09-12 04:42:15 -0700821 SetUpForExternalDecoderFactory(parameters.codecs));
pbos@webrtc.org96a93252014-11-03 14:46:44 +0000822
823 EXPECT_TRUE(
824 channel->AddRecvStream(cricket::StreamParams::CreateLegacy(kSsrc)));
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200825 ASSERT_EQ(1u, decoder_factory_->decoders().size());
pbos@webrtc.org96a93252014-11-03 14:46:44 +0000826
827 // Setting codecs of the same type should not reallocate the decoder.
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200828 EXPECT_TRUE(channel->SetRecvParameters(parameters));
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200829 EXPECT_EQ(1, decoder_factory_->GetNumCreatedDecoders());
pbos@webrtc.org96a93252014-11-03 14:46:44 +0000830
831 // Remove stream previously added to free the external decoder instance.
832 EXPECT_TRUE(channel->RemoveRecvStream(kSsrc));
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200833 EXPECT_EQ(0u, decoder_factory_->decoders().size());
pbos@webrtc.org96a93252014-11-03 14:46:44 +0000834}
835
836// Verifies that we can set up decoders that are not internally supported.
eladalonf1841382017-06-12 01:16:46 -0700837TEST_F(WebRtcVideoEngineTest, RegisterExternalH264DecoderIfSupported) {
pbos@webrtc.org96a93252014-11-03 14:46:44 +0000838 // TODO(pbos): Do not assume that encoder/decoder support is symmetric. We
839 // can't even query the WebRtcVideoDecoderFactory for supported codecs.
840 // For now we add a FakeWebRtcVideoEncoderFactory to add H264 to supported
841 // codecs.
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200842 encoder_factory_->AddSupportedVideoCodecType("H264");
843 decoder_factory_->AddSupportedVideoCodecType(webrtc::kVideoCodecH264);
pbos@webrtc.org96a93252014-11-03 14:46:44 +0000844 std::vector<cricket::VideoCodec> codecs;
magjed509e4fe2016-11-18 01:34:11 -0800845 codecs.push_back(GetEngineCodec("H264"));
pbos@webrtc.org96a93252014-11-03 14:46:44 +0000846
kwiberg686a8ef2016-02-26 03:00:35 -0800847 std::unique_ptr<VideoMediaChannel> channel(
magjed2475ae22017-09-12 04:42:15 -0700848 SetUpForExternalDecoderFactory(codecs));
pbos@webrtc.org96a93252014-11-03 14:46:44 +0000849
850 EXPECT_TRUE(
851 channel->AddRecvStream(cricket::StreamParams::CreateLegacy(kSsrc)));
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200852 ASSERT_EQ(1u, decoder_factory_->decoders().size());
pbos@webrtc.org96a93252014-11-03 14:46:44 +0000853}
854
Magnus Jedvertd4b0c052017-09-14 10:24:54 +0200855class MockVideoEncoderFactory : public webrtc::VideoEncoderFactory {
856 public:
857 MOCK_CONST_METHOD0(GetSupportedFormats,
858 std::vector<webrtc::SdpVideoFormat>());
859 MOCK_CONST_METHOD1(QueryVideoEncoder,
860 CodecInfo(const webrtc::SdpVideoFormat&));
861
862 // We need to proxy to a return type that is copyable.
863 std::unique_ptr<webrtc::VideoEncoder> CreateVideoEncoder(
864 const webrtc::SdpVideoFormat& format) {
865 return std::unique_ptr<webrtc::VideoEncoder>(
866 CreateVideoEncoderProxy(format));
867 }
868 MOCK_METHOD1(CreateVideoEncoderProxy,
869 webrtc::VideoEncoder*(const webrtc::SdpVideoFormat&));
870
871 MOCK_METHOD0(Die, void());
872 ~MockVideoEncoderFactory() { Die(); }
873};
874
875class MockVideoDecoderFactory : public webrtc::VideoDecoderFactory {
876 public:
877 MOCK_CONST_METHOD0(GetSupportedFormats,
878 std::vector<webrtc::SdpVideoFormat>());
879
880 // We need to proxy to a return type that is copyable.
881 std::unique_ptr<webrtc::VideoDecoder> CreateVideoDecoder(
882 const webrtc::SdpVideoFormat& format) {
883 return std::unique_ptr<webrtc::VideoDecoder>(
884 CreateVideoDecoderProxy(format));
885 }
886 MOCK_METHOD1(CreateVideoDecoderProxy,
887 webrtc::VideoDecoder*(const webrtc::SdpVideoFormat&));
888
889 MOCK_METHOD0(Die, void());
890 ~MockVideoDecoderFactory() { Die(); }
891};
892
893TEST(WebRtcVideoEngineNewVideoCodecFactoryTest, NullFactories) {
894 std::unique_ptr<webrtc::VideoEncoderFactory> encoder_factory;
895 std::unique_ptr<webrtc::VideoDecoderFactory> decoder_factory;
896 WebRtcVideoEngine engine(std::move(encoder_factory),
897 std::move(decoder_factory));
898 EXPECT_EQ(0u, engine.codecs().size());
899}
900
901TEST(WebRtcVideoEngineNewVideoCodecFactoryTest, EmptyFactories) {
902 // |engine| take ownership of the factories.
903 MockVideoEncoderFactory* encoder_factory = new MockVideoEncoderFactory();
904 MockVideoDecoderFactory* decoder_factory = new MockVideoDecoderFactory();
905 WebRtcVideoEngine engine(
906 (std::unique_ptr<webrtc::VideoEncoderFactory>(encoder_factory)),
907 (std::unique_ptr<webrtc::VideoDecoderFactory>(decoder_factory)));
908 EXPECT_CALL(*encoder_factory, GetSupportedFormats());
909 EXPECT_EQ(0u, engine.codecs().size());
910 EXPECT_CALL(*encoder_factory, Die());
911 EXPECT_CALL(*decoder_factory, Die());
912}
913
914// Test full behavior in the video engine when video codec factories of the new
915// type are injected supporting the single codec Vp8. Check the returned codecs
916// from the engine and that we will create a Vp8 encoder and decoder using the
917// new factories.
918TEST(WebRtcVideoEngineNewVideoCodecFactoryTest, Vp8) {
919 // |engine| take ownership of the factories.
920 MockVideoEncoderFactory* encoder_factory = new MockVideoEncoderFactory();
921 MockVideoDecoderFactory* decoder_factory = new MockVideoDecoderFactory();
922 WebRtcVideoEngine engine(
923 (std::unique_ptr<webrtc::VideoEncoderFactory>(encoder_factory)),
924 (std::unique_ptr<webrtc::VideoDecoderFactory>(decoder_factory)));
925 const webrtc::SdpVideoFormat vp8_format("VP8");
926 const std::vector<webrtc::SdpVideoFormat> supported_formats = {vp8_format};
927 EXPECT_CALL(*encoder_factory, GetSupportedFormats())
928 .WillRepeatedly(testing::Return(supported_formats));
929
930 // Verify the codecs from the engine.
931 const std::vector<VideoCodec> engine_codecs = engine.codecs();
932 // Verify an RTX codec has been added correctly.
933 EXPECT_EQ(2u, engine_codecs.size());
934 EXPECT_EQ("VP8", engine_codecs.at(0).name);
935 EXPECT_EQ("rtx", engine_codecs.at(1).name);
936 int associated_payload_type;
937 EXPECT_TRUE(engine_codecs.at(1).GetParam(
938 cricket::kCodecParamAssociatedPayloadType, &associated_payload_type));
939 EXPECT_EQ(engine_codecs.at(0).id, associated_payload_type);
940 // Verify default parameters has been added to the VP8 codec.
941 VerifyCodecHasDefaultFeedbackParams(engine_codecs.at(0));
942
943 // Mock encoder creation. |engine| take ownership of the encoder.
944 webrtc::VideoEncoderFactory::CodecInfo codec_info;
945 codec_info.is_hardware_accelerated = false;
946 codec_info.has_internal_source = false;
947 const webrtc::SdpVideoFormat format("VP8");
948 EXPECT_CALL(*encoder_factory, QueryVideoEncoder(format))
949 .WillRepeatedly(testing::Return(codec_info));
950 FakeWebRtcVideoEncoder* const encoder = new FakeWebRtcVideoEncoder();
951 EXPECT_CALL(*encoder_factory, CreateVideoEncoderProxy(format))
952 .WillOnce(testing::Return(encoder));
953
954 // Mock decoder creation. |engine| take ownership of the decoder.
955 FakeWebRtcVideoDecoder* const decoder = new FakeWebRtcVideoDecoder();
956 EXPECT_CALL(*decoder_factory, CreateVideoDecoderProxy(format))
957 .WillOnce(testing::Return(decoder));
958
959 // Create a call.
960 webrtc::RtcEventLogNullImpl event_log;
961 std::unique_ptr<webrtc::Call> call(
962 webrtc::Call::Create(webrtc::Call::Config(&event_log)));
963
964 // Create send channel.
965 const int send_ssrc = 123;
966 std::unique_ptr<VideoMediaChannel> send_channel(
967 engine.CreateChannel(call.get(), GetMediaConfig(), VideoOptions()));
968 cricket::VideoSendParameters send_parameters;
969 send_parameters.codecs.push_back(engine_codecs.at(0));
970 EXPECT_TRUE(send_channel->SetSendParameters(send_parameters));
971 send_channel->OnReadyToSend(true);
972 EXPECT_TRUE(
973 send_channel->AddSendStream(StreamParams::CreateLegacy(send_ssrc)));
974 EXPECT_TRUE(send_channel->SetSend(true));
975
976 // Create recv channel.
977 const int recv_ssrc = 321;
978 std::unique_ptr<VideoMediaChannel> recv_channel(
979 engine.CreateChannel(call.get(), GetMediaConfig(), VideoOptions()));
980 cricket::VideoRecvParameters recv_parameters;
981 recv_parameters.codecs.push_back(engine_codecs.at(0));
982 EXPECT_TRUE(recv_channel->SetRecvParameters(recv_parameters));
983 EXPECT_TRUE(recv_channel->AddRecvStream(
984 cricket::StreamParams::CreateLegacy(recv_ssrc)));
985
986 // Remove streams previously added to free the encoder and decoder instance.
987 EXPECT_CALL(*encoder_factory, Die());
988 EXPECT_CALL(*decoder_factory, Die());
989 EXPECT_TRUE(send_channel->RemoveSendStream(send_ssrc));
990 EXPECT_TRUE(recv_channel->RemoveRecvStream(recv_ssrc));
991}
992
eladalonf1841382017-06-12 01:16:46 -0700993class WebRtcVideoChannelBaseTest
994 : public VideoMediaChannelTest<WebRtcVideoEngine, WebRtcVideoChannel> {
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +0000995 protected:
eladalonf1841382017-06-12 01:16:46 -0700996 typedef VideoMediaChannelTest<WebRtcVideoEngine, WebRtcVideoChannel> Base;
pbos@webrtc.org42684be2014-10-03 11:25:45 +0000997
magjed509e4fe2016-11-18 01:34:11 -0800998 cricket::VideoCodec GetEngineCodec(const std::string& name) {
999 for (const cricket::VideoCodec& engine_codec : engine_.codecs()) {
1000 if (CodecNamesEq(name, engine_codec.name))
1001 return engine_codec;
1002 }
1003 // This point should never be reached.
1004 ADD_FAILURE() << "Unrecognized codec name: " << name;
1005 return cricket::VideoCodec();
1006 }
1007
1008 cricket::VideoCodec DefaultCodec() override { return GetEngineCodec("VP8"); }
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001009};
1010
sakal1fd95952016-06-22 00:46:15 -07001011// Verifies that id given in stream params is passed to the decoder factory.
eladalonf1841382017-06-12 01:16:46 -07001012TEST_F(WebRtcVideoEngineTest, StreamParamsIdPassedToDecoderFactory) {
Magnus Jedvert02e7a192017-09-23 17:21:32 +02001013 decoder_factory_->AddSupportedVideoCodecType(webrtc::kVideoCodecVP8);
sakal1fd95952016-06-22 00:46:15 -07001014 cricket::VideoRecvParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08001015 parameters.codecs.push_back(GetEngineCodec("VP8"));
sakal1fd95952016-06-22 00:46:15 -07001016
1017 std::unique_ptr<VideoMediaChannel> channel(
magjed2475ae22017-09-12 04:42:15 -07001018 SetUpForExternalDecoderFactory(parameters.codecs));
sakal1fd95952016-06-22 00:46:15 -07001019
1020 StreamParams sp = cricket::StreamParams::CreateLegacy(kSsrc);
1021 sp.id = "FakeStreamParamsId";
1022 EXPECT_TRUE(channel->AddRecvStream(sp));
Magnus Jedvert02e7a192017-09-23 17:21:32 +02001023 EXPECT_EQ(1u, decoder_factory_->decoders().size());
sakal1fd95952016-06-22 00:46:15 -07001024
Magnus Jedvert02e7a192017-09-23 17:21:32 +02001025 std::vector<cricket::VideoDecoderParams> params = decoder_factory_->params();
sakal1fd95952016-06-22 00:46:15 -07001026 ASSERT_EQ(1u, params.size());
1027 EXPECT_EQ(sp.id, params[0].receive_stream_id);
1028}
1029
eladalonf1841382017-06-12 01:16:46 -07001030TEST_F(WebRtcVideoEngineTest, DISABLED_RecreatesEncoderOnContentTypeChange) {
Magnus Jedvert02e7a192017-09-23 17:21:32 +02001031 encoder_factory_->AddSupportedVideoCodecType("VP8");
sprangf24a0642017-02-28 13:23:26 -08001032 std::unique_ptr<FakeCall> fake_call(
1033 new FakeCall(webrtc::Call::Config(&event_log_)));
magjed2475ae22017-09-12 04:42:15 -07001034 std::unique_ptr<VideoMediaChannel> channel(SetUpForExternalEncoderFactory());
sprangf24a0642017-02-28 13:23:26 -08001035 ASSERT_TRUE(
1036 channel->AddSendStream(cricket::StreamParams::CreateLegacy(kSsrc)));
1037 cricket::VideoCodec codec = GetEngineCodec("VP8");
1038 cricket::VideoSendParameters parameters;
1039 parameters.codecs.push_back(codec);
1040 channel->OnReadyToSend(true);
1041 channel->SetSend(true);
1042 ASSERT_TRUE(channel->SetSendParameters(parameters));
1043
1044 cricket::FakeVideoCapturer capturer;
1045 VideoOptions options;
1046 EXPECT_TRUE(channel->SetVideoSend(kSsrc, true, &options, &capturer));
1047
1048 EXPECT_EQ(cricket::CS_RUNNING,
1049 capturer.Start(capturer.GetSupportedFormats()->front()));
1050 EXPECT_TRUE(capturer.CaptureFrame());
Magnus Jedvert02e7a192017-09-23 17:21:32 +02001051 ASSERT_TRUE(encoder_factory_->WaitForCreatedVideoEncoders(1));
sprangf24a0642017-02-28 13:23:26 -08001052 EXPECT_EQ(webrtc::kRealtimeVideo,
Magnus Jedvert02e7a192017-09-23 17:21:32 +02001053 encoder_factory_->encoders().back()->GetCodecSettings().mode);
sprangf24a0642017-02-28 13:23:26 -08001054
1055 EXPECT_TRUE(channel->SetVideoSend(kSsrc, true, &options, &capturer));
1056 EXPECT_TRUE(capturer.CaptureFrame());
1057 // No change in content type, keep current encoder.
Magnus Jedvert02e7a192017-09-23 17:21:32 +02001058 EXPECT_EQ(1, encoder_factory_->GetNumCreatedEncoders());
sprangf24a0642017-02-28 13:23:26 -08001059
1060 options.is_screencast.emplace(true);
1061 EXPECT_TRUE(channel->SetVideoSend(kSsrc, true, &options, &capturer));
1062 EXPECT_TRUE(capturer.CaptureFrame());
1063 // Change to screen content, recreate encoder. For the simulcast encoder
1064 // adapter case, this will result in two calls since InitEncode triggers a
1065 // a new instance.
Magnus Jedvert02e7a192017-09-23 17:21:32 +02001066 ASSERT_TRUE(encoder_factory_->WaitForCreatedVideoEncoders(2));
sprangf24a0642017-02-28 13:23:26 -08001067 EXPECT_EQ(webrtc::kScreensharing,
Magnus Jedvert02e7a192017-09-23 17:21:32 +02001068 encoder_factory_->encoders().back()->GetCodecSettings().mode);
sprangf24a0642017-02-28 13:23:26 -08001069
1070 EXPECT_TRUE(channel->SetVideoSend(kSsrc, true, &options, &capturer));
1071 EXPECT_TRUE(capturer.CaptureFrame());
1072 // Still screen content, no need to update encoder.
Magnus Jedvert02e7a192017-09-23 17:21:32 +02001073 EXPECT_EQ(2, encoder_factory_->GetNumCreatedEncoders());
sprangf24a0642017-02-28 13:23:26 -08001074
1075 options.is_screencast.emplace(false);
1076 options.video_noise_reduction.emplace(false);
1077 EXPECT_TRUE(channel->SetVideoSend(kSsrc, true, &options, &capturer));
1078 // Change back to regular video content, update encoder. Also change
1079 // a non |is_screencast| option just to verify it doesn't affect recreation.
1080 EXPECT_TRUE(capturer.CaptureFrame());
Magnus Jedvert02e7a192017-09-23 17:21:32 +02001081 ASSERT_TRUE(encoder_factory_->WaitForCreatedVideoEncoders(3));
sprangf24a0642017-02-28 13:23:26 -08001082 EXPECT_EQ(webrtc::kRealtimeVideo,
Magnus Jedvert02e7a192017-09-23 17:21:32 +02001083 encoder_factory_->encoders().back()->GetCodecSettings().mode);
sprangf24a0642017-02-28 13:23:26 -08001084
1085 // Remove stream previously added to free the external encoder instance.
1086 EXPECT_TRUE(channel->RemoveSendStream(kSsrc));
Magnus Jedvert02e7a192017-09-23 17:21:32 +02001087 EXPECT_EQ(0u, encoder_factory_->encoders().size());
sprangf24a0642017-02-28 13:23:26 -08001088}
1089
pbos@webrtc.org8fdeee62014-07-20 14:40:23 +00001090#define WEBRTC_BASE_TEST(test) \
eladalonf1841382017-06-12 01:16:46 -07001091 TEST_F(WebRtcVideoChannelBaseTest, test) { Base::test(); }
pbos@webrtc.org8fdeee62014-07-20 14:40:23 +00001092
1093#define WEBRTC_DISABLED_BASE_TEST(test) \
eladalonf1841382017-06-12 01:16:46 -07001094 TEST_F(WebRtcVideoChannelBaseTest, DISABLED_##test) { Base::test(); }
pbos@webrtc.org8fdeee62014-07-20 14:40:23 +00001095
pbos@webrtc.org8fdeee62014-07-20 14:40:23 +00001096WEBRTC_BASE_TEST(SetSend);
1097WEBRTC_BASE_TEST(SetSendWithoutCodecs);
1098WEBRTC_BASE_TEST(SetSendSetsTransportBufferSizes);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001099
pbos@webrtc.org8fdeee62014-07-20 14:40:23 +00001100WEBRTC_BASE_TEST(GetStats);
1101WEBRTC_BASE_TEST(GetStatsMultipleRecvStreams);
1102WEBRTC_BASE_TEST(GetStatsMultipleSendStreams);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001103
pbos@webrtc.org8fdeee62014-07-20 14:40:23 +00001104WEBRTC_BASE_TEST(SetSendBandwidth);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001105
pbos@webrtc.org8fdeee62014-07-20 14:40:23 +00001106WEBRTC_BASE_TEST(SetSendSsrc);
1107WEBRTC_BASE_TEST(SetSendSsrcAfterSetCodecs);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001108
nisse08582ff2016-02-04 01:24:52 -08001109WEBRTC_BASE_TEST(SetSink);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001110
pbos@webrtc.org8fdeee62014-07-20 14:40:23 +00001111WEBRTC_BASE_TEST(AddRemoveSendStreams);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001112
pbos@webrtc.org8fdeee62014-07-20 14:40:23 +00001113WEBRTC_BASE_TEST(SimulateConference);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001114
Alejandro Luebs947c02d2016-06-15 15:39:46 -07001115WEBRTC_DISABLED_BASE_TEST(AddRemoveCapturer);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001116
pbos@webrtc.org8fdeee62014-07-20 14:40:23 +00001117WEBRTC_BASE_TEST(RemoveCapturerWithoutAdd);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001118
pbos@webrtc.org8fdeee62014-07-20 14:40:23 +00001119WEBRTC_BASE_TEST(AddRemoveCapturerMultipleSources);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001120
pbos@webrtc.org8fdeee62014-07-20 14:40:23 +00001121WEBRTC_BASE_TEST(RejectEmptyStreamParams);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001122
pbos@webrtc.orgc4175b92014-09-03 15:25:49 +00001123WEBRTC_BASE_TEST(MultipleSendStreams);
1124
eladalonf1841382017-06-12 01:16:46 -07001125TEST_F(WebRtcVideoChannelBaseTest, SendAndReceiveVp8Vga) {
magjed509e4fe2016-11-18 01:34:11 -08001126 SendAndReceive(GetEngineCodec("VP8"));
pbos@webrtc.org9359cb32014-07-23 15:44:48 +00001127}
1128
eladalonf1841382017-06-12 01:16:46 -07001129TEST_F(WebRtcVideoChannelBaseTest, SendAndReceiveVp8Qvga) {
magjed509e4fe2016-11-18 01:34:11 -08001130 SendAndReceive(GetEngineCodec("VP8"));
pbos@webrtc.org9359cb32014-07-23 15:44:48 +00001131}
1132
eladalonf1841382017-06-12 01:16:46 -07001133TEST_F(WebRtcVideoChannelBaseTest, SendAndReceiveVp8SvcQqvga) {
magjed509e4fe2016-11-18 01:34:11 -08001134 SendAndReceive(GetEngineCodec("VP8"));
pbos@webrtc.org9359cb32014-07-23 15:44:48 +00001135}
1136
eladalonf1841382017-06-12 01:16:46 -07001137TEST_F(WebRtcVideoChannelBaseTest, TwoStreamsSendAndReceive) {
Peter Boströmd1f584b2016-04-20 16:31:53 +02001138 // Set a high bitrate to not be downscaled by VP8 due to low initial start
1139 // bitrates. This currently happens at <250k, and two streams sharing 300k
1140 // initially will use QVGA instead of VGA.
1141 // TODO(pbos): Set up the quality scaler so that both senders reliably start
1142 // at QVGA, then verify that instead.
magjed509e4fe2016-11-18 01:34:11 -08001143 cricket::VideoCodec codec = GetEngineCodec("VP8");
Peter Boströmd1f584b2016-04-20 16:31:53 +02001144 codec.params[kCodecParamStartBitrate] = "1000000";
1145 Base::TwoStreamsSendAndReceive(codec);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001146}
1147
eladalonf1841382017-06-12 01:16:46 -07001148class WebRtcVideoChannelTest : public WebRtcVideoEngineTest {
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001149 public:
eladalonf1841382017-06-12 01:16:46 -07001150 WebRtcVideoChannelTest() : WebRtcVideoChannelTest("") {}
1151 explicit WebRtcVideoChannelTest(const char* field_trials)
1152 : WebRtcVideoEngineTest(field_trials), last_ssrc_(0) {}
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001153 void SetUp() override {
skvlad11a9cbf2016-10-07 11:53:05 -07001154 fake_call_.reset(new FakeCall(webrtc::Call::Config(&event_log_)));
kthelgason2bc68642017-02-07 07:02:22 -08001155 channel_.reset(engine_.CreateChannel(fake_call_.get(), GetMediaConfig(),
1156 VideoOptions()));
Sergey Ulanove2b15012016-11-22 16:08:30 -08001157 channel_->OnReadyToSend(true);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001158 last_ssrc_ = 123;
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001159 send_parameters_.codecs = engine_.codecs();
1160 recv_parameters_.codecs = engine_.codecs();
1161 ASSERT_TRUE(channel_->SetSendParameters(send_parameters_));
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001162 }
1163
1164 protected:
1165 FakeVideoSendStream* AddSendStream() {
pbos@webrtc.org42684be2014-10-03 11:25:45 +00001166 return AddSendStream(StreamParams::CreateLegacy(++last_ssrc_));
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001167 }
1168
1169 FakeVideoSendStream* AddSendStream(const StreamParams& sp) {
pbos@webrtc.org42684be2014-10-03 11:25:45 +00001170 size_t num_streams = fake_call_->GetVideoSendStreams().size();
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001171 EXPECT_TRUE(channel_->AddSendStream(sp));
1172 std::vector<FakeVideoSendStream*> streams =
pbos@webrtc.org42684be2014-10-03 11:25:45 +00001173 fake_call_->GetVideoSendStreams();
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001174 EXPECT_EQ(num_streams + 1, streams.size());
1175 return streams[streams.size() - 1];
1176 }
1177
1178 std::vector<FakeVideoSendStream*> GetFakeSendStreams() {
pbos@webrtc.org42684be2014-10-03 11:25:45 +00001179 return fake_call_->GetVideoSendStreams();
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001180 }
1181
1182 FakeVideoReceiveStream* AddRecvStream() {
pbos@webrtc.org42684be2014-10-03 11:25:45 +00001183 return AddRecvStream(StreamParams::CreateLegacy(++last_ssrc_));
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001184 }
1185
1186 FakeVideoReceiveStream* AddRecvStream(const StreamParams& sp) {
pbos@webrtc.org42684be2014-10-03 11:25:45 +00001187 size_t num_streams = fake_call_->GetVideoReceiveStreams().size();
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001188 EXPECT_TRUE(channel_->AddRecvStream(sp));
1189 std::vector<FakeVideoReceiveStream*> streams =
pbos@webrtc.org42684be2014-10-03 11:25:45 +00001190 fake_call_->GetVideoReceiveStreams();
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001191 EXPECT_EQ(num_streams + 1, streams.size());
1192 return streams[streams.size() - 1];
1193 }
1194
pbos@webrtc.org00873182014-11-25 14:03:34 +00001195 void SetSendCodecsShouldWorkForBitrates(const char* min_bitrate_kbps,
1196 int expected_min_bitrate_bps,
1197 const char* start_bitrate_kbps,
1198 int expected_start_bitrate_bps,
1199 const char* max_bitrate_kbps,
1200 int expected_max_bitrate_bps) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001201 auto& codecs = send_parameters_.codecs;
1202 codecs.clear();
magjed509e4fe2016-11-18 01:34:11 -08001203 codecs.push_back(GetEngineCodec("VP8"));
pbos@webrtc.org00873182014-11-25 14:03:34 +00001204 codecs[0].params[kCodecParamMinBitrate] = min_bitrate_kbps;
1205 codecs[0].params[kCodecParamStartBitrate] = start_bitrate_kbps;
1206 codecs[0].params[kCodecParamMaxBitrate] = max_bitrate_kbps;
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001207 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001208
pbos@webrtc.org00873182014-11-25 14:03:34 +00001209 EXPECT_EQ(expected_min_bitrate_bps,
Stefan Holmere5904162015-03-26 11:11:06 +01001210 fake_call_->GetConfig().bitrate_config.min_bitrate_bps);
pbos@webrtc.org00873182014-11-25 14:03:34 +00001211 EXPECT_EQ(expected_start_bitrate_bps,
Stefan Holmere5904162015-03-26 11:11:06 +01001212 fake_call_->GetConfig().bitrate_config.start_bitrate_bps);
pbos@webrtc.org00873182014-11-25 14:03:34 +00001213 EXPECT_EQ(expected_max_bitrate_bps,
Stefan Holmere5904162015-03-26 11:11:06 +01001214 fake_call_->GetConfig().bitrate_config.max_bitrate_bps);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001215 }
1216
isheriff6f8d6862016-05-26 11:24:55 -07001217 void TestSetSendRtpHeaderExtensions(const std::string& ext_uri) {
pbos@webrtc.org587ef602014-06-16 17:32:02 +00001218 // Enable extension.
1219 const int id = 1;
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001220 cricket::VideoSendParameters parameters = send_parameters_;
isheriff6f8d6862016-05-26 11:24:55 -07001221 parameters.extensions.push_back(RtpExtension(ext_uri, id));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001222 EXPECT_TRUE(channel_->SetSendParameters(parameters));
pbos@webrtc.org587ef602014-06-16 17:32:02 +00001223 FakeVideoSendStream* send_stream =
1224 AddSendStream(cricket::StreamParams::CreateLegacy(123));
1225
1226 // Verify the send extension id.
1227 ASSERT_EQ(1u, send_stream->GetConfig().rtp.extensions.size());
1228 EXPECT_EQ(id, send_stream->GetConfig().rtp.extensions[0].id);
isheriff6f8d6862016-05-26 11:24:55 -07001229 EXPECT_EQ(ext_uri, send_stream->GetConfig().rtp.extensions[0].uri);
pbos@webrtc.org587ef602014-06-16 17:32:02 +00001230 // Verify call with same set of extensions returns true.
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001231 EXPECT_TRUE(channel_->SetSendParameters(parameters));
pbos@webrtc.org587ef602014-06-16 17:32:02 +00001232 // Verify that SetSendRtpHeaderExtensions doesn't implicitly add them for
1233 // receivers.
1234 EXPECT_TRUE(AddRecvStream(cricket::StreamParams::CreateLegacy(123))
1235 ->GetConfig()
1236 .rtp.extensions.empty());
1237
pbos@webrtc.orgd1ea06b2014-07-18 09:35:58 +00001238 // Verify that existing RTP header extensions can be removed.
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001239 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
Fredrik Solenberg709ed672015-09-15 12:26:33 +02001240 ASSERT_EQ(1u, fake_call_->GetVideoSendStreams().size());
1241 send_stream = fake_call_->GetVideoSendStreams()[0];
pbos@webrtc.orgd1ea06b2014-07-18 09:35:58 +00001242 EXPECT_TRUE(send_stream->GetConfig().rtp.extensions.empty());
1243
1244 // Verify that adding receive RTP header extensions adds them for existing
1245 // streams.
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001246 EXPECT_TRUE(channel_->SetSendParameters(parameters));
Fredrik Solenberg709ed672015-09-15 12:26:33 +02001247 send_stream = fake_call_->GetVideoSendStreams()[0];
pbos@webrtc.orgd1ea06b2014-07-18 09:35:58 +00001248 ASSERT_EQ(1u, send_stream->GetConfig().rtp.extensions.size());
1249 EXPECT_EQ(id, send_stream->GetConfig().rtp.extensions[0].id);
isheriff6f8d6862016-05-26 11:24:55 -07001250 EXPECT_EQ(ext_uri, send_stream->GetConfig().rtp.extensions[0].uri);
pbos@webrtc.org587ef602014-06-16 17:32:02 +00001251 }
1252
isheriff6f8d6862016-05-26 11:24:55 -07001253 void TestSetRecvRtpHeaderExtensions(const std::string& ext_uri) {
pbos@webrtc.org587ef602014-06-16 17:32:02 +00001254 // Enable extension.
1255 const int id = 1;
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001256 cricket::VideoRecvParameters parameters = recv_parameters_;
isheriff6f8d6862016-05-26 11:24:55 -07001257 parameters.extensions.push_back(RtpExtension(ext_uri, id));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001258 EXPECT_TRUE(channel_->SetRecvParameters(parameters));
pbos@webrtc.org587ef602014-06-16 17:32:02 +00001259
1260 FakeVideoReceiveStream* recv_stream =
1261 AddRecvStream(cricket::StreamParams::CreateLegacy(123));
1262
1263 // Verify the recv extension id.
1264 ASSERT_EQ(1u, recv_stream->GetConfig().rtp.extensions.size());
1265 EXPECT_EQ(id, recv_stream->GetConfig().rtp.extensions[0].id);
isheriff6f8d6862016-05-26 11:24:55 -07001266 EXPECT_EQ(ext_uri, recv_stream->GetConfig().rtp.extensions[0].uri);
pbos@webrtc.org587ef602014-06-16 17:32:02 +00001267 // Verify call with same set of extensions returns true.
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001268 EXPECT_TRUE(channel_->SetRecvParameters(parameters));
pbos@webrtc.orgd1ea06b2014-07-18 09:35:58 +00001269
pbos@webrtc.org587ef602014-06-16 17:32:02 +00001270 // Verify that SetRecvRtpHeaderExtensions doesn't implicitly add them for
1271 // senders.
1272 EXPECT_TRUE(AddSendStream(cricket::StreamParams::CreateLegacy(123))
1273 ->GetConfig()
1274 .rtp.extensions.empty());
1275
pbos@webrtc.orgd1ea06b2014-07-18 09:35:58 +00001276 // Verify that existing RTP header extensions can be removed.
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001277 EXPECT_TRUE(channel_->SetRecvParameters(recv_parameters_));
Fredrik Solenberg709ed672015-09-15 12:26:33 +02001278 ASSERT_EQ(1u, fake_call_->GetVideoReceiveStreams().size());
1279 recv_stream = fake_call_->GetVideoReceiveStreams()[0];
pbos@webrtc.orgd1ea06b2014-07-18 09:35:58 +00001280 EXPECT_TRUE(recv_stream->GetConfig().rtp.extensions.empty());
1281
1282 // Verify that adding receive RTP header extensions adds them for existing
1283 // streams.
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001284 EXPECT_TRUE(channel_->SetRecvParameters(parameters));
Fredrik Solenberg709ed672015-09-15 12:26:33 +02001285 recv_stream = fake_call_->GetVideoReceiveStreams()[0];
pbos@webrtc.orgd1ea06b2014-07-18 09:35:58 +00001286 ASSERT_EQ(1u, recv_stream->GetConfig().rtp.extensions.size());
1287 EXPECT_EQ(id, recv_stream->GetConfig().rtp.extensions[0].id);
isheriff6f8d6862016-05-26 11:24:55 -07001288 EXPECT_EQ(ext_uri, recv_stream->GetConfig().rtp.extensions[0].uri);
pbos@webrtc.org587ef602014-06-16 17:32:02 +00001289 }
1290
Stefan Holmerbbaf3632015-10-29 18:53:23 +01001291 void TestExtensionFilter(const std::vector<std::string>& extensions,
1292 const std::string& expected_extension) {
1293 cricket::VideoSendParameters parameters = send_parameters_;
1294 int expected_id = -1;
1295 int id = 1;
1296 for (const std::string& extension : extensions) {
1297 if (extension == expected_extension)
1298 expected_id = id;
isheriff6f8d6862016-05-26 11:24:55 -07001299 parameters.extensions.push_back(RtpExtension(extension, id++));
Stefan Holmerbbaf3632015-10-29 18:53:23 +01001300 }
1301 EXPECT_TRUE(channel_->SetSendParameters(parameters));
1302 FakeVideoSendStream* send_stream =
1303 AddSendStream(cricket::StreamParams::CreateLegacy(123));
1304
1305 // Verify that only one of them has been set, and that it is the one with
1306 // highest priority (transport sequence number).
1307 ASSERT_EQ(1u, send_stream->GetConfig().rtp.extensions.size());
1308 EXPECT_EQ(expected_id, send_stream->GetConfig().rtp.extensions[0].id);
1309 EXPECT_EQ(expected_extension,
isheriff6f8d6862016-05-26 11:24:55 -07001310 send_stream->GetConfig().rtp.extensions[0].uri);
Stefan Holmerbbaf3632015-10-29 18:53:23 +01001311 }
1312
asapersson3c81a1a2017-06-14 05:52:21 -07001313 void TestDegradationPreference(bool resolution_scaling_enabled,
1314 bool fps_scaling_enabled);
1315
Erik Språngefbde372015-04-29 16:21:28 +02001316 void TestCpuAdaptation(bool enable_overuse, bool is_screenshare);
Peter Boström3548dd22015-05-22 18:48:36 +02001317 void TestReceiverLocalSsrcConfiguration(bool receiver_first);
magjed509e4fe2016-11-18 01:34:11 -08001318 void TestReceiveUnsignaledSsrcPacket(uint8_t payload_type,
1319 bool expect_created_receive_stream);
pbos@webrtc.org42684be2014-10-03 11:25:45 +00001320
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001321 FakeVideoSendStream* SetDenoisingOption(
nisse05103312016-03-16 02:22:50 -07001322 uint32_t ssrc,
nisse0db023a2016-03-01 04:29:59 -08001323 cricket::FakeVideoCapturer* capturer,
1324 bool enabled) {
nisse05103312016-03-16 02:22:50 -07001325 cricket::VideoOptions options;
1326 options.video_noise_reduction = rtc::Optional<bool>(enabled);
deadbeef5a4a75a2016-06-02 16:23:38 -07001327 EXPECT_TRUE(channel_->SetVideoSend(ssrc, true, &options, capturer));
nisse0db023a2016-03-01 04:29:59 -08001328 // Options only take effect on the next frame.
1329 EXPECT_TRUE(capturer->CaptureFrame());
1330
Erik Språng143cec12015-04-28 10:01:41 +02001331 return fake_call_->GetVideoSendStreams().back();
1332 }
1333
Peter Boström2feafdb2015-09-09 14:32:14 +02001334 FakeVideoSendStream* SetUpSimulcast(bool enabled, bool with_rtx) {
1335 const int kRtxSsrcOffset = 0xDEADBEEF;
Erik Språng143cec12015-04-28 10:01:41 +02001336 last_ssrc_ += 3;
Peter Boström2feafdb2015-09-09 14:32:14 +02001337 std::vector<uint32_t> ssrcs;
1338 std::vector<uint32_t> rtx_ssrcs;
1339 uint32_t num_streams = enabled ? 3 : 1;
1340 for (uint32_t i = 0; i < num_streams; ++i) {
1341 uint32_t ssrc = last_ssrc_ + i;
1342 ssrcs.push_back(ssrc);
1343 if (with_rtx) {
1344 rtx_ssrcs.push_back(ssrc + kRtxSsrcOffset);
1345 }
Erik Språng143cec12015-04-28 10:01:41 +02001346 }
Peter Boström2feafdb2015-09-09 14:32:14 +02001347 if (with_rtx) {
1348 return AddSendStream(
1349 cricket::CreateSimWithRtxStreamParams("cname", ssrcs, rtx_ssrcs));
1350 }
1351 return AddSendStream(CreateSimStreamParams("cname", ssrcs));
Erik Språng143cec12015-04-28 10:01:41 +02001352 }
1353
perkjfa10b552016-10-02 23:45:26 -07001354 int GetMaxEncoderBitrate() {
skvladdc1c62c2016-03-16 19:07:43 -07001355 std::vector<FakeVideoSendStream*> streams =
1356 fake_call_->GetVideoSendStreams();
perkjfa10b552016-10-02 23:45:26 -07001357 EXPECT_EQ(1u, streams.size());
skvladdc1c62c2016-03-16 19:07:43 -07001358 FakeVideoSendStream* stream = streams[streams.size() - 1];
perkjfa10b552016-10-02 23:45:26 -07001359 EXPECT_EQ(1, stream->GetEncoderConfig().number_of_streams);
1360 return stream->GetVideoStreams()[0].max_bitrate_bps;
skvladdc1c62c2016-03-16 19:07:43 -07001361 }
1362
perkjfa10b552016-10-02 23:45:26 -07001363 void SetAndExpectMaxBitrate(int global_max,
skvladdc1c62c2016-03-16 19:07:43 -07001364 int stream_max,
1365 int expected_encoder_bitrate) {
1366 VideoSendParameters limited_send_params = send_parameters_;
1367 limited_send_params.max_bandwidth_bps = global_max;
1368 EXPECT_TRUE(channel_->SetSendParameters(limited_send_params));
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001369 webrtc::RtpParameters parameters =
1370 channel_->GetRtpSendParameters(last_ssrc_);
skvladdc1c62c2016-03-16 19:07:43 -07001371 EXPECT_EQ(1UL, parameters.encodings.size());
deadbeefe702b302017-02-04 12:09:01 -08001372 parameters.encodings[0].max_bitrate_bps = rtc::Optional<int>(stream_max);
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001373 EXPECT_TRUE(channel_->SetRtpSendParameters(last_ssrc_, parameters));
skvladdc1c62c2016-03-16 19:07:43 -07001374 // Read back the parameteres and verify they have the correct value
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001375 parameters = channel_->GetRtpSendParameters(last_ssrc_);
skvladdc1c62c2016-03-16 19:07:43 -07001376 EXPECT_EQ(1UL, parameters.encodings.size());
deadbeefe702b302017-02-04 12:09:01 -08001377 EXPECT_EQ(rtc::Optional<int>(stream_max),
1378 parameters.encodings[0].max_bitrate_bps);
skvladdc1c62c2016-03-16 19:07:43 -07001379 // Verify that the new value propagated down to the encoder
perkjfa10b552016-10-02 23:45:26 -07001380 EXPECT_EQ(expected_encoder_bitrate, GetMaxEncoderBitrate());
skvladdc1c62c2016-03-16 19:07:43 -07001381 }
1382
kwiberg686a8ef2016-02-26 03:00:35 -08001383 std::unique_ptr<FakeCall> fake_call_;
1384 std::unique_ptr<VideoMediaChannel> channel_;
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001385 cricket::VideoSendParameters send_parameters_;
1386 cricket::VideoRecvParameters recv_parameters_;
Peter Boström0c4e06b2015-10-07 12:23:21 +02001387 uint32_t last_ssrc_;
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001388};
1389
eladalonf1841382017-06-12 01:16:46 -07001390TEST_F(WebRtcVideoChannelTest, SetsSyncGroupFromSyncLabel) {
Peter Boström0c4e06b2015-10-07 12:23:21 +02001391 const uint32_t kVideoSsrc = 123;
pbos8fc7fa72015-07-15 08:02:58 -07001392 const std::string kSyncLabel = "AvSyncLabel";
1393
1394 cricket::StreamParams sp = cricket::StreamParams::CreateLegacy(kVideoSsrc);
1395 sp.sync_label = kSyncLabel;
1396 EXPECT_TRUE(channel_->AddRecvStream(sp));
1397
1398 EXPECT_EQ(1, fake_call_->GetVideoReceiveStreams().size());
1399 EXPECT_EQ(kSyncLabel,
1400 fake_call_->GetVideoReceiveStreams()[0]->GetConfig().sync_group)
1401 << "SyncGroup should be set based on sync_label";
1402}
1403
eladalonf1841382017-06-12 01:16:46 -07001404TEST_F(WebRtcVideoChannelTest, RecvStreamWithSimAndRtx) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001405 cricket::VideoSendParameters parameters;
1406 parameters.codecs = engine_.codecs();
1407 EXPECT_TRUE(channel_->SetSendParameters(parameters));
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001408 EXPECT_TRUE(channel_->SetSend(true));
nisse4b4dc862016-02-17 05:25:36 -08001409 parameters.conference_mode = true;
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001410 EXPECT_TRUE(channel_->SetSendParameters(parameters));
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001411
1412 // Send side.
Peter Boström0c4e06b2015-10-07 12:23:21 +02001413 const std::vector<uint32_t> ssrcs = MAKE_VECTOR(kSsrcs1);
1414 const std::vector<uint32_t> rtx_ssrcs = MAKE_VECTOR(kRtxSsrcs1);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001415 FakeVideoSendStream* send_stream = AddSendStream(
1416 cricket::CreateSimWithRtxStreamParams("cname", ssrcs, rtx_ssrcs));
1417
1418 ASSERT_EQ(rtx_ssrcs.size(), send_stream->GetConfig().rtp.rtx.ssrcs.size());
1419 for (size_t i = 0; i < rtx_ssrcs.size(); ++i)
1420 EXPECT_EQ(rtx_ssrcs[i], send_stream->GetConfig().rtp.rtx.ssrcs[i]);
1421
1422 // Receiver side.
1423 FakeVideoReceiveStream* recv_stream = AddRecvStream(
1424 cricket::CreateSimWithRtxStreamParams("cname", ssrcs, rtx_ssrcs));
nisse26e3abb2017-08-25 04:44:25 -07001425 EXPECT_FALSE(
1426 recv_stream->GetConfig().rtp.rtx_associated_payload_types.empty());
nisseca5706d2017-09-11 02:32:16 -07001427 EXPECT_TRUE(VerifyRtxReceiveAssociations(recv_stream->GetConfig()))
Peter Boströmd8b01092016-05-12 16:44:36 +02001428 << "RTX should be mapped for all decoders/payload types.";
nisseca5706d2017-09-11 02:32:16 -07001429 EXPECT_TRUE(HasRtxReceiveAssociation(recv_stream->GetConfig(),
1430 GetEngineCodec("red").id))
1431 << "RTX should be mapped for the RED payload type";
1432
brandtr14742122017-01-27 04:53:07 -08001433 EXPECT_EQ(rtx_ssrcs[0], recv_stream->GetConfig().rtp.rtx_ssrc);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001434}
1435
eladalonf1841382017-06-12 01:16:46 -07001436TEST_F(WebRtcVideoChannelTest, RecvStreamWithRtx) {
pbos@webrtc.orge322a172014-06-13 11:47:28 +00001437 // Setup one channel with an associated RTX stream.
1438 cricket::StreamParams params =
1439 cricket::StreamParams::CreateLegacy(kSsrcs1[0]);
1440 params.AddFidSsrc(kSsrcs1[0], kRtxSsrcs1[0]);
1441 FakeVideoReceiveStream* recv_stream = AddRecvStream(params);
brandtr14742122017-01-27 04:53:07 -08001442 EXPECT_EQ(kRtxSsrcs1[0], recv_stream->GetConfig().rtp.rtx_ssrc);
nisseca5706d2017-09-11 02:32:16 -07001443
1444 EXPECT_TRUE(VerifyRtxReceiveAssociations(recv_stream->GetConfig()))
1445 << "RTX should be mapped for all decoders/payload types.";
1446 EXPECT_TRUE(HasRtxReceiveAssociation(recv_stream->GetConfig(),
1447 GetEngineCodec("red").id))
1448 << "RTX should be mapped for the RED payload type";
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001449}
1450
eladalonf1841382017-06-12 01:16:46 -07001451TEST_F(WebRtcVideoChannelTest, RecvStreamNoRtx) {
pbos@webrtc.orge322a172014-06-13 11:47:28 +00001452 // Setup one channel without an associated RTX stream.
1453 cricket::StreamParams params =
1454 cricket::StreamParams::CreateLegacy(kSsrcs1[0]);
1455 FakeVideoReceiveStream* recv_stream = AddRecvStream(params);
brandtr14742122017-01-27 04:53:07 -08001456 ASSERT_EQ(0U, recv_stream->GetConfig().rtp.rtx_ssrc);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001457}
1458
eladalonf1841382017-06-12 01:16:46 -07001459TEST_F(WebRtcVideoChannelTest, NoHeaderExtesionsByDefault) {
pbos@webrtc.org587ef602014-06-16 17:32:02 +00001460 FakeVideoSendStream* send_stream =
1461 AddSendStream(cricket::StreamParams::CreateLegacy(kSsrcs1[0]));
1462 ASSERT_TRUE(send_stream->GetConfig().rtp.extensions.empty());
1463
1464 FakeVideoReceiveStream* recv_stream =
1465 AddRecvStream(cricket::StreamParams::CreateLegacy(kSsrcs1[0]));
1466 ASSERT_TRUE(recv_stream->GetConfig().rtp.extensions.empty());
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001467}
1468
pbos@webrtc.org587ef602014-06-16 17:32:02 +00001469// Test support for RTP timestamp offset header extension.
eladalonf1841382017-06-12 01:16:46 -07001470TEST_F(WebRtcVideoChannelTest, SendRtpTimestampOffsetHeaderExtensions) {
isheriff6f8d6862016-05-26 11:24:55 -07001471 TestSetSendRtpHeaderExtensions(RtpExtension::kTimestampOffsetUri);
pbos@webrtc.org587ef602014-06-16 17:32:02 +00001472}
isheriff6f8d6862016-05-26 11:24:55 -07001473
eladalonf1841382017-06-12 01:16:46 -07001474TEST_F(WebRtcVideoChannelTest, RecvRtpTimestampOffsetHeaderExtensions) {
isheriff6f8d6862016-05-26 11:24:55 -07001475 TestSetRecvRtpHeaderExtensions(RtpExtension::kTimestampOffsetUri);
pbos@webrtc.org587ef602014-06-16 17:32:02 +00001476}
1477
1478// Test support for absolute send time header extension.
eladalonf1841382017-06-12 01:16:46 -07001479TEST_F(WebRtcVideoChannelTest, SendAbsoluteSendTimeHeaderExtensions) {
isheriff6f8d6862016-05-26 11:24:55 -07001480 TestSetSendRtpHeaderExtensions(RtpExtension::kAbsSendTimeUri);
pbos@webrtc.org587ef602014-06-16 17:32:02 +00001481}
isheriff6f8d6862016-05-26 11:24:55 -07001482
eladalonf1841382017-06-12 01:16:46 -07001483TEST_F(WebRtcVideoChannelTest, RecvAbsoluteSendTimeHeaderExtensions) {
isheriff6f8d6862016-05-26 11:24:55 -07001484 TestSetRecvRtpHeaderExtensions(RtpExtension::kAbsSendTimeUri);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001485}
1486
eladalonf1841382017-06-12 01:16:46 -07001487TEST_F(WebRtcVideoChannelTest, FiltersExtensionsPicksTransportSeqNum) {
Stefan Holmerbbaf3632015-10-29 18:53:23 +01001488 // Enable three redundant extensions.
1489 std::vector<std::string> extensions;
isheriff6f8d6862016-05-26 11:24:55 -07001490 extensions.push_back(RtpExtension::kAbsSendTimeUri);
1491 extensions.push_back(RtpExtension::kTimestampOffsetUri);
1492 extensions.push_back(RtpExtension::kTransportSequenceNumberUri);
1493 TestExtensionFilter(extensions, RtpExtension::kTransportSequenceNumberUri);
Stefan Holmerbbaf3632015-10-29 18:53:23 +01001494}
1495
eladalonf1841382017-06-12 01:16:46 -07001496TEST_F(WebRtcVideoChannelTest, FiltersExtensionsPicksAbsSendTime) {
Stefan Holmerbbaf3632015-10-29 18:53:23 +01001497 // Enable two redundant extensions.
1498 std::vector<std::string> extensions;
isheriff6f8d6862016-05-26 11:24:55 -07001499 extensions.push_back(RtpExtension::kAbsSendTimeUri);
1500 extensions.push_back(RtpExtension::kTimestampOffsetUri);
1501 TestExtensionFilter(extensions, RtpExtension::kAbsSendTimeUri);
Stefan Holmerbbaf3632015-10-29 18:53:23 +01001502}
1503
stefanc1aeaf02015-10-15 07:26:07 -07001504// Test support for transport sequence number header extension.
eladalonf1841382017-06-12 01:16:46 -07001505TEST_F(WebRtcVideoChannelTest, SendTransportSequenceNumberHeaderExtensions) {
isheriff6f8d6862016-05-26 11:24:55 -07001506 TestSetSendRtpHeaderExtensions(RtpExtension::kTransportSequenceNumberUri);
stefanc1aeaf02015-10-15 07:26:07 -07001507}
eladalonf1841382017-06-12 01:16:46 -07001508TEST_F(WebRtcVideoChannelTest, RecvTransportSequenceNumberHeaderExtensions) {
isheriff6f8d6862016-05-26 11:24:55 -07001509 TestSetRecvRtpHeaderExtensions(RtpExtension::kTransportSequenceNumberUri);
stefanc1aeaf02015-10-15 07:26:07 -07001510}
1511
Guo-wei Shieh64c1e8c2015-04-01 15:33:06 -07001512// Test support for video rotation header extension.
eladalonf1841382017-06-12 01:16:46 -07001513TEST_F(WebRtcVideoChannelTest, SendVideoRotationHeaderExtensions) {
isheriff6f8d6862016-05-26 11:24:55 -07001514 TestSetSendRtpHeaderExtensions(RtpExtension::kVideoRotationUri);
Guo-wei Shieh64c1e8c2015-04-01 15:33:06 -07001515}
eladalonf1841382017-06-12 01:16:46 -07001516TEST_F(WebRtcVideoChannelTest, RecvVideoRotationHeaderExtensions) {
isheriff6f8d6862016-05-26 11:24:55 -07001517 TestSetRecvRtpHeaderExtensions(RtpExtension::kVideoRotationUri);
Guo-wei Shieh64c1e8c2015-04-01 15:33:06 -07001518}
1519
eladalonf1841382017-06-12 01:16:46 -07001520TEST_F(WebRtcVideoChannelTest, IdenticalSendExtensionsDoesntRecreateStream) {
Stefan Holmerbbaf3632015-10-29 18:53:23 +01001521 const int kAbsSendTimeId = 1;
1522 const int kVideoRotationId = 2;
isheriff6f8d6862016-05-26 11:24:55 -07001523 send_parameters_.extensions.push_back(
1524 RtpExtension(RtpExtension::kAbsSendTimeUri, kAbsSendTimeId));
1525 send_parameters_.extensions.push_back(
1526 RtpExtension(RtpExtension::kVideoRotationUri, kVideoRotationId));
pbos@webrtc.orgc37e72e2015-01-05 18:51:13 +00001527
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001528 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
pbos@webrtc.orgc37e72e2015-01-05 18:51:13 +00001529 FakeVideoSendStream* send_stream =
1530 AddSendStream(cricket::StreamParams::CreateLegacy(123));
1531
1532 EXPECT_EQ(1, fake_call_->GetNumCreatedSendStreams());
Stefan Holmerbbaf3632015-10-29 18:53:23 +01001533 ASSERT_EQ(2u, send_stream->GetConfig().rtp.extensions.size());
pbos@webrtc.orgc37e72e2015-01-05 18:51:13 +00001534
1535 // Setting the same extensions (even if in different order) shouldn't
1536 // reallocate the stream.
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001537 std::reverse(send_parameters_.extensions.begin(),
1538 send_parameters_.extensions.end());
1539 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
pbos@webrtc.orgc37e72e2015-01-05 18:51:13 +00001540
1541 EXPECT_EQ(1, fake_call_->GetNumCreatedSendStreams());
1542
1543 // Setting different extensions should recreate the stream.
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001544 send_parameters_.extensions.resize(1);
1545 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
pbos@webrtc.orgc37e72e2015-01-05 18:51:13 +00001546
1547 EXPECT_EQ(2, fake_call_->GetNumCreatedSendStreams());
1548}
1549
eladalonf1841382017-06-12 01:16:46 -07001550TEST_F(WebRtcVideoChannelTest, IdenticalRecvExtensionsDoesntRecreateStream) {
pbos@webrtc.orgc37e72e2015-01-05 18:51:13 +00001551 const int kTOffsetId = 1;
1552 const int kAbsSendTimeId = 2;
Guo-wei Shieh64c1e8c2015-04-01 15:33:06 -07001553 const int kVideoRotationId = 3;
isheriff6f8d6862016-05-26 11:24:55 -07001554 recv_parameters_.extensions.push_back(
1555 RtpExtension(RtpExtension::kAbsSendTimeUri, kAbsSendTimeId));
1556 recv_parameters_.extensions.push_back(
1557 RtpExtension(RtpExtension::kTimestampOffsetUri, kTOffsetId));
1558 recv_parameters_.extensions.push_back(
1559 RtpExtension(RtpExtension::kVideoRotationUri, kVideoRotationId));
pbos@webrtc.orgc37e72e2015-01-05 18:51:13 +00001560
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001561 EXPECT_TRUE(channel_->SetRecvParameters(recv_parameters_));
Peter Boström54be3e02015-05-25 15:04:24 +02001562 FakeVideoReceiveStream* recv_stream =
pbos@webrtc.orgc37e72e2015-01-05 18:51:13 +00001563 AddRecvStream(cricket::StreamParams::CreateLegacy(123));
1564
1565 EXPECT_EQ(1, fake_call_->GetNumCreatedReceiveStreams());
Peter Boström54be3e02015-05-25 15:04:24 +02001566 ASSERT_EQ(3u, recv_stream->GetConfig().rtp.extensions.size());
pbos@webrtc.orgc37e72e2015-01-05 18:51:13 +00001567
1568 // Setting the same extensions (even if in different order) shouldn't
1569 // reallocate the stream.
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001570 std::reverse(recv_parameters_.extensions.begin(),
1571 recv_parameters_.extensions.end());
1572 EXPECT_TRUE(channel_->SetRecvParameters(recv_parameters_));
pbos@webrtc.orgc37e72e2015-01-05 18:51:13 +00001573
1574 EXPECT_EQ(1, fake_call_->GetNumCreatedReceiveStreams());
1575
1576 // Setting different extensions should recreate the stream.
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001577 recv_parameters_.extensions.resize(1);
1578 EXPECT_TRUE(channel_->SetRecvParameters(recv_parameters_));
pbos@webrtc.orgc37e72e2015-01-05 18:51:13 +00001579
1580 EXPECT_EQ(2, fake_call_->GetNumCreatedReceiveStreams());
1581}
1582
eladalonf1841382017-06-12 01:16:46 -07001583TEST_F(WebRtcVideoChannelTest,
pbos@webrtc.org42684be2014-10-03 11:25:45 +00001584 SetSendRtpHeaderExtensionsExcludeUnsupportedExtensions) {
pbos@webrtc.org3c107582014-07-20 15:27:35 +00001585 const int kUnsupportedId = 1;
1586 const int kTOffsetId = 2;
1587
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001588 send_parameters_.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001589 RtpExtension(kUnsupportedExtensionName, kUnsupportedId));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001590 send_parameters_.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001591 RtpExtension(RtpExtension::kTimestampOffsetUri, kTOffsetId));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001592 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
pbos@webrtc.org3c107582014-07-20 15:27:35 +00001593 FakeVideoSendStream* send_stream =
1594 AddSendStream(cricket::StreamParams::CreateLegacy(123));
1595
1596 // Only timestamp offset extension is set to send stream,
1597 // unsupported rtp extension is ignored.
1598 ASSERT_EQ(1u, send_stream->GetConfig().rtp.extensions.size());
isheriff6f8d6862016-05-26 11:24:55 -07001599 EXPECT_STREQ(RtpExtension::kTimestampOffsetUri,
1600 send_stream->GetConfig().rtp.extensions[0].uri.c_str());
pbos@webrtc.org3c107582014-07-20 15:27:35 +00001601}
1602
eladalonf1841382017-06-12 01:16:46 -07001603TEST_F(WebRtcVideoChannelTest,
pbos@webrtc.org42684be2014-10-03 11:25:45 +00001604 SetRecvRtpHeaderExtensionsExcludeUnsupportedExtensions) {
pbos@webrtc.org3c107582014-07-20 15:27:35 +00001605 const int kUnsupportedId = 1;
1606 const int kTOffsetId = 2;
1607
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001608 recv_parameters_.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001609 RtpExtension(kUnsupportedExtensionName, kUnsupportedId));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001610 recv_parameters_.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001611 RtpExtension(RtpExtension::kTimestampOffsetUri, kTOffsetId));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001612 EXPECT_TRUE(channel_->SetRecvParameters(recv_parameters_));
pbos@webrtc.org3c107582014-07-20 15:27:35 +00001613 FakeVideoReceiveStream* recv_stream =
1614 AddRecvStream(cricket::StreamParams::CreateLegacy(123));
1615
1616 // Only timestamp offset extension is set to receive stream,
1617 // unsupported rtp extension is ignored.
1618 ASSERT_EQ(1u, recv_stream->GetConfig().rtp.extensions.size());
isheriff6f8d6862016-05-26 11:24:55 -07001619 EXPECT_STREQ(RtpExtension::kTimestampOffsetUri,
1620 recv_stream->GetConfig().rtp.extensions[0].uri.c_str());
pbos@webrtc.org3c107582014-07-20 15:27:35 +00001621}
1622
eladalonf1841382017-06-12 01:16:46 -07001623TEST_F(WebRtcVideoChannelTest, SetSendRtpHeaderExtensionsRejectsIncorrectIds) {
Peter Boström23914fe2015-03-31 15:08:04 +02001624 const int kIncorrectIds[] = {-2, -1, 0, 15, 16};
pkasting@chromium.orge7a4a122015-01-28 21:36:55 +00001625 for (size_t i = 0; i < arraysize(kIncorrectIds); ++i) {
isheriff6f8d6862016-05-26 11:24:55 -07001626 send_parameters_.extensions.push_back(
1627 RtpExtension(RtpExtension::kTimestampOffsetUri, kIncorrectIds[i]));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001628 EXPECT_FALSE(channel_->SetSendParameters(send_parameters_))
pbos@webrtc.org3c107582014-07-20 15:27:35 +00001629 << "Bad extension id '" << kIncorrectIds[i] << "' accepted.";
1630 }
1631}
1632
eladalonf1841382017-06-12 01:16:46 -07001633TEST_F(WebRtcVideoChannelTest, SetRecvRtpHeaderExtensionsRejectsIncorrectIds) {
Peter Boström23914fe2015-03-31 15:08:04 +02001634 const int kIncorrectIds[] = {-2, -1, 0, 15, 16};
pkasting@chromium.orge7a4a122015-01-28 21:36:55 +00001635 for (size_t i = 0; i < arraysize(kIncorrectIds); ++i) {
isheriff6f8d6862016-05-26 11:24:55 -07001636 recv_parameters_.extensions.push_back(
1637 RtpExtension(RtpExtension::kTimestampOffsetUri, kIncorrectIds[i]));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001638 EXPECT_FALSE(channel_->SetRecvParameters(recv_parameters_))
pbos@webrtc.org3c107582014-07-20 15:27:35 +00001639 << "Bad extension id '" << kIncorrectIds[i] << "' accepted.";
1640 }
1641}
1642
eladalonf1841382017-06-12 01:16:46 -07001643TEST_F(WebRtcVideoChannelTest, SetSendRtpHeaderExtensionsRejectsDuplicateIds) {
pbos@webrtc.org3c107582014-07-20 15:27:35 +00001644 const int id = 1;
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001645 send_parameters_.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001646 RtpExtension(RtpExtension::kTimestampOffsetUri, id));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001647 send_parameters_.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001648 RtpExtension(RtpExtension::kAbsSendTimeUri, id));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001649 EXPECT_FALSE(channel_->SetSendParameters(send_parameters_));
pbos@webrtc.org3c107582014-07-20 15:27:35 +00001650
1651 // Duplicate entries are also not supported.
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001652 send_parameters_.extensions.clear();
1653 send_parameters_.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001654 RtpExtension(RtpExtension::kTimestampOffsetUri, id));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001655 send_parameters_.extensions.push_back(send_parameters_.extensions.back());
1656 EXPECT_FALSE(channel_->SetSendParameters(send_parameters_));
pbos@webrtc.org3c107582014-07-20 15:27:35 +00001657}
1658
eladalonf1841382017-06-12 01:16:46 -07001659TEST_F(WebRtcVideoChannelTest, SetRecvRtpHeaderExtensionsRejectsDuplicateIds) {
pbos@webrtc.org3c107582014-07-20 15:27:35 +00001660 const int id = 1;
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001661 recv_parameters_.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001662 RtpExtension(RtpExtension::kTimestampOffsetUri, id));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001663 recv_parameters_.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001664 RtpExtension(RtpExtension::kAbsSendTimeUri, id));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001665 EXPECT_FALSE(channel_->SetRecvParameters(recv_parameters_));
pbos@webrtc.org3c107582014-07-20 15:27:35 +00001666
1667 // Duplicate entries are also not supported.
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001668 recv_parameters_.extensions.clear();
1669 recv_parameters_.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001670 RtpExtension(RtpExtension::kTimestampOffsetUri, id));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001671 recv_parameters_.extensions.push_back(recv_parameters_.extensions.back());
1672 EXPECT_FALSE(channel_->SetRecvParameters(recv_parameters_));
pbos@webrtc.org3c107582014-07-20 15:27:35 +00001673}
1674
eladalonf1841382017-06-12 01:16:46 -07001675TEST_F(WebRtcVideoChannelTest, AddRecvStreamOnlyUsesOneReceiveStream) {
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001676 EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(1)));
pbos@webrtc.org42684be2014-10-03 11:25:45 +00001677 EXPECT_EQ(1u, fake_call_->GetVideoReceiveStreams().size());
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001678}
1679
eladalonf1841382017-06-12 01:16:46 -07001680TEST_F(WebRtcVideoChannelTest, RtcpIsCompoundByDefault) {
Peter Boströmd7da1202015-06-05 14:09:38 +02001681 FakeVideoReceiveStream* stream = AddRecvStream();
pbosda903ea2015-10-02 02:36:56 -07001682 EXPECT_EQ(webrtc::RtcpMode::kCompound, stream->GetConfig().rtp.rtcp_mode);
Peter Boströmd7da1202015-06-05 14:09:38 +02001683}
1684
eladalonf1841382017-06-12 01:16:46 -07001685TEST_F(WebRtcVideoChannelTest, RembIsEnabledByDefault) {
pbos@webrtc.org257e1302014-07-25 19:01:32 +00001686 FakeVideoReceiveStream* stream = AddRecvStream();
1687 EXPECT_TRUE(stream->GetConfig().rtp.remb);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001688}
1689
eladalonf1841382017-06-12 01:16:46 -07001690TEST_F(WebRtcVideoChannelTest, TransportCcIsEnabledByDefault) {
stefan43edf0f2015-11-20 18:05:48 -08001691 FakeVideoReceiveStream* stream = AddRecvStream();
1692 EXPECT_TRUE(stream->GetConfig().rtp.transport_cc);
1693}
1694
eladalonf1841382017-06-12 01:16:46 -07001695TEST_F(WebRtcVideoChannelTest, RembCanBeEnabledAndDisabled) {
pbos@webrtc.org257e1302014-07-25 19:01:32 +00001696 FakeVideoReceiveStream* stream = AddRecvStream();
1697 EXPECT_TRUE(stream->GetConfig().rtp.remb);
1698
Peter Boström126c03e2015-05-11 12:48:12 +02001699 // Verify that REMB is turned off when send(!) codecs without REMB are set.
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001700 cricket::VideoSendParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08001701 parameters.codecs.push_back(RemoveFeedbackParams(GetEngineCodec("VP8")));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001702 EXPECT_TRUE(parameters.codecs[0].feedback_params.params().empty());
1703 EXPECT_TRUE(channel_->SetSendParameters(parameters));
pbos@webrtc.org42684be2014-10-03 11:25:45 +00001704 stream = fake_call_->GetVideoReceiveStreams()[0];
pbos@webrtc.org257e1302014-07-25 19:01:32 +00001705 EXPECT_FALSE(stream->GetConfig().rtp.remb);
1706
1707 // Verify that REMB is turned on when setting default codecs since the
1708 // default codecs have REMB enabled.
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001709 parameters.codecs = engine_.codecs();
1710 EXPECT_TRUE(channel_->SetSendParameters(parameters));
pbos@webrtc.org42684be2014-10-03 11:25:45 +00001711 stream = fake_call_->GetVideoReceiveStreams()[0];
pbos@webrtc.org257e1302014-07-25 19:01:32 +00001712 EXPECT_TRUE(stream->GetConfig().rtp.remb);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001713}
1714
eladalonf1841382017-06-12 01:16:46 -07001715TEST_F(WebRtcVideoChannelTest, TransportCcCanBeEnabledAndDisabled) {
stefan43edf0f2015-11-20 18:05:48 -08001716 FakeVideoReceiveStream* stream = AddRecvStream();
1717 EXPECT_TRUE(stream->GetConfig().rtp.transport_cc);
1718
1719 // Verify that transport cc feedback is turned off when send(!) codecs without
1720 // transport cc feedback are set.
1721 cricket::VideoSendParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08001722 parameters.codecs.push_back(RemoveFeedbackParams(GetEngineCodec("VP8")));
stefan43edf0f2015-11-20 18:05:48 -08001723 EXPECT_TRUE(parameters.codecs[0].feedback_params.params().empty());
1724 EXPECT_TRUE(channel_->SetSendParameters(parameters));
1725 stream = fake_call_->GetVideoReceiveStreams()[0];
1726 EXPECT_FALSE(stream->GetConfig().rtp.transport_cc);
1727
1728 // Verify that transport cc feedback is turned on when setting default codecs
1729 // since the default codecs have transport cc feedback enabled.
1730 parameters.codecs = engine_.codecs();
1731 EXPECT_TRUE(channel_->SetSendParameters(parameters));
1732 stream = fake_call_->GetVideoReceiveStreams()[0];
1733 EXPECT_TRUE(stream->GetConfig().rtp.transport_cc);
1734}
1735
eladalonf1841382017-06-12 01:16:46 -07001736TEST_F(WebRtcVideoChannelTest, NackIsEnabledByDefault) {
pbos@webrtc.orgf99c2f22014-06-13 12:27:38 +00001737 VerifyCodecHasDefaultFeedbackParams(default_codec_);
1738
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001739 cricket::VideoSendParameters parameters;
1740 parameters.codecs = engine_.codecs();
1741 EXPECT_TRUE(channel_->SetSendParameters(parameters));
pbos@webrtc.org19864742014-05-30 07:35:47 +00001742 EXPECT_TRUE(channel_->SetSend(true));
1743
1744 // Send side.
1745 FakeVideoSendStream* send_stream =
1746 AddSendStream(cricket::StreamParams::CreateLegacy(1));
1747 EXPECT_GT(send_stream->GetConfig().rtp.nack.rtp_history_ms, 0);
1748
1749 // Receiver side.
1750 FakeVideoReceiveStream* recv_stream =
1751 AddRecvStream(cricket::StreamParams::CreateLegacy(1));
1752 EXPECT_GT(recv_stream->GetConfig().rtp.nack.rtp_history_ms, 0);
1753
1754 // Nack history size should match between sender and receiver.
1755 EXPECT_EQ(send_stream->GetConfig().rtp.nack.rtp_history_ms,
1756 recv_stream->GetConfig().rtp.nack.rtp_history_ms);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001757}
1758
eladalonf1841382017-06-12 01:16:46 -07001759TEST_F(WebRtcVideoChannelTest, NackCanBeEnabledAndDisabled) {
Peter Boström67c9df72015-05-11 14:34:58 +02001760 FakeVideoSendStream* send_stream = AddSendStream();
Peter Boström3548dd22015-05-22 18:48:36 +02001761 FakeVideoReceiveStream* recv_stream = AddRecvStream();
Peter Boström67c9df72015-05-11 14:34:58 +02001762
1763 EXPECT_GT(recv_stream->GetConfig().rtp.nack.rtp_history_ms, 0);
1764 EXPECT_GT(send_stream->GetConfig().rtp.nack.rtp_history_ms, 0);
1765
1766 // Verify that NACK is turned off when send(!) codecs without NACK are set.
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001767 cricket::VideoSendParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08001768 parameters.codecs.push_back(RemoveFeedbackParams(GetEngineCodec("VP8")));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001769 EXPECT_TRUE(parameters.codecs[0].feedback_params.params().empty());
1770 EXPECT_TRUE(channel_->SetSendParameters(parameters));
Peter Boström67c9df72015-05-11 14:34:58 +02001771 recv_stream = fake_call_->GetVideoReceiveStreams()[0];
1772 EXPECT_EQ(0, recv_stream->GetConfig().rtp.nack.rtp_history_ms);
1773 send_stream = fake_call_->GetVideoSendStreams()[0];
pbos@webrtc.orgf99c2f22014-06-13 12:27:38 +00001774 EXPECT_EQ(0, send_stream->GetConfig().rtp.nack.rtp_history_ms);
1775
Peter Boström67c9df72015-05-11 14:34:58 +02001776 // Verify that NACK is turned on when setting default codecs since the
1777 // default codecs have NACK enabled.
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001778 parameters.codecs = engine_.codecs();
1779 EXPECT_TRUE(channel_->SetSendParameters(parameters));
Peter Boström67c9df72015-05-11 14:34:58 +02001780 recv_stream = fake_call_->GetVideoReceiveStreams()[0];
1781 EXPECT_GT(recv_stream->GetConfig().rtp.nack.rtp_history_ms, 0);
1782 send_stream = fake_call_->GetVideoSendStreams()[0];
1783 EXPECT_GT(send_stream->GetConfig().rtp.nack.rtp_history_ms, 0);
pbos@webrtc.orgf99c2f22014-06-13 12:27:38 +00001784}
1785
Peter Boströme7ba0862016-03-12 00:02:28 +01001786// This test verifies that new frame sizes reconfigures encoders even though not
1787// (yet) sending. The purpose of this is to permit encoding as quickly as
1788// possible once we start sending. Likely the frames being input are from the
1789// same source that will be sent later, which just means that we're ready
1790// earlier.
eladalonf1841382017-06-12 01:16:46 -07001791TEST_F(WebRtcVideoChannelTest, ReconfiguresEncodersWhenNotSending) {
Peter Boströme7ba0862016-03-12 00:02:28 +01001792 cricket::VideoSendParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08001793 parameters.codecs.push_back(GetEngineCodec("VP8"));
Peter Boströme7ba0862016-03-12 00:02:28 +01001794 ASSERT_TRUE(channel_->SetSendParameters(parameters));
1795 channel_->SetSend(false);
1796
1797 FakeVideoSendStream* stream = AddSendStream();
1798
perkjfa10b552016-10-02 23:45:26 -07001799 // No frames entered.
Peter Boströme7ba0862016-03-12 00:02:28 +01001800 std::vector<webrtc::VideoStream> streams = stream->GetVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07001801 EXPECT_EQ(0u, streams[0].width);
1802 EXPECT_EQ(0u, streams[0].height);
Peter Boströme7ba0862016-03-12 00:02:28 +01001803
1804 cricket::FakeVideoCapturer capturer;
deadbeef5a4a75a2016-06-02 16:23:38 -07001805 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, &capturer));
perkj26752742016-10-24 01:21:16 -07001806 VideoFormat capture_format = capturer.GetSupportedFormats()->front();
1807 EXPECT_EQ(cricket::CS_RUNNING, capturer.Start(capture_format));
Peter Boströme7ba0862016-03-12 00:02:28 +01001808 EXPECT_TRUE(capturer.CaptureFrame());
1809
1810 // Frame entered, should be reconfigured to new dimensions.
1811 streams = stream->GetVideoStreams();
perkj26752742016-10-24 01:21:16 -07001812 EXPECT_EQ(capture_format.width, streams[0].width);
1813 EXPECT_EQ(capture_format.height, streams[0].height);
Peter Boströme7ba0862016-03-12 00:02:28 +01001814
deadbeef5a4a75a2016-06-02 16:23:38 -07001815 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, nullptr));
Peter Boströme7ba0862016-03-12 00:02:28 +01001816}
1817
eladalonf1841382017-06-12 01:16:46 -07001818TEST_F(WebRtcVideoChannelTest, UsesCorrectSettingsForScreencast) {
pbos@webrtc.orgefc82c22014-10-27 13:58:00 +00001819 static const int kScreenshareMinBitrateKbps = 800;
magjed509e4fe2016-11-18 01:34:11 -08001820 cricket::VideoCodec codec = GetEngineCodec("VP8");
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001821 cricket::VideoSendParameters parameters;
1822 parameters.codecs.push_back(codec);
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001823 EXPECT_TRUE(channel_->SetSendParameters(parameters));
pbos@webrtc.orgefc82c22014-10-27 13:58:00 +00001824 AddSendStream();
1825
deadbeef5a4a75a2016-06-02 16:23:38 -07001826 cricket::FakeVideoCapturer capturer;
nisse05103312016-03-16 02:22:50 -07001827 VideoOptions min_bitrate_options;
1828 min_bitrate_options.screencast_min_bitrate_kbps =
1829 rtc::Optional<int>(kScreenshareMinBitrateKbps);
deadbeef5a4a75a2016-06-02 16:23:38 -07001830 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, &min_bitrate_options,
1831 &capturer));
pbos@webrtc.orgefc82c22014-10-27 13:58:00 +00001832 cricket::VideoFormat capture_format_hd =
1833 capturer.GetSupportedFormats()->front();
1834 EXPECT_EQ(1280, capture_format_hd.width);
1835 EXPECT_EQ(720, capture_format_hd.height);
1836 EXPECT_EQ(cricket::CS_RUNNING, capturer.Start(capture_format_hd));
1837
1838 EXPECT_TRUE(channel_->SetSend(true));
1839
1840 EXPECT_TRUE(capturer.CaptureFrame());
1841 ASSERT_EQ(1u, fake_call_->GetVideoSendStreams().size());
1842 FakeVideoSendStream* send_stream = fake_call_->GetVideoSendStreams().front();
1843
1844 EXPECT_EQ(1, send_stream->GetNumberOfSwappedFrames());
1845
1846 // Verify non-screencast settings.
perkj26091b12016-09-01 01:17:40 -07001847 webrtc::VideoEncoderConfig encoder_config =
1848 send_stream->GetEncoderConfig().Copy();
Erik Språng143cec12015-04-28 10:01:41 +02001849 EXPECT_EQ(webrtc::VideoEncoderConfig::ContentType::kRealtimeVideo,
pbos@webrtc.orgefc82c22014-10-27 13:58:00 +00001850 encoder_config.content_type);
perkjfa10b552016-10-02 23:45:26 -07001851 std::vector<webrtc::VideoStream> streams = send_stream->GetVideoStreams();
1852 EXPECT_EQ(capture_format_hd.width, streams.front().width);
1853 EXPECT_EQ(capture_format_hd.height, streams.front().height);
pbos@webrtc.orgefc82c22014-10-27 13:58:00 +00001854 EXPECT_EQ(0, encoder_config.min_transmit_bitrate_bps)
1855 << "Non-screenshare shouldn't use min-transmit bitrate.";
1856
deadbeef5a4a75a2016-06-02 16:23:38 -07001857 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, nullptr));
perkjd533aec2017-01-13 05:57:25 -08001858 EXPECT_EQ(1, send_stream->GetNumberOfSwappedFrames());
nisse05103312016-03-16 02:22:50 -07001859 VideoOptions screencast_options;
1860 screencast_options.is_screencast = rtc::Optional<bool>(true);
deadbeef5a4a75a2016-06-02 16:23:38 -07001861 EXPECT_TRUE(
1862 channel_->SetVideoSend(last_ssrc_, true, &screencast_options, &capturer));
perkj2d5f0912016-02-29 00:04:41 -08001863 EXPECT_TRUE(capturer.CaptureFrame());
sprangf24a0642017-02-28 13:23:26 -08001864 // Send stream recreated after option change.
1865 ASSERT_EQ(2, fake_call_->GetNumCreatedSendStreams());
1866 send_stream = fake_call_->GetVideoSendStreams().front();
1867 EXPECT_EQ(1, send_stream->GetNumberOfSwappedFrames());
pbos@webrtc.orgefc82c22014-10-27 13:58:00 +00001868
1869 // Verify screencast settings.
perkj26091b12016-09-01 01:17:40 -07001870 encoder_config = send_stream->GetEncoderConfig().Copy();
Erik Språng143cec12015-04-28 10:01:41 +02001871 EXPECT_EQ(webrtc::VideoEncoderConfig::ContentType::kScreen,
pbos@webrtc.orgefc82c22014-10-27 13:58:00 +00001872 encoder_config.content_type);
1873 EXPECT_EQ(kScreenshareMinBitrateKbps * 1000,
1874 encoder_config.min_transmit_bitrate_bps);
1875
perkjfa10b552016-10-02 23:45:26 -07001876 streams = send_stream->GetVideoStreams();
1877 EXPECT_EQ(capture_format_hd.width, streams.front().width);
1878 EXPECT_EQ(capture_format_hd.height, streams.front().height);
1879 EXPECT_TRUE(streams[0].temporal_layer_thresholds_bps.empty());
deadbeef5a4a75a2016-06-02 16:23:38 -07001880 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, nullptr));
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001881}
1882
eladalonf1841382017-06-12 01:16:46 -07001883TEST_F(WebRtcVideoChannelTest,
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001884 ConferenceModeScreencastConfiguresTemporalLayer) {
Erik Språng2c4c9142015-06-24 11:24:44 +02001885 static const int kConferenceScreencastTemporalBitrateBps =
1886 ScreenshareLayerConfig::GetDefault().tl0_bitrate_kbps * 1000;
nisse4b4dc862016-02-17 05:25:36 -08001887 send_parameters_.conference_mode = true;
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001888 channel_->SetSendParameters(send_parameters_);
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001889
1890 AddSendStream();
nisse05103312016-03-16 02:22:50 -07001891 VideoOptions options;
1892 options.is_screencast = rtc::Optional<bool>(true);
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001893 cricket::FakeVideoCapturer capturer;
deadbeef5a4a75a2016-06-02 16:23:38 -07001894 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, &options, &capturer));
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001895 cricket::VideoFormat capture_format_hd =
1896 capturer.GetSupportedFormats()->front();
1897 EXPECT_EQ(cricket::CS_RUNNING, capturer.Start(capture_format_hd));
1898
1899 EXPECT_TRUE(channel_->SetSend(true));
1900
1901 EXPECT_TRUE(capturer.CaptureFrame());
1902 ASSERT_EQ(1u, fake_call_->GetVideoSendStreams().size());
1903 FakeVideoSendStream* send_stream = fake_call_->GetVideoSendStreams().front();
1904
perkj26091b12016-09-01 01:17:40 -07001905 webrtc::VideoEncoderConfig encoder_config =
1906 send_stream->GetEncoderConfig().Copy();
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001907
1908 // Verify screencast settings.
perkj26091b12016-09-01 01:17:40 -07001909 encoder_config = send_stream->GetEncoderConfig().Copy();
Erik Språng143cec12015-04-28 10:01:41 +02001910 EXPECT_EQ(webrtc::VideoEncoderConfig::ContentType::kScreen,
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001911 encoder_config.content_type);
perkjfa10b552016-10-02 23:45:26 -07001912
1913 std::vector<webrtc::VideoStream> streams = send_stream->GetVideoStreams();
1914 ASSERT_EQ(1u, streams.size());
1915 ASSERT_EQ(1u, streams[0].temporal_layer_thresholds_bps.size());
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001916 EXPECT_EQ(kConferenceScreencastTemporalBitrateBps,
perkjfa10b552016-10-02 23:45:26 -07001917 streams[0].temporal_layer_thresholds_bps[0]);
pbos@webrtc.orgefc82c22014-10-27 13:58:00 +00001918
deadbeef5a4a75a2016-06-02 16:23:38 -07001919 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, nullptr));
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001920}
1921
eladalonf1841382017-06-12 01:16:46 -07001922TEST_F(WebRtcVideoChannelTest, SuspendBelowMinBitrateDisabledByDefault) {
pbos@webrtc.org5ff71ab2014-07-23 07:28:56 +00001923 FakeVideoSendStream* stream = AddSendStream();
1924 EXPECT_FALSE(stream->GetConfig().suspend_below_min_bitrate);
1925}
1926
eladalonf1841382017-06-12 01:16:46 -07001927TEST_F(WebRtcVideoChannelTest, SetMediaConfigSuspendBelowMinBitrate) {
kthelgason2bc68642017-02-07 07:02:22 -08001928 MediaConfig media_config = GetMediaConfig();
nisse0db023a2016-03-01 04:29:59 -08001929 media_config.video.suspend_below_min_bitrate = true;
1930
1931 channel_.reset(
1932 engine_.CreateChannel(fake_call_.get(), media_config, VideoOptions()));
Sergey Ulanove2b15012016-11-22 16:08:30 -08001933 channel_->OnReadyToSend(true);
nisse0db023a2016-03-01 04:29:59 -08001934
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001935 channel_->SetSendParameters(send_parameters_);
pbos@webrtc.org5ff71ab2014-07-23 07:28:56 +00001936
1937 FakeVideoSendStream* stream = AddSendStream();
1938 EXPECT_TRUE(stream->GetConfig().suspend_below_min_bitrate);
1939
nisse0db023a2016-03-01 04:29:59 -08001940 media_config.video.suspend_below_min_bitrate = false;
1941 channel_.reset(
1942 engine_.CreateChannel(fake_call_.get(), media_config, VideoOptions()));
Sergey Ulanove2b15012016-11-22 16:08:30 -08001943 channel_->OnReadyToSend(true);
nisse0db023a2016-03-01 04:29:59 -08001944
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001945 channel_->SetSendParameters(send_parameters_);
pbos@webrtc.org5ff71ab2014-07-23 07:28:56 +00001946
nisse0db023a2016-03-01 04:29:59 -08001947 stream = AddSendStream();
pbos@webrtc.org5ff71ab2014-07-23 07:28:56 +00001948 EXPECT_FALSE(stream->GetConfig().suspend_below_min_bitrate);
1949}
1950
eladalonf1841382017-06-12 01:16:46 -07001951TEST_F(WebRtcVideoChannelTest, Vp8DenoisingEnabledByDefault) {
pbos@webrtc.org6f48f1b2014-07-22 16:29:54 +00001952 FakeVideoSendStream* stream = AddSendStream();
1953 webrtc::VideoCodecVP8 vp8_settings;
1954 ASSERT_TRUE(stream->GetVp8Settings(&vp8_settings)) << "No VP8 config set.";
1955 EXPECT_TRUE(vp8_settings.denoisingOn);
1956}
1957
eladalonf1841382017-06-12 01:16:46 -07001958TEST_F(WebRtcVideoChannelTest, VerifyVp8SpecificSettings) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001959 cricket::VideoSendParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08001960 parameters.codecs.push_back(GetEngineCodec("VP8"));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001961 ASSERT_TRUE(channel_->SetSendParameters(parameters));
pbos@webrtc.org6f48f1b2014-07-22 16:29:54 +00001962
Peter Boström2feafdb2015-09-09 14:32:14 +02001963 // Single-stream settings should apply with RTX as well (verifies that we
1964 // check number of regular SSRCs and not StreamParams::ssrcs which contains
1965 // both RTX and regular SSRCs).
1966 FakeVideoSendStream* stream = SetUpSimulcast(false, true);
Erik Språng143cec12015-04-28 10:01:41 +02001967
1968 cricket::FakeVideoCapturer capturer;
Erik Språng143cec12015-04-28 10:01:41 +02001969 EXPECT_EQ(cricket::CS_RUNNING,
1970 capturer.Start(capturer.GetSupportedFormats()->front()));
deadbeef5a4a75a2016-06-02 16:23:38 -07001971 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, &capturer));
Erik Språng143cec12015-04-28 10:01:41 +02001972 channel_->SetSend(true);
1973
1974 EXPECT_TRUE(capturer.CaptureFrame());
1975
pbos4cba4eb2015-10-26 11:18:18 -07001976 webrtc::VideoCodecVP8 vp8_settings;
1977 ASSERT_TRUE(stream->GetVp8Settings(&vp8_settings)) << "No VP8 config set.";
1978 EXPECT_TRUE(vp8_settings.denoisingOn)
1979 << "VP8 denoising should be on by default.";
1980
nisse05103312016-03-16 02:22:50 -07001981 stream = SetDenoisingOption(last_ssrc_, &capturer, false);
Erik Språng143cec12015-04-28 10:01:41 +02001982
pbos@webrtc.org6f48f1b2014-07-22 16:29:54 +00001983 ASSERT_TRUE(stream->GetVp8Settings(&vp8_settings)) << "No VP8 config set.";
1984 EXPECT_FALSE(vp8_settings.denoisingOn);
Erik Språng143cec12015-04-28 10:01:41 +02001985 EXPECT_TRUE(vp8_settings.automaticResizeOn);
1986 EXPECT_TRUE(vp8_settings.frameDroppingOn);
pbos@webrtc.org6f48f1b2014-07-22 16:29:54 +00001987
nisse05103312016-03-16 02:22:50 -07001988 stream = SetDenoisingOption(last_ssrc_, &capturer, true);
pbos@webrtc.org6f48f1b2014-07-22 16:29:54 +00001989
pbos@webrtc.org6f48f1b2014-07-22 16:29:54 +00001990 ASSERT_TRUE(stream->GetVp8Settings(&vp8_settings)) << "No VP8 config set.";
1991 EXPECT_TRUE(vp8_settings.denoisingOn);
Erik Språng143cec12015-04-28 10:01:41 +02001992 EXPECT_TRUE(vp8_settings.automaticResizeOn);
1993 EXPECT_TRUE(vp8_settings.frameDroppingOn);
1994
deadbeef5a4a75a2016-06-02 16:23:38 -07001995 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, nullptr));
Peter Boström2feafdb2015-09-09 14:32:14 +02001996 stream = SetUpSimulcast(true, false);
deadbeef5a4a75a2016-06-02 16:23:38 -07001997 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, &capturer));
Erik Språng143cec12015-04-28 10:01:41 +02001998 channel_->SetSend(true);
1999 EXPECT_TRUE(capturer.CaptureFrame());
2000
2001 EXPECT_EQ(3, stream->GetVideoStreams().size());
2002 ASSERT_TRUE(stream->GetVp8Settings(&vp8_settings)) << "No VP8 config set.";
2003 // Autmatic resize off when using simulcast.
2004 EXPECT_FALSE(vp8_settings.automaticResizeOn);
2005 EXPECT_TRUE(vp8_settings.frameDroppingOn);
2006
2007 // In screen-share mode, denoising is forced off and simulcast disabled.
nisse05103312016-03-16 02:22:50 -07002008 VideoOptions options;
2009 options.is_screencast = rtc::Optional<bool>(true);
deadbeef5a4a75a2016-06-02 16:23:38 -07002010 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, &options, &capturer));
Niels Möller60653ba2016-03-02 11:41:36 +01002011
nisse05103312016-03-16 02:22:50 -07002012 stream = SetDenoisingOption(last_ssrc_, &capturer, false);
Erik Språng143cec12015-04-28 10:01:41 +02002013
2014 EXPECT_EQ(1, stream->GetVideoStreams().size());
2015 ASSERT_TRUE(stream->GetVp8Settings(&vp8_settings)) << "No VP8 config set.";
2016 EXPECT_FALSE(vp8_settings.denoisingOn);
2017 // Resizing and frame dropping always off for screen sharing.
2018 EXPECT_FALSE(vp8_settings.automaticResizeOn);
2019 EXPECT_FALSE(vp8_settings.frameDroppingOn);
2020
nisse05103312016-03-16 02:22:50 -07002021 stream = SetDenoisingOption(last_ssrc_, &capturer, true);
Erik Språng143cec12015-04-28 10:01:41 +02002022
2023 ASSERT_TRUE(stream->GetVp8Settings(&vp8_settings)) << "No VP8 config set.";
2024 EXPECT_FALSE(vp8_settings.denoisingOn);
2025 EXPECT_FALSE(vp8_settings.automaticResizeOn);
2026 EXPECT_FALSE(vp8_settings.frameDroppingOn);
2027
deadbeef5a4a75a2016-06-02 16:23:38 -07002028 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, nullptr));
Erik Språng143cec12015-04-28 10:01:41 +02002029}
2030
deadbeef119760a2016-04-04 11:43:27 -07002031// Test that setting the same options doesn't result in the encoder being
2032// reconfigured.
eladalonf1841382017-06-12 01:16:46 -07002033TEST_F(WebRtcVideoChannelTest, SetIdenticalOptionsDoesntReconfigureEncoder) {
deadbeef119760a2016-04-04 11:43:27 -07002034 VideoOptions options;
2035 cricket::FakeVideoCapturer capturer;
2036
perkjfa10b552016-10-02 23:45:26 -07002037 AddSendStream();
deadbeef119760a2016-04-04 11:43:27 -07002038 EXPECT_EQ(cricket::CS_RUNNING,
2039 capturer.Start(capturer.GetSupportedFormats()->front()));
perkjfa10b552016-10-02 23:45:26 -07002040 cricket::VideoSendParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08002041 parameters.codecs.push_back(GetEngineCodec("VP8"));
perkjfa10b552016-10-02 23:45:26 -07002042 ASSERT_TRUE(channel_->SetSendParameters(parameters));
2043 FakeVideoSendStream* send_stream = fake_call_->GetVideoSendStreams().front();
2044
2045 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, &options, &capturer));
deadbeef5a4a75a2016-06-02 16:23:38 -07002046 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, &options, &capturer));
deadbeef119760a2016-04-04 11:43:27 -07002047 EXPECT_TRUE(capturer.CaptureFrame());
perkjfa10b552016-10-02 23:45:26 -07002048 // Expect 1 reconfigurations at this point from the initial configuration.
2049 EXPECT_EQ(1, send_stream->num_encoder_reconfigurations());
deadbeef119760a2016-04-04 11:43:27 -07002050
2051 // Set the options one more time and expect no additional reconfigurations.
deadbeef5a4a75a2016-06-02 16:23:38 -07002052 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, &options, &capturer));
perkjfa10b552016-10-02 23:45:26 -07002053 EXPECT_EQ(1, send_stream->num_encoder_reconfigurations());
2054
2055 // Change |options| and expect 2 reconfigurations.
sprangf24a0642017-02-28 13:23:26 -08002056 options.video_noise_reduction = rtc::Optional<bool>(true);
perkjfa10b552016-10-02 23:45:26 -07002057 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, &options, &capturer));
deadbeef119760a2016-04-04 11:43:27 -07002058 EXPECT_EQ(2, send_stream->num_encoder_reconfigurations());
2059
deadbeef5a4a75a2016-06-02 16:23:38 -07002060 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, nullptr));
deadbeef119760a2016-04-04 11:43:27 -07002061}
2062
eladalonf1841382017-06-12 01:16:46 -07002063class Vp9SettingsTest : public WebRtcVideoChannelTest {
Erik Språng143cec12015-04-28 10:01:41 +02002064 public:
asaperssonc5dabdd2016-03-21 04:15:50 -07002065 Vp9SettingsTest() : Vp9SettingsTest("") {}
2066 explicit Vp9SettingsTest(const char* field_trials)
eladalonf1841382017-06-12 01:16:46 -07002067 : WebRtcVideoChannelTest(field_trials) {
Magnus Jedvert02e7a192017-09-23 17:21:32 +02002068 encoder_factory_->AddSupportedVideoCodecType("VP9");
Erik Språng143cec12015-04-28 10:01:41 +02002069 }
2070 virtual ~Vp9SettingsTest() {}
2071
2072 protected:
Erik Språng143cec12015-04-28 10:01:41 +02002073 void TearDown() override {
2074 // Remove references to encoder_factory_ since this will be destroyed
2075 // before channel_ and engine_.
Fredrik Solenbergb071a192015-09-17 16:42:56 +02002076 ASSERT_TRUE(channel_->SetSendParameters(send_parameters_));
Erik Språng143cec12015-04-28 10:01:41 +02002077 }
Erik Språng143cec12015-04-28 10:01:41 +02002078};
2079
2080TEST_F(Vp9SettingsTest, VerifyVp9SpecificSettings) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02002081 cricket::VideoSendParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08002082 parameters.codecs.push_back(GetEngineCodec("VP9"));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02002083 ASSERT_TRUE(channel_->SetSendParameters(parameters));
Erik Språng143cec12015-04-28 10:01:41 +02002084
Peter Boström2feafdb2015-09-09 14:32:14 +02002085 FakeVideoSendStream* stream = SetUpSimulcast(false, false);
Erik Språng143cec12015-04-28 10:01:41 +02002086
2087 cricket::FakeVideoCapturer capturer;
Erik Språng143cec12015-04-28 10:01:41 +02002088 EXPECT_EQ(cricket::CS_RUNNING,
2089 capturer.Start(capturer.GetSupportedFormats()->front()));
deadbeef5a4a75a2016-06-02 16:23:38 -07002090 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, &capturer));
Erik Språng143cec12015-04-28 10:01:41 +02002091 channel_->SetSend(true);
2092
2093 EXPECT_TRUE(capturer.CaptureFrame());
2094
pbos4cba4eb2015-10-26 11:18:18 -07002095 webrtc::VideoCodecVP9 vp9_settings;
2096 ASSERT_TRUE(stream->GetVp9Settings(&vp9_settings)) << "No VP9 config set.";
jianja5e8aa62017-03-27 10:09:00 -07002097 EXPECT_TRUE(vp9_settings.denoisingOn)
2098 << "VP9 denoising should be on by default.";
pbos4cba4eb2015-10-26 11:18:18 -07002099
nisse05103312016-03-16 02:22:50 -07002100 stream = SetDenoisingOption(last_ssrc_, &capturer, false);
Erik Språng143cec12015-04-28 10:01:41 +02002101
Erik Språng143cec12015-04-28 10:01:41 +02002102 ASSERT_TRUE(stream->GetVp9Settings(&vp9_settings)) << "No VP9 config set.";
2103 EXPECT_FALSE(vp9_settings.denoisingOn);
2104 // Frame dropping always on for real time video.
2105 EXPECT_TRUE(vp9_settings.frameDroppingOn);
2106
nisse05103312016-03-16 02:22:50 -07002107 stream = SetDenoisingOption(last_ssrc_, &capturer, true);
Erik Språng143cec12015-04-28 10:01:41 +02002108
2109 ASSERT_TRUE(stream->GetVp9Settings(&vp9_settings)) << "No VP9 config set.";
2110 EXPECT_TRUE(vp9_settings.denoisingOn);
2111 EXPECT_TRUE(vp9_settings.frameDroppingOn);
2112
2113 // In screen-share mode, denoising is forced off.
nisse05103312016-03-16 02:22:50 -07002114 VideoOptions options;
2115 options.is_screencast = rtc::Optional<bool>(true);
deadbeef5a4a75a2016-06-02 16:23:38 -07002116 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, &options, &capturer));
perkj2d5f0912016-02-29 00:04:41 -08002117
nisse05103312016-03-16 02:22:50 -07002118 stream = SetDenoisingOption(last_ssrc_, &capturer, false);
Erik Språng143cec12015-04-28 10:01:41 +02002119
2120 ASSERT_TRUE(stream->GetVp9Settings(&vp9_settings)) << "No VP9 config set.";
2121 EXPECT_FALSE(vp9_settings.denoisingOn);
2122 // Frame dropping always off for screen sharing.
2123 EXPECT_FALSE(vp9_settings.frameDroppingOn);
2124
nisse05103312016-03-16 02:22:50 -07002125 stream = SetDenoisingOption(last_ssrc_, &capturer, false);
Erik Språng143cec12015-04-28 10:01:41 +02002126
2127 ASSERT_TRUE(stream->GetVp9Settings(&vp9_settings)) << "No VP9 config set.";
2128 EXPECT_FALSE(vp9_settings.denoisingOn);
2129 EXPECT_FALSE(vp9_settings.frameDroppingOn);
2130
deadbeef5a4a75a2016-06-02 16:23:38 -07002131 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, nullptr));
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00002132}
2133
asaperssonc5dabdd2016-03-21 04:15:50 -07002134class Vp9SettingsTestWithFieldTrial : public Vp9SettingsTest {
2135 public:
brandtr468da7c2016-11-22 02:16:47 -08002136 explicit Vp9SettingsTestWithFieldTrial(const char* field_trials)
asaperssonc5dabdd2016-03-21 04:15:50 -07002137 : Vp9SettingsTest(field_trials) {}
2138
2139 protected:
2140 void VerifySettings(int num_spatial_layers, int num_temporal_layers) {
2141 cricket::VideoSendParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08002142 parameters.codecs.push_back(GetEngineCodec("VP9"));
asaperssonc5dabdd2016-03-21 04:15:50 -07002143 ASSERT_TRUE(channel_->SetSendParameters(parameters));
2144
2145 FakeVideoSendStream* stream = SetUpSimulcast(false, false);
2146
2147 cricket::FakeVideoCapturer capturer;
2148 EXPECT_EQ(cricket::CS_RUNNING,
2149 capturer.Start(capturer.GetSupportedFormats()->front()));
deadbeef5a4a75a2016-06-02 16:23:38 -07002150 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, &capturer));
asaperssonc5dabdd2016-03-21 04:15:50 -07002151 channel_->SetSend(true);
2152
2153 EXPECT_TRUE(capturer.CaptureFrame());
2154
2155 webrtc::VideoCodecVP9 vp9_settings;
2156 ASSERT_TRUE(stream->GetVp9Settings(&vp9_settings)) << "No VP9 config set.";
2157 EXPECT_EQ(num_spatial_layers, vp9_settings.numberOfSpatialLayers);
2158 EXPECT_EQ(num_temporal_layers, vp9_settings.numberOfTemporalLayers);
2159
deadbeef5a4a75a2016-06-02 16:23:38 -07002160 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, nullptr));
asaperssonc5dabdd2016-03-21 04:15:50 -07002161 }
2162};
2163
2164class Vp9SettingsTestWithNoFlag : public Vp9SettingsTestWithFieldTrial {
2165 public:
2166 Vp9SettingsTestWithNoFlag() : Vp9SettingsTestWithFieldTrial("") {}
2167};
2168
2169TEST_F(Vp9SettingsTestWithNoFlag, VerifySettings) {
2170 const int kNumSpatialLayers = 1;
2171 const int kNumTemporalLayers = 1;
2172 VerifySettings(kNumSpatialLayers, kNumTemporalLayers);
2173}
2174
2175class Vp9SettingsTestWithInvalidFlag : public Vp9SettingsTestWithFieldTrial {
2176 public:
2177 Vp9SettingsTestWithInvalidFlag()
2178 : Vp9SettingsTestWithFieldTrial("WebRTC-SupportVP9SVC/Default/") {}
2179};
2180
2181TEST_F(Vp9SettingsTestWithInvalidFlag, VerifySettings) {
2182 const int kNumSpatialLayers = 1;
2183 const int kNumTemporalLayers = 1;
2184 VerifySettings(kNumSpatialLayers, kNumTemporalLayers);
2185}
2186
2187class Vp9SettingsTestWith2SL3TLFlag : public Vp9SettingsTestWithFieldTrial {
2188 public:
2189 Vp9SettingsTestWith2SL3TLFlag()
2190 : Vp9SettingsTestWithFieldTrial(
2191 "WebRTC-SupportVP9SVC/EnabledByFlag_2SL3TL/") {}
2192};
2193
2194TEST_F(Vp9SettingsTestWith2SL3TLFlag, VerifySettings) {
2195 const int kNumSpatialLayers = 2;
2196 const int kNumTemporalLayers = 3;
2197 VerifySettings(kNumSpatialLayers, kNumTemporalLayers);
2198}
2199
asapersson3c81a1a2017-06-14 05:52:21 -07002200TEST_F(WebRtcVideoChannelTest,
2201 BalancedDegradationPreferenceNotSupportedWithoutFieldtrial) {
2202 webrtc::test::ScopedFieldTrials override_field_trials_(
2203 "WebRTC-Video-BalancedDegradation/Disabled/");
2204 const bool kResolutionScalingEnabled = true;
2205 const bool kFpsScalingEnabled = false;
2206 TestDegradationPreference(kResolutionScalingEnabled, kFpsScalingEnabled);
2207}
2208
2209TEST_F(WebRtcVideoChannelTest,
2210 BalancedDegradationPreferenceSupportedBehindFieldtrial) {
2211 webrtc::test::ScopedFieldTrials override_field_trials_(
2212 "WebRTC-Video-BalancedDegradation/Enabled/");
2213 const bool kResolutionScalingEnabled = true;
2214 const bool kFpsScalingEnabled = true;
2215 TestDegradationPreference(kResolutionScalingEnabled, kFpsScalingEnabled);
2216}
2217
eladalonf1841382017-06-12 01:16:46 -07002218TEST_F(WebRtcVideoChannelTest, AdaptsOnOveruse) {
Erik Språngefbde372015-04-29 16:21:28 +02002219 TestCpuAdaptation(true, false);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00002220}
2221
eladalonf1841382017-06-12 01:16:46 -07002222TEST_F(WebRtcVideoChannelTest, DoesNotAdaptOnOveruseWhenDisabled) {
Erik Språngefbde372015-04-29 16:21:28 +02002223 TestCpuAdaptation(false, false);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00002224}
2225
eladalonf1841382017-06-12 01:16:46 -07002226TEST_F(WebRtcVideoChannelTest, DoesNotAdaptOnOveruseWhenScreensharing) {
Erik Språngefbde372015-04-29 16:21:28 +02002227 TestCpuAdaptation(true, true);
2228}
2229
eladalonf1841382017-06-12 01:16:46 -07002230TEST_F(WebRtcVideoChannelTest, AdaptsOnOveruseAndChangeResolution) {
magjed509e4fe2016-11-18 01:34:11 -08002231 cricket::VideoCodec codec = GetEngineCodec("VP8");
perkj2d5f0912016-02-29 00:04:41 -08002232 cricket::VideoSendParameters parameters;
2233 parameters.codecs.push_back(codec);
2234
kthelgason2bc68642017-02-07 07:02:22 -08002235 MediaConfig media_config = GetMediaConfig();
perkj2d5f0912016-02-29 00:04:41 -08002236 channel_.reset(
2237 engine_.CreateChannel(fake_call_.get(), media_config, VideoOptions()));
Sergey Ulanove2b15012016-11-22 16:08:30 -08002238 channel_->OnReadyToSend(true);
perkj2d5f0912016-02-29 00:04:41 -08002239 ASSERT_TRUE(channel_->SetSendParameters(parameters));
2240
2241 AddSendStream();
2242
2243 cricket::FakeVideoCapturer capturer;
deadbeef5a4a75a2016-06-02 16:23:38 -07002244 ASSERT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, &capturer));
perkj2d5f0912016-02-29 00:04:41 -08002245 ASSERT_EQ(cricket::CS_RUNNING,
2246 capturer.Start(capturer.GetSupportedFormats()->front()));
2247 ASSERT_TRUE(channel_->SetSend(true));
2248
2249 ASSERT_EQ(1u, fake_call_->GetVideoSendStreams().size());
2250 FakeVideoSendStream* send_stream = fake_call_->GetVideoSendStreams().front();
perkj2d5f0912016-02-29 00:04:41 -08002251
2252 EXPECT_TRUE(capturer.CaptureCustomFrame(1280, 720, cricket::FOURCC_I420));
2253 EXPECT_EQ(1, send_stream->GetNumberOfSwappedFrames());
2254 EXPECT_EQ(1280, send_stream->GetLastWidth());
2255 EXPECT_EQ(720, send_stream->GetLastHeight());
2256
2257 // Trigger overuse.
perkj803d97f2016-11-01 11:45:46 -07002258 rtc::VideoSinkWants wants;
sprangc5d62e22017-04-02 23:53:04 -07002259 wants.max_pixel_count =
2260 send_stream->GetLastWidth() * send_stream->GetLastHeight() - 1;
perkj803d97f2016-11-01 11:45:46 -07002261 send_stream->InjectVideoSinkWants(wants);
perkj2d5f0912016-02-29 00:04:41 -08002262 EXPECT_TRUE(capturer.CaptureCustomFrame(1280, 720, cricket::FOURCC_I420));
2263 EXPECT_EQ(2, send_stream->GetNumberOfSwappedFrames());
2264 EXPECT_EQ(1280 * 3 / 4, send_stream->GetLastWidth());
2265 EXPECT_EQ(720 * 3 / 4, send_stream->GetLastHeight());
2266
2267 // Trigger overuse again.
sprangc5d62e22017-04-02 23:53:04 -07002268 wants.max_pixel_count =
2269 send_stream->GetLastWidth() * send_stream->GetLastHeight() - 1;
perkj803d97f2016-11-01 11:45:46 -07002270 send_stream->InjectVideoSinkWants(wants);
perkj2d5f0912016-02-29 00:04:41 -08002271 EXPECT_TRUE(capturer.CaptureCustomFrame(1280, 720, cricket::FOURCC_I420));
2272 EXPECT_EQ(3, send_stream->GetNumberOfSwappedFrames());
2273 EXPECT_EQ(1280 * 2 / 4, send_stream->GetLastWidth());
2274 EXPECT_EQ(720 * 2 / 4, send_stream->GetLastHeight());
2275
2276 // Change input resolution.
2277 EXPECT_TRUE(capturer.CaptureCustomFrame(1284, 724, cricket::FOURCC_I420));
perkj803d97f2016-11-01 11:45:46 -07002278 EXPECT_EQ(4, send_stream->GetNumberOfSwappedFrames());
perkj2d5f0912016-02-29 00:04:41 -08002279 EXPECT_EQ(1284 / 2, send_stream->GetLastWidth());
2280 EXPECT_EQ(724 / 2, send_stream->GetLastHeight());
2281
2282 // Trigger underuse which should go back up in resolution.
sprang84a37592017-02-10 07:04:27 -08002283 int current_pixel_count =
2284 send_stream->GetLastWidth() * send_stream->GetLastHeight();
2285 // Cap the max to 4x the pixel count (assuming max 1/2 x 1/2 scale downs)
2286 // of the current stream, so we don't take too large steps.
sprangc5d62e22017-04-02 23:53:04 -07002287 wants.max_pixel_count = current_pixel_count * 4;
sprang84a37592017-02-10 07:04:27 -08002288 // Default step down is 3/5 pixel count, so go up by 5/3.
2289 wants.target_pixel_count = rtc::Optional<int>((current_pixel_count * 5) / 3);
perkj803d97f2016-11-01 11:45:46 -07002290 send_stream->InjectVideoSinkWants(wants);
perkj2d5f0912016-02-29 00:04:41 -08002291 EXPECT_TRUE(capturer.CaptureCustomFrame(1284, 724, cricket::FOURCC_I420));
perkj803d97f2016-11-01 11:45:46 -07002292 EXPECT_EQ(5, send_stream->GetNumberOfSwappedFrames());
perkj2d5f0912016-02-29 00:04:41 -08002293 EXPECT_EQ(1284 * 3 / 4, send_stream->GetLastWidth());
2294 EXPECT_EQ(724 * 3 / 4, send_stream->GetLastHeight());
2295
sprang84a37592017-02-10 07:04:27 -08002296 // Trigger underuse again, should go back up to full resolution.
2297 current_pixel_count =
2298 send_stream->GetLastWidth() * send_stream->GetLastHeight();
sprangc5d62e22017-04-02 23:53:04 -07002299 wants.max_pixel_count = current_pixel_count * 4;
sprang84a37592017-02-10 07:04:27 -08002300 wants.target_pixel_count = rtc::Optional<int>((current_pixel_count * 5) / 3);
perkj803d97f2016-11-01 11:45:46 -07002301 send_stream->InjectVideoSinkWants(wants);
perkj2d5f0912016-02-29 00:04:41 -08002302 EXPECT_TRUE(capturer.CaptureCustomFrame(1284, 724, cricket::FOURCC_I420));
perkj803d97f2016-11-01 11:45:46 -07002303 EXPECT_EQ(6, send_stream->GetNumberOfSwappedFrames());
perkj2d5f0912016-02-29 00:04:41 -08002304 EXPECT_EQ(1284, send_stream->GetLastWidth());
2305 EXPECT_EQ(724, send_stream->GetLastHeight());
2306
deadbeef5a4a75a2016-06-02 16:23:38 -07002307 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, nullptr));
perkj2d5f0912016-02-29 00:04:41 -08002308}
2309
eladalonf1841382017-06-12 01:16:46 -07002310TEST_F(WebRtcVideoChannelTest, PreviousAdaptationDoesNotApplyToScreenshare) {
magjed509e4fe2016-11-18 01:34:11 -08002311 cricket::VideoCodec codec = GetEngineCodec("VP8");
Per766ad3b2016-04-05 15:23:49 +02002312 cricket::VideoSendParameters parameters;
2313 parameters.codecs.push_back(codec);
2314
kthelgason2bc68642017-02-07 07:02:22 -08002315 MediaConfig media_config = GetMediaConfig();
2316 media_config.video.enable_cpu_overuse_detection = true;
Per766ad3b2016-04-05 15:23:49 +02002317 channel_.reset(
2318 engine_.CreateChannel(fake_call_.get(), media_config, VideoOptions()));
Sergey Ulanove2b15012016-11-22 16:08:30 -08002319 channel_->OnReadyToSend(true);
Per766ad3b2016-04-05 15:23:49 +02002320 ASSERT_TRUE(channel_->SetSendParameters(parameters));
2321
2322 AddSendStream();
2323
2324 cricket::FakeVideoCapturer capturer;
Per766ad3b2016-04-05 15:23:49 +02002325 ASSERT_EQ(cricket::CS_RUNNING,
2326 capturer.Start(capturer.GetSupportedFormats()->front()));
2327 ASSERT_TRUE(channel_->SetSend(true));
2328 cricket::VideoOptions camera_options;
perkj803d97f2016-11-01 11:45:46 -07002329 camera_options.is_screencast = rtc::Optional<bool>(false);
deadbeef5a4a75a2016-06-02 16:23:38 -07002330 channel_->SetVideoSend(last_ssrc_, true /* enable */, &camera_options,
2331 &capturer);
Per766ad3b2016-04-05 15:23:49 +02002332
2333 ASSERT_EQ(1u, fake_call_->GetVideoSendStreams().size());
2334 FakeVideoSendStream* send_stream = fake_call_->GetVideoSendStreams().front();
Per766ad3b2016-04-05 15:23:49 +02002335
2336 EXPECT_TRUE(capturer.CaptureCustomFrame(1280, 720, cricket::FOURCC_I420));
2337 EXPECT_EQ(1, send_stream->GetNumberOfSwappedFrames());
2338 EXPECT_EQ(1280, send_stream->GetLastWidth());
2339 EXPECT_EQ(720, send_stream->GetLastHeight());
2340
2341 // Trigger overuse.
perkj803d97f2016-11-01 11:45:46 -07002342 rtc::VideoSinkWants wants;
sprangc5d62e22017-04-02 23:53:04 -07002343 wants.max_pixel_count =
2344 send_stream->GetLastWidth() * send_stream->GetLastHeight() - 1;
perkj803d97f2016-11-01 11:45:46 -07002345 send_stream->InjectVideoSinkWants(wants);
Per766ad3b2016-04-05 15:23:49 +02002346 EXPECT_TRUE(capturer.CaptureCustomFrame(1280, 720, cricket::FOURCC_I420));
2347 EXPECT_EQ(2, send_stream->GetNumberOfSwappedFrames());
2348 EXPECT_EQ(1280 * 3 / 4, send_stream->GetLastWidth());
2349 EXPECT_EQ(720 * 3 / 4, send_stream->GetLastHeight());
2350
2351 // Switch to screen share. Expect no CPU adaptation.
2352 cricket::FakeVideoCapturer screen_share(true);
2353 ASSERT_EQ(cricket::CS_RUNNING,
2354 screen_share.Start(screen_share.GetSupportedFormats()->front()));
Per766ad3b2016-04-05 15:23:49 +02002355 cricket::VideoOptions screenshare_options;
2356 screenshare_options.is_screencast = rtc::Optional<bool>(true);
deadbeef5a4a75a2016-06-02 16:23:38 -07002357 channel_->SetVideoSend(last_ssrc_, true /* enable */, &screenshare_options,
2358 &screen_share);
Per766ad3b2016-04-05 15:23:49 +02002359 EXPECT_TRUE(screen_share.CaptureCustomFrame(1284, 724, cricket::FOURCC_I420));
sprangf24a0642017-02-28 13:23:26 -08002360 ASSERT_EQ(2, fake_call_->GetNumCreatedSendStreams());
2361 send_stream = fake_call_->GetVideoSendStreams().front();
2362 EXPECT_EQ(1, send_stream->GetNumberOfSwappedFrames());
Per766ad3b2016-04-05 15:23:49 +02002363 EXPECT_EQ(1284, send_stream->GetLastWidth());
2364 EXPECT_EQ(724, send_stream->GetLastHeight());
2365
2366 // Switch back to the normal capturer. Expect the frame to be CPU adapted.
deadbeef5a4a75a2016-06-02 16:23:38 -07002367 channel_->SetVideoSend(last_ssrc_, true /* enable */, &camera_options,
2368 &capturer);
sprangf24a0642017-02-28 13:23:26 -08002369 send_stream = fake_call_->GetVideoSendStreams().front();
2370 // We have a new fake send stream, so it doesn't remember the old sink wants.
2371 // In practice, it will be populated from
mflodmancc3d4422017-08-03 08:27:51 -07002372 // VideoStreamEncoder::VideoSourceProxy::SetSource(), so simulate that here.
sprangf24a0642017-02-28 13:23:26 -08002373 send_stream->InjectVideoSinkWants(wants);
Per766ad3b2016-04-05 15:23:49 +02002374 EXPECT_TRUE(capturer.CaptureCustomFrame(1280, 720, cricket::FOURCC_I420));
sprangf24a0642017-02-28 13:23:26 -08002375 ASSERT_EQ(3, fake_call_->GetNumCreatedSendStreams());
2376 send_stream = fake_call_->GetVideoSendStreams().front();
2377 EXPECT_EQ(1, send_stream->GetNumberOfSwappedFrames());
Per766ad3b2016-04-05 15:23:49 +02002378 EXPECT_EQ(1280 * 3 / 4, send_stream->GetLastWidth());
2379 EXPECT_EQ(720 * 3 / 4, send_stream->GetLastHeight());
2380
deadbeef5a4a75a2016-06-02 16:23:38 -07002381 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, nullptr));
Per766ad3b2016-04-05 15:23:49 +02002382}
2383
asapersson3c81a1a2017-06-14 05:52:21 -07002384// TODO(asapersson): Remove this test when the balanced field trial is removed.
2385void WebRtcVideoChannelTest::TestDegradationPreference(
2386 bool resolution_scaling_enabled,
2387 bool fps_scaling_enabled) {
2388 cricket::VideoCodec codec = GetEngineCodec("VP8");
2389 cricket::VideoSendParameters parameters;
2390 parameters.codecs.push_back(codec);
2391
2392 MediaConfig media_config = GetMediaConfig();
2393 media_config.video.enable_cpu_overuse_detection = true;
2394 channel_.reset(
2395 engine_.CreateChannel(fake_call_.get(), media_config, VideoOptions()));
2396 channel_->OnReadyToSend(true);
2397
2398 EXPECT_TRUE(channel_->SetSendParameters(parameters));
2399
2400 AddSendStream();
2401
2402 cricket::FakeVideoCapturer capturer;
2403 VideoOptions options;
2404 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, &options, &capturer));
2405 cricket::VideoFormat capture_format = capturer.GetSupportedFormats()->front();
2406 EXPECT_EQ(cricket::CS_RUNNING, capturer.Start(capture_format));
2407
2408 EXPECT_TRUE(channel_->SetSend(true));
2409
2410 FakeVideoSendStream* send_stream = fake_call_->GetVideoSendStreams().front();
2411 EXPECT_EQ(resolution_scaling_enabled,
2412 send_stream->resolution_scaling_enabled());
2413 EXPECT_EQ(fps_scaling_enabled, send_stream->framerate_scaling_enabled());
2414
2415 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, nullptr));
2416}
2417
eladalonf1841382017-06-12 01:16:46 -07002418void WebRtcVideoChannelTest::TestCpuAdaptation(bool enable_overuse,
2419 bool is_screenshare) {
sprangc5d62e22017-04-02 23:53:04 -07002420 const int kDefaultFps = 30;
magjed509e4fe2016-11-18 01:34:11 -08002421 cricket::VideoCodec codec = GetEngineCodec("VP8");
Fredrik Solenbergb071a192015-09-17 16:42:56 +02002422 cricket::VideoSendParameters parameters;
2423 parameters.codecs.push_back(codec);
nisse51542be2016-02-12 02:27:06 -08002424
kthelgason2bc68642017-02-07 07:02:22 -08002425 MediaConfig media_config = GetMediaConfig();
2426 if (enable_overuse) {
2427 media_config.video.enable_cpu_overuse_detection = true;
pbos@webrtc.org42684be2014-10-03 11:25:45 +00002428 }
nisse51542be2016-02-12 02:27:06 -08002429 channel_.reset(
2430 engine_.CreateChannel(fake_call_.get(), media_config, VideoOptions()));
Sergey Ulanove2b15012016-11-22 16:08:30 -08002431 channel_->OnReadyToSend(true);
nisse51542be2016-02-12 02:27:06 -08002432
Fredrik Solenbergb071a192015-09-17 16:42:56 +02002433 EXPECT_TRUE(channel_->SetSendParameters(parameters));
pbos@webrtc.org42684be2014-10-03 11:25:45 +00002434
2435 AddSendStream();
2436
deadbeef5a4a75a2016-06-02 16:23:38 -07002437 cricket::FakeVideoCapturer capturer;
nisse05103312016-03-16 02:22:50 -07002438 VideoOptions options;
2439 options.is_screencast = rtc::Optional<bool>(is_screenshare);
deadbeef5a4a75a2016-06-02 16:23:38 -07002440 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, &options, &capturer));
perkj26752742016-10-24 01:21:16 -07002441 cricket::VideoFormat capture_format = capturer.GetSupportedFormats()->front();
sprangc5d62e22017-04-02 23:53:04 -07002442 capture_format.interval = rtc::kNumNanosecsPerSec / kDefaultFps;
perkj26752742016-10-24 01:21:16 -07002443 EXPECT_EQ(cricket::CS_RUNNING, capturer.Start(capture_format));
pbos@webrtc.org42684be2014-10-03 11:25:45 +00002444
2445 EXPECT_TRUE(channel_->SetSend(true));
2446
solenberge5269742015-09-08 05:13:22 -07002447 FakeVideoSendStream* send_stream = fake_call_->GetVideoSendStreams().front();
perkj2d5f0912016-02-29 00:04:41 -08002448
sprangc5d62e22017-04-02 23:53:04 -07002449 if (!enable_overuse) {
perkj803d97f2016-11-01 11:45:46 -07002450 EXPECT_FALSE(send_stream->resolution_scaling_enabled());
sprangc5d62e22017-04-02 23:53:04 -07002451 EXPECT_FALSE(send_stream->framerate_scaling_enabled());
2452 EXPECT_EQ(is_screenshare, send_stream->framerate_scaling_enabled());
perkj2d5f0912016-02-29 00:04:41 -08002453
2454 EXPECT_TRUE(capturer.CaptureFrame());
2455 EXPECT_EQ(1, send_stream->GetNumberOfSwappedFrames());
2456
perkj26752742016-10-24 01:21:16 -07002457 EXPECT_EQ(capture_format.width, send_stream->GetLastWidth());
2458 EXPECT_EQ(capture_format.height, send_stream->GetLastHeight());
perkj2d5f0912016-02-29 00:04:41 -08002459
deadbeef5a4a75a2016-06-02 16:23:38 -07002460 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, nullptr));
perkj2d5f0912016-02-29 00:04:41 -08002461 return;
2462 }
2463
sprangc5d62e22017-04-02 23:53:04 -07002464 if (is_screenshare) {
2465 EXPECT_FALSE(send_stream->resolution_scaling_enabled());
2466 EXPECT_TRUE(send_stream->framerate_scaling_enabled());
2467 } else {
2468 EXPECT_TRUE(send_stream->resolution_scaling_enabled());
2469 EXPECT_FALSE(send_stream->framerate_scaling_enabled());
2470 }
2471
perkj803d97f2016-11-01 11:45:46 -07002472 // Trigger overuse.
2473 ASSERT_EQ(1u, fake_call_->GetVideoSendStreams().size());
2474
2475 rtc::VideoSinkWants wants;
sprangc5d62e22017-04-02 23:53:04 -07002476 if (is_screenshare) {
2477 wants.max_framerate_fps = (kDefaultFps * 2) / 3;
2478 } else {
2479 wants.max_pixel_count = capture_format.width * capture_format.height - 1;
2480 }
perkj803d97f2016-11-01 11:45:46 -07002481 send_stream->InjectVideoSinkWants(wants);
2482
sprangc5d62e22017-04-02 23:53:04 -07002483 for (int i = 0; i < kDefaultFps; ++i)
2484 EXPECT_TRUE(capturer.CaptureFrame());
pbos@webrtc.org42684be2014-10-03 11:25:45 +00002485
sprangc5d62e22017-04-02 23:53:04 -07002486 if (is_screenshare) {
2487 // Drops every third frame.
2488 EXPECT_EQ(kDefaultFps * 2 / 3, send_stream->GetNumberOfSwappedFrames());
2489 EXPECT_EQ(send_stream->GetLastWidth(), capture_format.width);
2490 EXPECT_EQ(send_stream->GetLastHeight(), capture_format.height);
2491 } else {
2492 EXPECT_EQ(kDefaultFps, send_stream->GetNumberOfSwappedFrames());
2493 EXPECT_LT(send_stream->GetLastWidth(), capture_format.width);
2494 EXPECT_LT(send_stream->GetLastHeight(), capture_format.height);
2495 }
pbos@webrtc.org42684be2014-10-03 11:25:45 +00002496
2497 // Trigger underuse which should go back to normal resolution.
sprang84a37592017-02-10 07:04:27 -08002498 int last_pixel_count =
2499 send_stream->GetLastWidth() * send_stream->GetLastHeight();
sprangc5d62e22017-04-02 23:53:04 -07002500 if (is_screenshare) {
2501 wants.max_framerate_fps = kDefaultFps;
2502 } else {
2503 wants.max_pixel_count = last_pixel_count * 4;
2504 wants.target_pixel_count.emplace((last_pixel_count * 5) / 3);
2505 }
perkj803d97f2016-11-01 11:45:46 -07002506 send_stream->InjectVideoSinkWants(wants);
2507
sprangc5d62e22017-04-02 23:53:04 -07002508 for (int i = 0; i < kDefaultFps; ++i)
2509 EXPECT_TRUE(capturer.CaptureFrame());
2510
2511 if (is_screenshare) {
2512 EXPECT_EQ(kDefaultFps + (kDefaultFps * 2 / 3),
2513 send_stream->GetNumberOfSwappedFrames());
2514 } else {
2515 EXPECT_EQ(kDefaultFps * 2, send_stream->GetNumberOfSwappedFrames());
2516 }
pbos@webrtc.org42684be2014-10-03 11:25:45 +00002517
perkj26752742016-10-24 01:21:16 -07002518 EXPECT_EQ(capture_format.width, send_stream->GetLastWidth());
2519 EXPECT_EQ(capture_format.height, send_stream->GetLastHeight());
pbos@webrtc.org42684be2014-10-03 11:25:45 +00002520
deadbeef5a4a75a2016-06-02 16:23:38 -07002521 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, nullptr));
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00002522}
2523
eladalonf1841382017-06-12 01:16:46 -07002524TEST_F(WebRtcVideoChannelTest, EstimatesNtpStartTimeCorrectly) {
magjed@webrtc.orgfc5ad952015-01-27 09:57:01 +00002525 // Start at last timestamp to verify that wraparounds are estimated correctly.
2526 static const uint32_t kInitialTimestamp = 0xFFFFFFFFu;
2527 static const int64_t kInitialNtpTimeMs = 1247891230;
2528 static const int kFrameOffsetMs = 20;
Fredrik Solenbergb071a192015-09-17 16:42:56 +02002529 EXPECT_TRUE(channel_->SetRecvParameters(recv_parameters_));
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00002530
magjed@webrtc.orgfc5ad952015-01-27 09:57:01 +00002531 FakeVideoReceiveStream* stream = AddRecvStream();
2532 cricket::FakeVideoRenderer renderer;
nisse08582ff2016-02-04 01:24:52 -08002533 EXPECT_TRUE(channel_->SetSink(last_ssrc_, &renderer));
magjed@webrtc.orgfc5ad952015-01-27 09:57:01 +00002534
nisse64ec8f82016-09-27 00:17:25 -07002535 webrtc::VideoFrame video_frame(CreateBlackFrameBuffer(4, 4),
2536 kInitialTimestamp, 0,
2537 webrtc::kVideoRotation_0);
magjed@webrtc.orgfc5ad952015-01-27 09:57:01 +00002538 // Initial NTP time is not available on the first frame, but should still be
2539 // able to be estimated.
nisseeb83a1a2016-03-21 01:27:56 -07002540 stream->InjectFrame(video_frame);
magjed@webrtc.orgfc5ad952015-01-27 09:57:01 +00002541
2542 EXPECT_EQ(1, renderer.num_rendered_frames());
magjed@webrtc.orgfc5ad952015-01-27 09:57:01 +00002543
2544 // This timestamp is kInitialTimestamp (-1) + kFrameOffsetMs * 90, which
2545 // triggers a constant-overflow warning, hence we're calculating it explicitly
2546 // here.
2547 video_frame.set_timestamp(kFrameOffsetMs * 90 - 1);
2548 video_frame.set_ntp_time_ms(kInitialNtpTimeMs + kFrameOffsetMs);
nisseeb83a1a2016-03-21 01:27:56 -07002549 stream->InjectFrame(video_frame);
magjed@webrtc.orgfc5ad952015-01-27 09:57:01 +00002550
2551 EXPECT_EQ(2, renderer.num_rendered_frames());
magjed@webrtc.orgfc5ad952015-01-27 09:57:01 +00002552
2553 // Verify that NTP time has been correctly deduced.
2554 cricket::VideoMediaInfo info;
pbos@webrtc.org058b1f12015-03-04 08:54:32 +00002555 ASSERT_TRUE(channel_->GetStats(&info));
magjed@webrtc.orgfc5ad952015-01-27 09:57:01 +00002556 ASSERT_EQ(1u, info.receivers.size());
2557 EXPECT_EQ(kInitialNtpTimeMs, info.receivers[0].capture_start_ntp_time_ms);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00002558}
2559
eladalonf1841382017-06-12 01:16:46 -07002560TEST_F(WebRtcVideoChannelTest, SetDefaultSendCodecs) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02002561 ASSERT_TRUE(channel_->SetSendParameters(send_parameters_));
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00002562
2563 VideoCodec codec;
2564 EXPECT_TRUE(channel_->GetSendCodec(&codec));
pbos@webrtc.org9fbb7172014-06-13 09:34:13 +00002565 EXPECT_TRUE(codec.Matches(engine_.codecs()[0]));
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00002566
2567 // Using a RTX setup to verify that the default RTX payload type is good.
Peter Boström0c4e06b2015-10-07 12:23:21 +02002568 const std::vector<uint32_t> ssrcs = MAKE_VECTOR(kSsrcs1);
2569 const std::vector<uint32_t> rtx_ssrcs = MAKE_VECTOR(kRtxSsrcs1);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00002570 FakeVideoSendStream* stream = AddSendStream(
2571 cricket::CreateSimWithRtxStreamParams("cname", ssrcs, rtx_ssrcs));
perkj26091b12016-09-01 01:17:40 -07002572 webrtc::VideoSendStream::Config config = stream->GetConfig().Copy();
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00002573
2574 // Make sure NACK and FEC are enabled on the correct payload types.
2575 EXPECT_EQ(1000, config.rtp.nack.rtp_history_ms);
magjed509e4fe2016-11-18 01:34:11 -08002576 EXPECT_EQ(GetEngineCodec("ulpfec").id, config.rtp.ulpfec.ulpfec_payload_type);
2577 EXPECT_EQ(GetEngineCodec("red").id, config.rtp.ulpfec.red_payload_type);
pbos@webrtc.org269605c2014-06-26 08:49:03 +00002578
2579 EXPECT_EQ(1u, config.rtp.rtx.ssrcs.size());
2580 EXPECT_EQ(kRtxSsrcs1[0], config.rtp.rtx.ssrcs[0]);
Shao Changbine62202f2015-04-21 20:24:50 +08002581 VerifySendStreamHasRtxTypes(config, default_apt_rtx_types_);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00002582 // TODO(juberti): Check RTCP, PLI, TMMBR.
2583}
2584
brandtr31bd2242017-05-19 05:47:46 -07002585// The following four tests ensures that FlexFEC is not activated by default
2586// when the field trials are not enabled.
2587// TODO(brandtr): Remove or update these tests when FlexFEC _is_ enabled by
2588// default.
eladalonf1841382017-06-12 01:16:46 -07002589TEST_F(WebRtcVideoChannelTest,
brandtr31bd2242017-05-19 05:47:46 -07002590 FlexfecSendCodecWithoutSsrcNotExposedByDefault) {
brandtr468da7c2016-11-22 02:16:47 -08002591 FakeVideoSendStream* stream = AddSendStream();
2592 webrtc::VideoSendStream::Config config = stream->GetConfig().Copy();
2593
brandtr3d200bd2017-01-16 06:59:19 -08002594 EXPECT_EQ(-1, config.rtp.flexfec.payload_type);
brandtr31bd2242017-05-19 05:47:46 -07002595 EXPECT_EQ(0U, config.rtp.flexfec.ssrc);
2596 EXPECT_TRUE(config.rtp.flexfec.protected_media_ssrcs.empty());
brandtr468da7c2016-11-22 02:16:47 -08002597}
2598
eladalonf1841382017-06-12 01:16:46 -07002599TEST_F(WebRtcVideoChannelTest, FlexfecSendCodecWithSsrcNotExposedByDefault) {
brandtr468da7c2016-11-22 02:16:47 -08002600 FakeVideoSendStream* stream = AddSendStream(
2601 CreatePrimaryWithFecFrStreamParams("cname", kSsrcs1[0], kFlexfecSsrc));
2602 webrtc::VideoSendStream::Config config = stream->GetConfig().Copy();
2603
brandtr3d200bd2017-01-16 06:59:19 -08002604 EXPECT_EQ(-1, config.rtp.flexfec.payload_type);
brandtr31bd2242017-05-19 05:47:46 -07002605 EXPECT_EQ(0U, config.rtp.flexfec.ssrc);
2606 EXPECT_TRUE(config.rtp.flexfec.protected_media_ssrcs.empty());
2607}
2608
eladalonf1841382017-06-12 01:16:46 -07002609TEST_F(WebRtcVideoChannelTest,
brandtr31bd2242017-05-19 05:47:46 -07002610 FlexfecRecvCodecWithoutSsrcNotExposedByDefault) {
2611 AddRecvStream();
2612
2613 const std::vector<FakeFlexfecReceiveStream*>& streams =
2614 fake_call_->GetFlexfecReceiveStreams();
2615 EXPECT_TRUE(streams.empty());
2616}
2617
eladalonf1841382017-06-12 01:16:46 -07002618TEST_F(WebRtcVideoChannelTest, FlexfecRecvCodecWithSsrcNotExposedByDefault) {
brandtr31bd2242017-05-19 05:47:46 -07002619 AddRecvStream(
2620 CreatePrimaryWithFecFrStreamParams("cname", kSsrcs1[0], kFlexfecSsrc));
2621
2622 const std::vector<FakeFlexfecReceiveStream*>& streams =
2623 fake_call_->GetFlexfecReceiveStreams();
2624 EXPECT_TRUE(streams.empty());
brandtr468da7c2016-11-22 02:16:47 -08002625}
2626
2627// TODO(brandtr): When FlexFEC is no longer behind a field trial, merge all
2628// tests that use this test fixture into the corresponding "non-field trial"
2629// tests.
eladalonf1841382017-06-12 01:16:46 -07002630class WebRtcVideoChannelFlexfecRecvTest : public WebRtcVideoChannelTest {
brandtr468da7c2016-11-22 02:16:47 -08002631 public:
eladalonf1841382017-06-12 01:16:46 -07002632 WebRtcVideoChannelFlexfecRecvTest()
2633 : WebRtcVideoChannelTest("WebRTC-FlexFEC-03-Advertised/Enabled/") {}
brandtr468da7c2016-11-22 02:16:47 -08002634};
2635
eladalonf1841382017-06-12 01:16:46 -07002636TEST_F(WebRtcVideoChannelFlexfecRecvTest,
brandtr36e7d702017-01-13 07:15:54 -08002637 DefaultFlexfecCodecHasTransportCcAndRembFeedbackParam) {
2638 EXPECT_TRUE(cricket::HasTransportCc(GetEngineCodec("flexfec-03")));
2639 EXPECT_TRUE(cricket::HasRemb(GetEngineCodec("flexfec-03")));
2640}
2641
eladalonf1841382017-06-12 01:16:46 -07002642TEST_F(WebRtcVideoChannelFlexfecRecvTest, SetDefaultRecvCodecsWithoutSsrc) {
brandtr31bd2242017-05-19 05:47:46 -07002643 AddRecvStream();
2644
2645 const std::vector<FakeFlexfecReceiveStream*>& streams =
2646 fake_call_->GetFlexfecReceiveStreams();
2647 EXPECT_TRUE(streams.empty());
2648}
2649
eladalonf1841382017-06-12 01:16:46 -07002650TEST_F(WebRtcVideoChannelFlexfecRecvTest, SetDefaultRecvCodecsWithSsrc) {
brandtr31bd2242017-05-19 05:47:46 -07002651 AddRecvStream(
2652 CreatePrimaryWithFecFrStreamParams("cname", kSsrcs1[0], kFlexfecSsrc));
2653
2654 const std::vector<FakeFlexfecReceiveStream*>& streams =
2655 fake_call_->GetFlexfecReceiveStreams();
2656 ASSERT_EQ(1U, streams.size());
2657 const FakeFlexfecReceiveStream* stream = streams.front();
2658 const webrtc::FlexfecReceiveStream::Config& config = stream->GetConfig();
2659 EXPECT_EQ(GetEngineCodec("flexfec-03").id, config.payload_type);
2660 EXPECT_EQ(kFlexfecSsrc, config.remote_ssrc);
2661 ASSERT_EQ(1U, config.protected_media_ssrcs.size());
2662 EXPECT_EQ(kSsrcs1[0], config.protected_media_ssrcs[0]);
brandtr7cd28b92017-09-22 00:26:25 -07002663
2664 const std::vector<FakeVideoReceiveStream*>& video_streams =
2665 fake_call_->GetVideoReceiveStreams();
2666 ASSERT_EQ(1U, video_streams.size());
2667 const webrtc::VideoReceiveStream::Config& video_config =
2668 video_streams.front()->GetConfig();
2669 EXPECT_TRUE(video_config.rtp.protected_by_flexfec);
brandtr31bd2242017-05-19 05:47:46 -07002670}
2671
eladalonf1841382017-06-12 01:16:46 -07002672TEST_F(WebRtcVideoChannelFlexfecRecvTest,
brandtr11fb4722017-05-30 01:31:37 -07002673 EnablingFlexfecDoesNotRecreateVideoReceiveStream) {
2674 cricket::VideoRecvParameters recv_parameters;
2675 recv_parameters.codecs.push_back(GetEngineCodec("VP8"));
2676 ASSERT_TRUE(channel_->SetRecvParameters(recv_parameters));
2677
2678 AddRecvStream(
2679 CreatePrimaryWithFecFrStreamParams("cname", kSsrcs1[0], kFlexfecSsrc));
2680 EXPECT_EQ(1, fake_call_->GetNumCreatedReceiveStreams());
2681 EXPECT_EQ(1U, fake_call_->GetVideoReceiveStreams().size());
2682
2683 // Enable FlexFEC.
2684 recv_parameters.codecs.push_back(GetEngineCodec("flexfec-03"));
2685 ASSERT_TRUE(channel_->SetRecvParameters(recv_parameters));
2686 EXPECT_EQ(2, fake_call_->GetNumCreatedReceiveStreams())
2687 << "Enabling FlexFEC should create FlexfecReceiveStream.";
2688 EXPECT_EQ(1U, fake_call_->GetVideoReceiveStreams().size())
2689 << "Enabling FlexFEC should not create VideoReceiveStream.";
2690 EXPECT_EQ(1U, fake_call_->GetFlexfecReceiveStreams().size())
2691 << "Enabling FlexFEC should create a single FlexfecReceiveStream.";
2692}
2693
eladalonf1841382017-06-12 01:16:46 -07002694TEST_F(WebRtcVideoChannelFlexfecRecvTest,
brandtr11fb4722017-05-30 01:31:37 -07002695 DisablingFlexfecDoesNotRecreateVideoReceiveStream) {
2696 cricket::VideoRecvParameters recv_parameters;
2697 recv_parameters.codecs.push_back(GetEngineCodec("VP8"));
2698 recv_parameters.codecs.push_back(GetEngineCodec("flexfec-03"));
2699 ASSERT_TRUE(channel_->SetRecvParameters(recv_parameters));
2700
2701 AddRecvStream(
2702 CreatePrimaryWithFecFrStreamParams("cname", kSsrcs1[0], kFlexfecSsrc));
2703 EXPECT_EQ(2, fake_call_->GetNumCreatedReceiveStreams());
2704 EXPECT_EQ(1U, fake_call_->GetVideoReceiveStreams().size());
2705 EXPECT_EQ(1U, fake_call_->GetFlexfecReceiveStreams().size());
2706
2707 // Disable FlexFEC.
2708 recv_parameters.codecs.clear();
2709 recv_parameters.codecs.push_back(GetEngineCodec("VP8"));
2710 ASSERT_TRUE(channel_->SetRecvParameters(recv_parameters));
2711 EXPECT_EQ(2, fake_call_->GetNumCreatedReceiveStreams())
2712 << "Disabling FlexFEC should not recreate VideoReceiveStream.";
2713 EXPECT_EQ(1U, fake_call_->GetVideoReceiveStreams().size())
2714 << "Disabling FlexFEC should not destroy VideoReceiveStream.";
2715 EXPECT_TRUE(fake_call_->GetFlexfecReceiveStreams().empty())
2716 << "Disabling FlexFEC should destroy FlexfecReceiveStream.";
2717}
2718
brandtr31bd2242017-05-19 05:47:46 -07002719// TODO(brandtr): When FlexFEC is no longer behind a field trial, merge all
2720// tests that use this test fixture into the corresponding "non-field trial"
2721// tests.
eladalonf1841382017-06-12 01:16:46 -07002722class WebRtcVideoChannelFlexfecSendRecvTest : public WebRtcVideoChannelTest {
brandtr31bd2242017-05-19 05:47:46 -07002723 public:
eladalonf1841382017-06-12 01:16:46 -07002724 WebRtcVideoChannelFlexfecSendRecvTest()
2725 : WebRtcVideoChannelTest(
brandtr31bd2242017-05-19 05:47:46 -07002726 "WebRTC-FlexFEC-03-Advertised/Enabled/WebRTC-FlexFEC-03/Enabled/") {
2727 }
2728};
2729
eladalonf1841382017-06-12 01:16:46 -07002730TEST_F(WebRtcVideoChannelFlexfecSendRecvTest,
brandtr31bd2242017-05-19 05:47:46 -07002731 SetDefaultSendCodecsWithoutSsrc) {
brandtr468da7c2016-11-22 02:16:47 -08002732 FakeVideoSendStream* stream = AddSendStream();
2733 webrtc::VideoSendStream::Config config = stream->GetConfig().Copy();
2734
brandtr3d200bd2017-01-16 06:59:19 -08002735 EXPECT_EQ(GetEngineCodec("flexfec-03").id, config.rtp.flexfec.payload_type);
2736 EXPECT_EQ(0U, config.rtp.flexfec.ssrc);
2737 EXPECT_TRUE(config.rtp.flexfec.protected_media_ssrcs.empty());
brandtr468da7c2016-11-22 02:16:47 -08002738}
2739
eladalonf1841382017-06-12 01:16:46 -07002740TEST_F(WebRtcVideoChannelFlexfecSendRecvTest, SetDefaultSendCodecsWithSsrc) {
brandtr468da7c2016-11-22 02:16:47 -08002741 FakeVideoSendStream* stream = AddSendStream(
2742 CreatePrimaryWithFecFrStreamParams("cname", kSsrcs1[0], kFlexfecSsrc));
2743 webrtc::VideoSendStream::Config config = stream->GetConfig().Copy();
2744
brandtr3d200bd2017-01-16 06:59:19 -08002745 EXPECT_EQ(GetEngineCodec("flexfec-03").id, config.rtp.flexfec.payload_type);
2746 EXPECT_EQ(kFlexfecSsrc, config.rtp.flexfec.ssrc);
2747 ASSERT_EQ(1U, config.rtp.flexfec.protected_media_ssrcs.size());
2748 EXPECT_EQ(kSsrcs1[0], config.rtp.flexfec.protected_media_ssrcs[0]);
brandtr468da7c2016-11-22 02:16:47 -08002749}
2750
eladalonf1841382017-06-12 01:16:46 -07002751TEST_F(WebRtcVideoChannelTest, SetSendCodecsWithoutFec) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02002752 cricket::VideoSendParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08002753 parameters.codecs.push_back(GetEngineCodec("VP8"));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02002754 ASSERT_TRUE(channel_->SetSendParameters(parameters));
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00002755
2756 FakeVideoSendStream* stream = AddSendStream();
perkj26091b12016-09-01 01:17:40 -07002757 webrtc::VideoSendStream::Config config = stream->GetConfig().Copy();
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00002758
brandtrb5f2c3f2016-10-04 23:28:39 -07002759 EXPECT_EQ(-1, config.rtp.ulpfec.ulpfec_payload_type);
2760 EXPECT_EQ(-1, config.rtp.ulpfec.red_payload_type);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00002761}
2762
eladalonf1841382017-06-12 01:16:46 -07002763TEST_F(WebRtcVideoChannelFlexfecSendRecvTest, SetSendCodecsWithoutFec) {
brandtr468da7c2016-11-22 02:16:47 -08002764 cricket::VideoSendParameters parameters;
2765 parameters.codecs.push_back(GetEngineCodec("VP8"));
2766 ASSERT_TRUE(channel_->SetSendParameters(parameters));
2767
2768 FakeVideoSendStream* stream = AddSendStream();
2769 webrtc::VideoSendStream::Config config = stream->GetConfig().Copy();
2770
brandtr3d200bd2017-01-16 06:59:19 -08002771 EXPECT_EQ(-1, config.rtp.flexfec.payload_type);
brandtr468da7c2016-11-22 02:16:47 -08002772}
2773
eladalonf1841382017-06-12 01:16:46 -07002774TEST_F(WebRtcVideoChannelFlexfecRecvTest, SetRecvCodecsWithFec) {
brandtr9c3d4c42017-01-23 06:59:13 -08002775 AddRecvStream(
2776 CreatePrimaryWithFecFrStreamParams("cname", kSsrcs1[0], kFlexfecSsrc));
brandtr9c3d4c42017-01-23 06:59:13 -08002777
2778 cricket::VideoRecvParameters recv_parameters;
2779 recv_parameters.codecs.push_back(GetEngineCodec("VP8"));
2780 recv_parameters.codecs.push_back(GetEngineCodec("flexfec-03"));
2781 ASSERT_TRUE(channel_->SetRecvParameters(recv_parameters));
brandtr9d58d942017-02-03 04:43:41 -08002782
2783 const std::vector<FakeFlexfecReceiveStream*>& flexfec_streams =
2784 fake_call_->GetFlexfecReceiveStreams();
2785 ASSERT_EQ(1U, flexfec_streams.size());
2786 const FakeFlexfecReceiveStream* flexfec_stream = flexfec_streams.front();
2787 const webrtc::FlexfecReceiveStream::Config& flexfec_stream_config =
2788 flexfec_stream->GetConfig();
brandtr9c3d4c42017-01-23 06:59:13 -08002789 EXPECT_EQ(GetEngineCodec("flexfec-03").id,
brandtr9d58d942017-02-03 04:43:41 -08002790 flexfec_stream_config.payload_type);
2791 EXPECT_EQ(kFlexfecSsrc, flexfec_stream_config.remote_ssrc);
2792 ASSERT_EQ(1U, flexfec_stream_config.protected_media_ssrcs.size());
2793 EXPECT_EQ(kSsrcs1[0], flexfec_stream_config.protected_media_ssrcs[0]);
2794 const std::vector<FakeVideoReceiveStream*>& video_streams =
2795 fake_call_->GetVideoReceiveStreams();
2796 const FakeVideoReceiveStream* video_stream = video_streams.front();
2797 const webrtc::VideoReceiveStream::Config& video_stream_config =
2798 video_stream->GetConfig();
2799 EXPECT_EQ(video_stream_config.rtp.local_ssrc,
2800 flexfec_stream_config.local_ssrc);
2801 EXPECT_EQ(video_stream_config.rtp.rtcp_mode, flexfec_stream_config.rtcp_mode);
2802 EXPECT_EQ(video_stream_config.rtcp_send_transport,
2803 flexfec_stream_config.rtcp_send_transport);
2804 // TODO(brandtr): Update this EXPECT when we set |transport_cc| in a
2805 // spec-compliant way.
2806 EXPECT_EQ(video_stream_config.rtp.transport_cc,
2807 flexfec_stream_config.transport_cc);
2808 EXPECT_EQ(video_stream_config.rtp.rtcp_mode, flexfec_stream_config.rtcp_mode);
2809 EXPECT_EQ(video_stream_config.rtp.extensions,
2810 flexfec_stream_config.rtp_header_extensions);
brandtr9c3d4c42017-01-23 06:59:13 -08002811}
2812
brandtr31bd2242017-05-19 05:47:46 -07002813// We should not send FlexFEC, even if we advertise it, unless the right
2814// field trial is set.
2815// TODO(brandtr): Remove when FlexFEC is enabled by default.
eladalonf1841382017-06-12 01:16:46 -07002816TEST_F(WebRtcVideoChannelFlexfecRecvTest,
brandtr31bd2242017-05-19 05:47:46 -07002817 SetSendCodecsWithoutSsrcWithFecDoesNotEnableFec) {
2818 cricket::VideoSendParameters parameters;
2819 parameters.codecs.push_back(GetEngineCodec("VP8"));
2820 parameters.codecs.push_back(GetEngineCodec("flexfec-03"));
2821 ASSERT_TRUE(channel_->SetSendParameters(parameters));
2822
2823 FakeVideoSendStream* stream = AddSendStream();
2824 webrtc::VideoSendStream::Config config = stream->GetConfig().Copy();
2825
2826 EXPECT_EQ(-1, config.rtp.flexfec.payload_type);
2827 EXPECT_EQ(0, config.rtp.flexfec.ssrc);
2828 EXPECT_TRUE(config.rtp.flexfec.protected_media_ssrcs.empty());
2829}
2830
eladalonf1841382017-06-12 01:16:46 -07002831TEST_F(WebRtcVideoChannelFlexfecRecvTest,
brandtr31bd2242017-05-19 05:47:46 -07002832 SetSendCodecsWithSsrcWithFecDoesNotEnableFec) {
2833 cricket::VideoSendParameters parameters;
2834 parameters.codecs.push_back(GetEngineCodec("VP8"));
2835 parameters.codecs.push_back(GetEngineCodec("flexfec-03"));
2836 ASSERT_TRUE(channel_->SetSendParameters(parameters));
2837
2838 FakeVideoSendStream* stream = AddSendStream(
2839 CreatePrimaryWithFecFrStreamParams("cname", kSsrcs1[0], kFlexfecSsrc));
2840 webrtc::VideoSendStream::Config config = stream->GetConfig().Copy();
2841
2842 EXPECT_EQ(-1, config.rtp.flexfec.payload_type);
2843 EXPECT_EQ(0, config.rtp.flexfec.ssrc);
2844 EXPECT_TRUE(config.rtp.flexfec.protected_media_ssrcs.empty());
2845}
2846
eladalonf1841382017-06-12 01:16:46 -07002847TEST_F(WebRtcVideoChannelTest,
pbos@webrtc.org269605c2014-06-26 08:49:03 +00002848 SetSendCodecRejectsRtxWithoutAssociatedPayloadType) {
magjed509e4fe2016-11-18 01:34:11 -08002849 const int kUnusedPayloadType = 127;
2850 EXPECT_FALSE(FindCodecById(engine_.codecs(), kUnusedPayloadType));
2851
Fredrik Solenbergb071a192015-09-17 16:42:56 +02002852 cricket::VideoSendParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08002853 cricket::VideoCodec rtx_codec(kUnusedPayloadType, "rtx");
Fredrik Solenbergb071a192015-09-17 16:42:56 +02002854 parameters.codecs.push_back(rtx_codec);
2855 EXPECT_FALSE(channel_->SetSendParameters(parameters))
pbos@webrtc.org269605c2014-06-26 08:49:03 +00002856 << "RTX codec without associated payload type should be rejected.";
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00002857}
2858
eladalonf1841382017-06-12 01:16:46 -07002859TEST_F(WebRtcVideoChannelTest,
pbos@webrtc.org269605c2014-06-26 08:49:03 +00002860 SetSendCodecRejectsRtxWithoutMatchingVideoCodec) {
magjed509e4fe2016-11-18 01:34:11 -08002861 const int kUnusedPayloadType1 = 126;
2862 const int kUnusedPayloadType2 = 127;
2863 EXPECT_FALSE(FindCodecById(engine_.codecs(), kUnusedPayloadType1));
2864 EXPECT_FALSE(FindCodecById(engine_.codecs(), kUnusedPayloadType2));
2865 {
2866 cricket::VideoCodec rtx_codec = cricket::VideoCodec::CreateRtxCodec(
2867 kUnusedPayloadType1, GetEngineCodec("VP8").id);
2868 cricket::VideoSendParameters parameters;
2869 parameters.codecs.push_back(GetEngineCodec("VP8"));
2870 parameters.codecs.push_back(rtx_codec);
2871 ASSERT_TRUE(channel_->SetSendParameters(parameters));
2872 }
2873 {
2874 cricket::VideoCodec rtx_codec = cricket::VideoCodec::CreateRtxCodec(
2875 kUnusedPayloadType1, kUnusedPayloadType2);
2876 cricket::VideoSendParameters parameters;
2877 parameters.codecs.push_back(GetEngineCodec("VP8"));
2878 parameters.codecs.push_back(rtx_codec);
2879 EXPECT_FALSE(channel_->SetSendParameters(parameters))
2880 << "RTX without matching video codec should be rejected.";
2881 }
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00002882}
2883
eladalonf1841382017-06-12 01:16:46 -07002884TEST_F(WebRtcVideoChannelTest, SetSendCodecsWithChangedRtxPayloadType) {
brandtr14742122017-01-27 04:53:07 -08002885 const int kUnusedPayloadType1 = 126;
2886 const int kUnusedPayloadType2 = 127;
2887 EXPECT_FALSE(FindCodecById(engine_.codecs(), kUnusedPayloadType1));
2888 EXPECT_FALSE(FindCodecById(engine_.codecs(), kUnusedPayloadType2));
2889
2890 // SSRCs for RTX.
2891 cricket::StreamParams params =
2892 cricket::StreamParams::CreateLegacy(kSsrcs1[0]);
2893 params.AddFidSsrc(kSsrcs1[0], kRtxSsrcs1[0]);
2894 AddSendStream(params);
2895
2896 // Original payload type for RTX.
2897 cricket::VideoSendParameters parameters;
2898 parameters.codecs.push_back(GetEngineCodec("VP8"));
2899 cricket::VideoCodec rtx_codec(kUnusedPayloadType1, "rtx");
2900 rtx_codec.SetParam("apt", GetEngineCodec("VP8").id);
2901 parameters.codecs.push_back(rtx_codec);
2902 EXPECT_TRUE(channel_->SetSendParameters(parameters));
2903 ASSERT_EQ(1U, fake_call_->GetVideoSendStreams().size());
2904 const webrtc::VideoSendStream::Config& config_before =
2905 fake_call_->GetVideoSendStreams()[0]->GetConfig();
2906 EXPECT_EQ(kUnusedPayloadType1, config_before.rtp.rtx.payload_type);
2907 ASSERT_EQ(1U, config_before.rtp.rtx.ssrcs.size());
2908 EXPECT_EQ(kRtxSsrcs1[0], config_before.rtp.rtx.ssrcs[0]);
2909
2910 // Change payload type for RTX.
2911 parameters.codecs[1].id = kUnusedPayloadType2;
2912 EXPECT_TRUE(channel_->SetSendParameters(parameters));
2913 ASSERT_EQ(1U, fake_call_->GetVideoSendStreams().size());
2914 const webrtc::VideoSendStream::Config& config_after =
2915 fake_call_->GetVideoSendStreams()[0]->GetConfig();
2916 EXPECT_EQ(kUnusedPayloadType2, config_after.rtp.rtx.payload_type);
2917 ASSERT_EQ(1U, config_after.rtp.rtx.ssrcs.size());
2918 EXPECT_EQ(kRtxSsrcs1[0], config_after.rtp.rtx.ssrcs[0]);
2919}
2920
eladalonf1841382017-06-12 01:16:46 -07002921TEST_F(WebRtcVideoChannelTest, SetSendCodecsWithoutFecDisablesFec) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02002922 cricket::VideoSendParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08002923 parameters.codecs.push_back(GetEngineCodec("VP8"));
2924 parameters.codecs.push_back(GetEngineCodec("ulpfec"));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02002925 ASSERT_TRUE(channel_->SetSendParameters(parameters));
pbos@webrtc.org269605c2014-06-26 08:49:03 +00002926
2927 FakeVideoSendStream* stream = AddSendStream();
perkj26091b12016-09-01 01:17:40 -07002928 webrtc::VideoSendStream::Config config = stream->GetConfig().Copy();
pbos@webrtc.org269605c2014-06-26 08:49:03 +00002929
magjed509e4fe2016-11-18 01:34:11 -08002930 EXPECT_EQ(GetEngineCodec("ulpfec").id, config.rtp.ulpfec.ulpfec_payload_type);
pbos@webrtc.org269605c2014-06-26 08:49:03 +00002931
Fredrik Solenbergb071a192015-09-17 16:42:56 +02002932 parameters.codecs.pop_back();
2933 ASSERT_TRUE(channel_->SetSendParameters(parameters));
pbos@webrtc.org42684be2014-10-03 11:25:45 +00002934 stream = fake_call_->GetVideoSendStreams()[0];
brandtr468da7c2016-11-22 02:16:47 -08002935 ASSERT_TRUE(stream != nullptr);
perkj26091b12016-09-01 01:17:40 -07002936 config = stream->GetConfig().Copy();
brandtrb5f2c3f2016-10-04 23:28:39 -07002937 EXPECT_EQ(-1, config.rtp.ulpfec.ulpfec_payload_type)
brandtr468da7c2016-11-22 02:16:47 -08002938 << "SetSendCodec without ULPFEC should disable current ULPFEC.";
2939}
2940
eladalonf1841382017-06-12 01:16:46 -07002941TEST_F(WebRtcVideoChannelFlexfecSendRecvTest,
brandtr31bd2242017-05-19 05:47:46 -07002942 SetSendCodecsWithoutFecDisablesFec) {
brandtr468da7c2016-11-22 02:16:47 -08002943 cricket::VideoSendParameters parameters;
2944 parameters.codecs.push_back(GetEngineCodec("VP8"));
2945 parameters.codecs.push_back(GetEngineCodec("flexfec-03"));
2946 ASSERT_TRUE(channel_->SetSendParameters(parameters));
2947
2948 FakeVideoSendStream* stream = AddSendStream(
2949 CreatePrimaryWithFecFrStreamParams("cname", kSsrcs1[0], kFlexfecSsrc));
2950 webrtc::VideoSendStream::Config config = stream->GetConfig().Copy();
2951
brandtr3d200bd2017-01-16 06:59:19 -08002952 EXPECT_EQ(GetEngineCodec("flexfec-03").id, config.rtp.flexfec.payload_type);
2953 EXPECT_EQ(kFlexfecSsrc, config.rtp.flexfec.ssrc);
brandtr468da7c2016-11-22 02:16:47 -08002954 ASSERT_EQ(1U, config.rtp.flexfec.protected_media_ssrcs.size());
2955 EXPECT_EQ(kSsrcs1[0], config.rtp.flexfec.protected_media_ssrcs[0]);
2956
2957 parameters.codecs.pop_back();
2958 ASSERT_TRUE(channel_->SetSendParameters(parameters));
2959 stream = fake_call_->GetVideoSendStreams()[0];
2960 ASSERT_TRUE(stream != nullptr);
2961 config = stream->GetConfig().Copy();
brandtr3d200bd2017-01-16 06:59:19 -08002962 EXPECT_EQ(-1, config.rtp.flexfec.payload_type)
brandtr468da7c2016-11-22 02:16:47 -08002963 << "SetSendCodec without FlexFEC should disable current FlexFEC.";
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00002964}
2965
eladalonf1841382017-06-12 01:16:46 -07002966TEST_F(WebRtcVideoChannelTest, SetSendCodecsChangesExistingStreams) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02002967 cricket::VideoSendParameters parameters;
perkj26752742016-10-24 01:21:16 -07002968 cricket::VideoCodec codec(100, "VP8");
2969 codec.SetParam(kCodecParamMaxQuantization, kDefaultQpMax);
2970 parameters.codecs.push_back(codec);
perkjfa10b552016-10-02 23:45:26 -07002971
Fredrik Solenbergb071a192015-09-17 16:42:56 +02002972 ASSERT_TRUE(channel_->SetSendParameters(parameters));
pbos@webrtc.org86196c42015-02-16 21:02:00 +00002973 channel_->SetSend(true);
pbos@webrtc.org38ce7d02014-07-16 08:01:38 +00002974
pbos@webrtc.org86196c42015-02-16 21:02:00 +00002975 FakeVideoSendStream* stream = AddSendStream();
pbos@webrtc.org86196c42015-02-16 21:02:00 +00002976 cricket::FakeVideoCapturer capturer;
deadbeef5a4a75a2016-06-02 16:23:38 -07002977 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, &capturer));
pbos@webrtc.org86196c42015-02-16 21:02:00 +00002978
2979 std::vector<webrtc::VideoStream> streams = stream->GetVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07002980 EXPECT_EQ(kDefaultQpMax, streams[0].max_qp);
pbos@webrtc.org38ce7d02014-07-16 08:01:38 +00002981
Fredrik Solenbergb071a192015-09-17 16:42:56 +02002982 parameters.codecs.clear();
perkj26752742016-10-24 01:21:16 -07002983 codec.SetParam(kCodecParamMaxQuantization, kDefaultQpMax + 1);
2984 parameters.codecs.push_back(codec);
Fredrik Solenbergb071a192015-09-17 16:42:56 +02002985 ASSERT_TRUE(channel_->SetSendParameters(parameters));
pbos@webrtc.org42684be2014-10-03 11:25:45 +00002986 streams = fake_call_->GetVideoSendStreams()[0]->GetVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07002987 EXPECT_EQ(kDefaultQpMax + 1, streams[0].max_qp);
deadbeef5a4a75a2016-06-02 16:23:38 -07002988 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, nullptr));
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00002989}
2990
eladalonf1841382017-06-12 01:16:46 -07002991TEST_F(WebRtcVideoChannelTest, SetSendCodecsWithBitrates) {
pbos@webrtc.org00873182014-11-25 14:03:34 +00002992 SetSendCodecsShouldWorkForBitrates("100", 100000, "150", 150000, "200",
2993 200000);
2994}
2995
eladalonf1841382017-06-12 01:16:46 -07002996TEST_F(WebRtcVideoChannelTest, SetSendCodecsWithHighMaxBitrate) {
pbos@webrtc.orga5f6fb52015-03-23 22:29:39 +00002997 SetSendCodecsShouldWorkForBitrates("", 0, "", -1, "10000", 10000000);
2998 std::vector<webrtc::VideoStream> streams = AddSendStream()->GetVideoStreams();
2999 ASSERT_EQ(1u, streams.size());
3000 EXPECT_EQ(10000000, streams[0].max_bitrate_bps);
3001}
3002
eladalonf1841382017-06-12 01:16:46 -07003003TEST_F(WebRtcVideoChannelTest,
pbos@webrtc.org00873182014-11-25 14:03:34 +00003004 SetSendCodecsWithoutBitratesUsesCorrectDefaults) {
3005 SetSendCodecsShouldWorkForBitrates(
3006 "", 0, "", -1, "", -1);
3007}
3008
eladalonf1841382017-06-12 01:16:46 -07003009TEST_F(WebRtcVideoChannelTest, SetSendCodecsCapsMinAndStartBitrate) {
pbos@webrtc.org00873182014-11-25 14:03:34 +00003010 SetSendCodecsShouldWorkForBitrates("-1", 0, "-100", -1, "", -1);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00003011}
3012
eladalonf1841382017-06-12 01:16:46 -07003013TEST_F(WebRtcVideoChannelTest, SetSendCodecsRejectsMaxLessThanMinBitrate) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003014 send_parameters_.codecs[0].params[kCodecParamMinBitrate] = "300";
3015 send_parameters_.codecs[0].params[kCodecParamMaxBitrate] = "200";
3016 EXPECT_FALSE(channel_->SetSendParameters(send_parameters_));
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00003017}
3018
Taylor Brandstetter58f2bd92016-04-26 17:15:23 -07003019// Test that when both the codec-specific bitrate params and max_bandwidth_bps
3020// are present in the same send parameters, the settings are combined correctly.
eladalonf1841382017-06-12 01:16:46 -07003021TEST_F(WebRtcVideoChannelTest, SetSendCodecsWithBitratesAndMaxSendBandwidth) {
Taylor Brandstetter58f2bd92016-04-26 17:15:23 -07003022 send_parameters_.codecs[0].params[kCodecParamMinBitrate] = "100";
3023 send_parameters_.codecs[0].params[kCodecParamStartBitrate] = "200";
3024 send_parameters_.codecs[0].params[kCodecParamMaxBitrate] = "300";
3025 send_parameters_.max_bandwidth_bps = 400000;
3026 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
3027 EXPECT_EQ(100000, fake_call_->GetConfig().bitrate_config.min_bitrate_bps);
3028 EXPECT_EQ(200000, fake_call_->GetConfig().bitrate_config.start_bitrate_bps);
3029 // We expect max_bandwidth_bps to take priority, if set.
3030 EXPECT_EQ(400000, fake_call_->GetConfig().bitrate_config.max_bitrate_bps);
3031
3032 // Decrease max_bandwidth_bps.
3033 send_parameters_.max_bandwidth_bps = 350000;
3034 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
3035 EXPECT_EQ(100000, fake_call_->GetConfig().bitrate_config.min_bitrate_bps);
3036 // Since the codec isn't changing, start_bitrate_bps should be -1.
3037 EXPECT_EQ(-1, fake_call_->GetConfig().bitrate_config.start_bitrate_bps);
3038 EXPECT_EQ(350000, fake_call_->GetConfig().bitrate_config.max_bitrate_bps);
3039
3040 // Now try again with the values flipped around.
3041 send_parameters_.codecs[0].params[kCodecParamMaxBitrate] = "400";
3042 send_parameters_.max_bandwidth_bps = 300000;
3043 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
3044 EXPECT_EQ(100000, fake_call_->GetConfig().bitrate_config.min_bitrate_bps);
3045 EXPECT_EQ(200000, fake_call_->GetConfig().bitrate_config.start_bitrate_bps);
3046 EXPECT_EQ(300000, fake_call_->GetConfig().bitrate_config.max_bitrate_bps);
3047
3048 // If we change the codec max, max_bandwidth_bps should still apply.
3049 send_parameters_.codecs[0].params[kCodecParamMaxBitrate] = "350";
3050 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
3051 EXPECT_EQ(100000, fake_call_->GetConfig().bitrate_config.min_bitrate_bps);
3052 EXPECT_EQ(200000, fake_call_->GetConfig().bitrate_config.start_bitrate_bps);
3053 EXPECT_EQ(300000, fake_call_->GetConfig().bitrate_config.max_bitrate_bps);
3054}
3055
eladalonf1841382017-06-12 01:16:46 -07003056TEST_F(WebRtcVideoChannelTest,
pbos@webrtc.org00873182014-11-25 14:03:34 +00003057 SetMaxSendBandwidthShouldPreserveOtherBitrates) {
3058 SetSendCodecsShouldWorkForBitrates("100", 100000, "150", 150000, "200",
3059 200000);
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003060 send_parameters_.max_bandwidth_bps = 300000;
3061 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
Stefan Holmere5904162015-03-26 11:11:06 +01003062 EXPECT_EQ(100000, fake_call_->GetConfig().bitrate_config.min_bitrate_bps)
pbos@webrtc.org00873182014-11-25 14:03:34 +00003063 << "Setting max bitrate should keep previous min bitrate.";
Stefan Holmere5904162015-03-26 11:11:06 +01003064 EXPECT_EQ(-1, fake_call_->GetConfig().bitrate_config.start_bitrate_bps)
pbos@webrtc.org00873182014-11-25 14:03:34 +00003065 << "Setting max bitrate should not reset start bitrate.";
Stefan Holmere5904162015-03-26 11:11:06 +01003066 EXPECT_EQ(300000, fake_call_->GetConfig().bitrate_config.max_bitrate_bps);
pbos@webrtc.org00873182014-11-25 14:03:34 +00003067}
3068
eladalonf1841382017-06-12 01:16:46 -07003069TEST_F(WebRtcVideoChannelTest, SetMaxSendBandwidthShouldBeRemovable) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003070 send_parameters_.max_bandwidth_bps = 300000;
3071 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
Stefan Holmere5904162015-03-26 11:11:06 +01003072 EXPECT_EQ(300000, fake_call_->GetConfig().bitrate_config.max_bitrate_bps);
pbos5c7760a2017-03-10 11:23:12 -08003073 // -1 means to disable max bitrate (set infinite).
3074 send_parameters_.max_bandwidth_bps = -1;
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003075 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
Stefan Holmere5904162015-03-26 11:11:06 +01003076 EXPECT_EQ(-1, fake_call_->GetConfig().bitrate_config.max_bitrate_bps)
pbos@webrtc.org00873182014-11-25 14:03:34 +00003077 << "Setting zero max bitrate did not reset start bitrate.";
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00003078}
3079
eladalonf1841382017-06-12 01:16:46 -07003080TEST_F(WebRtcVideoChannelTest, SetMaxSendBandwidthAndAddSendStream) {
perkjfa10b552016-10-02 23:45:26 -07003081 send_parameters_.max_bandwidth_bps = 99999;
3082 FakeVideoSendStream* stream = AddSendStream();
3083 ASSERT_TRUE(channel_->SetSendParameters(send_parameters_));
3084 EXPECT_EQ(send_parameters_.max_bandwidth_bps,
3085 fake_call_->GetConfig().bitrate_config.max_bitrate_bps);
3086 ASSERT_EQ(1u, stream->GetVideoStreams().size());
3087 EXPECT_EQ(send_parameters_.max_bandwidth_bps,
3088 stream->GetVideoStreams()[0].max_bitrate_bps);
3089
3090 send_parameters_.max_bandwidth_bps = 77777;
3091 ASSERT_TRUE(channel_->SetSendParameters(send_parameters_));
3092 EXPECT_EQ(send_parameters_.max_bandwidth_bps,
3093 fake_call_->GetConfig().bitrate_config.max_bitrate_bps);
3094 EXPECT_EQ(send_parameters_.max_bandwidth_bps,
3095 stream->GetVideoStreams()[0].max_bitrate_bps);
3096}
3097
eladalonf1841382017-06-12 01:16:46 -07003098TEST_F(WebRtcVideoChannelTest, SetMaxSendBitrateCanIncreaseSenderBitrate) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003099 cricket::VideoSendParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08003100 parameters.codecs.push_back(GetEngineCodec("VP8"));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003101 ASSERT_TRUE(channel_->SetSendParameters(parameters));
Peter Boströmdfd53fe2015-03-27 15:58:11 +01003102 channel_->SetSend(true);
3103
3104 FakeVideoSendStream* stream = AddSendStream();
3105
Peter Boström3afc8c42016-01-27 16:45:21 +01003106 cricket::FakeVideoCapturer capturer;
deadbeef5a4a75a2016-06-02 16:23:38 -07003107 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, &capturer));
Peter Boström3afc8c42016-01-27 16:45:21 +01003108 EXPECT_EQ(cricket::CS_RUNNING,
3109 capturer.Start(capturer.GetSupportedFormats()->front()));
3110
Peter Boströmdfd53fe2015-03-27 15:58:11 +01003111 std::vector<webrtc::VideoStream> streams = stream->GetVideoStreams();
3112 int initial_max_bitrate_bps = streams[0].max_bitrate_bps;
3113 EXPECT_GT(initial_max_bitrate_bps, 0);
3114
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003115 parameters.max_bandwidth_bps = initial_max_bitrate_bps * 2;
3116 EXPECT_TRUE(channel_->SetSendParameters(parameters));
Peter Boström3afc8c42016-01-27 16:45:21 +01003117 // Insert a frame to update the encoder config.
3118 EXPECT_TRUE(capturer.CaptureFrame());
Peter Boströmdfd53fe2015-03-27 15:58:11 +01003119 streams = stream->GetVideoStreams();
3120 EXPECT_EQ(initial_max_bitrate_bps * 2, streams[0].max_bitrate_bps);
deadbeef5a4a75a2016-06-02 16:23:38 -07003121 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, nullptr));
Peter Boströmdfd53fe2015-03-27 15:58:11 +01003122}
3123
eladalonf1841382017-06-12 01:16:46 -07003124TEST_F(WebRtcVideoChannelTest,
Peter Boströmdfd53fe2015-03-27 15:58:11 +01003125 SetMaxSendBitrateCanIncreaseSimulcastSenderBitrate) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003126 cricket::VideoSendParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08003127 parameters.codecs.push_back(GetEngineCodec("VP8"));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003128 ASSERT_TRUE(channel_->SetSendParameters(parameters));
Peter Boströmdfd53fe2015-03-27 15:58:11 +01003129 channel_->SetSend(true);
3130
3131 FakeVideoSendStream* stream = AddSendStream(
3132 cricket::CreateSimStreamParams("cname", MAKE_VECTOR(kSsrcs3)));
3133
3134 // Send a frame to make sure this scales up to >1 stream (simulcast).
3135 cricket::FakeVideoCapturer capturer;
deadbeef5a4a75a2016-06-02 16:23:38 -07003136 EXPECT_TRUE(channel_->SetVideoSend(kSsrcs3[0], true, nullptr, &capturer));
Peter Boströmdfd53fe2015-03-27 15:58:11 +01003137 EXPECT_EQ(cricket::CS_RUNNING,
3138 capturer.Start(capturer.GetSupportedFormats()->front()));
3139 EXPECT_TRUE(capturer.CaptureFrame());
3140
3141 std::vector<webrtc::VideoStream> streams = stream->GetVideoStreams();
3142 ASSERT_GT(streams.size(), 1u)
3143 << "Without simulcast this test doesn't make sense.";
pbosbe16f792015-10-16 12:49:39 -07003144 int initial_max_bitrate_bps = GetTotalMaxBitrateBps(streams);
Peter Boströmdfd53fe2015-03-27 15:58:11 +01003145 EXPECT_GT(initial_max_bitrate_bps, 0);
3146
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003147 parameters.max_bandwidth_bps = initial_max_bitrate_bps * 2;
3148 EXPECT_TRUE(channel_->SetSendParameters(parameters));
Peter Boström3afc8c42016-01-27 16:45:21 +01003149 // Insert a frame to update the encoder config.
3150 EXPECT_TRUE(capturer.CaptureFrame());
Peter Boströmdfd53fe2015-03-27 15:58:11 +01003151 streams = stream->GetVideoStreams();
pbosbe16f792015-10-16 12:49:39 -07003152 int increased_max_bitrate_bps = GetTotalMaxBitrateBps(streams);
Peter Boströmdfd53fe2015-03-27 15:58:11 +01003153 EXPECT_EQ(initial_max_bitrate_bps * 2, increased_max_bitrate_bps);
3154
deadbeef5a4a75a2016-06-02 16:23:38 -07003155 EXPECT_TRUE(channel_->SetVideoSend(kSsrcs3[0], true, nullptr, nullptr));
Peter Boströmdfd53fe2015-03-27 15:58:11 +01003156}
3157
eladalonf1841382017-06-12 01:16:46 -07003158TEST_F(WebRtcVideoChannelTest, SetSendCodecsWithMaxQuantization) {
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00003159 static const char* kMaxQuantization = "21";
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003160 cricket::VideoSendParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08003161 parameters.codecs.push_back(GetEngineCodec("VP8"));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003162 parameters.codecs[0].params[kCodecParamMaxQuantization] = kMaxQuantization;
3163 EXPECT_TRUE(channel_->SetSendParameters(parameters));
pbos@webrtc.org6ae48c62014-06-06 10:49:19 +00003164 EXPECT_EQ(static_cast<unsigned int>(atoi(kMaxQuantization)),
3165 AddSendStream()->GetVideoStreams().back().max_qp);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00003166
3167 VideoCodec codec;
3168 EXPECT_TRUE(channel_->GetSendCodec(&codec));
3169 EXPECT_EQ(kMaxQuantization, codec.params[kCodecParamMaxQuantization]);
3170}
3171
eladalonf1841382017-06-12 01:16:46 -07003172TEST_F(WebRtcVideoChannelTest, SetSendCodecsRejectBadPayloadTypes) {
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00003173 // TODO(pbos): Should we only allow the dynamic range?
pkasting@chromium.orge7a4a122015-01-28 21:36:55 +00003174 static const int kIncorrectPayloads[] = {-2, -1, 128, 129};
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003175 cricket::VideoSendParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08003176 parameters.codecs.push_back(GetEngineCodec("VP8"));
pkasting@chromium.orge7a4a122015-01-28 21:36:55 +00003177 for (size_t i = 0; i < arraysize(kIncorrectPayloads); ++i) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003178 parameters.codecs[0].id = kIncorrectPayloads[i];
3179 EXPECT_FALSE(channel_->SetSendParameters(parameters))
pkasting@chromium.orgd3245462015-02-23 21:28:22 +00003180 << "Bad payload type '" << kIncorrectPayloads[i] << "' accepted.";
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00003181 }
3182}
3183
eladalonf1841382017-06-12 01:16:46 -07003184TEST_F(WebRtcVideoChannelTest, SetSendCodecsAcceptAllValidPayloadTypes) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003185 cricket::VideoSendParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08003186 parameters.codecs.push_back(GetEngineCodec("VP8"));
magjedf823ede2016-11-12 09:53:04 -08003187 for (int payload_type = 96; payload_type <= 127; ++payload_type) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003188 parameters.codecs[0].id = payload_type;
3189 EXPECT_TRUE(channel_->SetSendParameters(parameters))
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00003190 << "Payload type '" << payload_type << "' rejected.";
3191 }
3192}
3193
deadbeef67cf2c12016-04-13 10:07:16 -07003194// Test that setting the a different set of codecs but with an identical front
3195// codec doesn't result in the stream being recreated.
3196// This may happen when a subsequent negotiation includes fewer codecs, as a
3197// result of one of the codecs being rejected.
eladalonf1841382017-06-12 01:16:46 -07003198TEST_F(WebRtcVideoChannelTest,
deadbeef67cf2c12016-04-13 10:07:16 -07003199 SetSendCodecsIdenticalFirstCodecDoesntRecreateStream) {
3200 cricket::VideoSendParameters parameters1;
magjed509e4fe2016-11-18 01:34:11 -08003201 parameters1.codecs.push_back(GetEngineCodec("VP8"));
3202 parameters1.codecs.push_back(GetEngineCodec("VP9"));
deadbeef67cf2c12016-04-13 10:07:16 -07003203 EXPECT_TRUE(channel_->SetSendParameters(parameters1));
3204
3205 AddSendStream();
3206 EXPECT_EQ(1, fake_call_->GetNumCreatedSendStreams());
3207
3208 cricket::VideoSendParameters parameters2;
magjed509e4fe2016-11-18 01:34:11 -08003209 parameters2.codecs.push_back(GetEngineCodec("VP8"));
deadbeef67cf2c12016-04-13 10:07:16 -07003210 EXPECT_TRUE(channel_->SetSendParameters(parameters2));
3211 EXPECT_EQ(1, fake_call_->GetNumCreatedSendStreams());
3212}
3213
eladalonf1841382017-06-12 01:16:46 -07003214TEST_F(WebRtcVideoChannelTest, SetRecvCodecsWithOnlyVp8) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003215 cricket::VideoRecvParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08003216 parameters.codecs.push_back(GetEngineCodec("VP8"));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003217 EXPECT_TRUE(channel_->SetRecvParameters(parameters));
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00003218}
3219
pbos@webrtc.orge322a172014-06-13 11:47:28 +00003220// Test that we set our inbound RTX codecs properly.
eladalonf1841382017-06-12 01:16:46 -07003221TEST_F(WebRtcVideoChannelTest, SetRecvCodecsWithRtx) {
magjed509e4fe2016-11-18 01:34:11 -08003222 const int kUnusedPayloadType1 = 126;
3223 const int kUnusedPayloadType2 = 127;
3224 EXPECT_FALSE(FindCodecById(engine_.codecs(), kUnusedPayloadType1));
3225 EXPECT_FALSE(FindCodecById(engine_.codecs(), kUnusedPayloadType2));
3226
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003227 cricket::VideoRecvParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08003228 parameters.codecs.push_back(GetEngineCodec("VP8"));
3229 cricket::VideoCodec rtx_codec(kUnusedPayloadType1, "rtx");
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003230 parameters.codecs.push_back(rtx_codec);
3231 EXPECT_FALSE(channel_->SetRecvParameters(parameters))
pbos@webrtc.orge322a172014-06-13 11:47:28 +00003232 << "RTX codec without associated payload should be rejected.";
3233
magjed509e4fe2016-11-18 01:34:11 -08003234 parameters.codecs[1].SetParam("apt", kUnusedPayloadType2);
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003235 EXPECT_FALSE(channel_->SetRecvParameters(parameters))
pbos@webrtc.orge322a172014-06-13 11:47:28 +00003236 << "RTX codec with invalid associated payload type should be rejected.";
3237
magjed509e4fe2016-11-18 01:34:11 -08003238 parameters.codecs[1].SetParam("apt", GetEngineCodec("VP8").id);
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003239 EXPECT_TRUE(channel_->SetRecvParameters(parameters));
pbos@webrtc.orge322a172014-06-13 11:47:28 +00003240
magjed509e4fe2016-11-18 01:34:11 -08003241 cricket::VideoCodec rtx_codec2(kUnusedPayloadType2, "rtx");
pbos@webrtc.orge322a172014-06-13 11:47:28 +00003242 rtx_codec2.SetParam("apt", rtx_codec.id);
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003243 parameters.codecs.push_back(rtx_codec2);
pbos@webrtc.orge322a172014-06-13 11:47:28 +00003244
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003245 EXPECT_FALSE(channel_->SetRecvParameters(parameters)) <<
3246 "RTX codec with another RTX as associated payload type should be "
3247 "rejected.";
pbos@webrtc.orge322a172014-06-13 11:47:28 +00003248}
3249
eladalonf1841382017-06-12 01:16:46 -07003250TEST_F(WebRtcVideoChannelTest, SetRecvCodecsWithChangedRtxPayloadType) {
brandtr14742122017-01-27 04:53:07 -08003251 const int kUnusedPayloadType1 = 126;
3252 const int kUnusedPayloadType2 = 127;
3253 EXPECT_FALSE(FindCodecById(engine_.codecs(), kUnusedPayloadType1));
3254 EXPECT_FALSE(FindCodecById(engine_.codecs(), kUnusedPayloadType2));
3255
3256 // SSRCs for RTX.
3257 cricket::StreamParams params =
3258 cricket::StreamParams::CreateLegacy(kSsrcs1[0]);
3259 params.AddFidSsrc(kSsrcs1[0], kRtxSsrcs1[0]);
3260 AddRecvStream(params);
3261
3262 // Original payload type for RTX.
3263 cricket::VideoRecvParameters parameters;
3264 parameters.codecs.push_back(GetEngineCodec("VP8"));
3265 cricket::VideoCodec rtx_codec(kUnusedPayloadType1, "rtx");
3266 rtx_codec.SetParam("apt", GetEngineCodec("VP8").id);
3267 parameters.codecs.push_back(rtx_codec);
3268 EXPECT_TRUE(channel_->SetRecvParameters(parameters));
3269 ASSERT_EQ(1U, fake_call_->GetVideoReceiveStreams().size());
3270 const webrtc::VideoReceiveStream::Config& config_before =
3271 fake_call_->GetVideoReceiveStreams()[0]->GetConfig();
nisse26e3abb2017-08-25 04:44:25 -07003272 EXPECT_EQ(1U, config_before.rtp.rtx_associated_payload_types.size());
3273 const int* payload_type_before = FindKeyByValue(
3274 config_before.rtp.rtx_associated_payload_types, GetEngineCodec("VP8").id);
3275 ASSERT_NE(payload_type_before, nullptr);
3276 EXPECT_EQ(kUnusedPayloadType1, *payload_type_before);
brandtr14742122017-01-27 04:53:07 -08003277 EXPECT_EQ(kRtxSsrcs1[0], config_before.rtp.rtx_ssrc);
3278
3279 // Change payload type for RTX.
3280 parameters.codecs[1].id = kUnusedPayloadType2;
3281 EXPECT_TRUE(channel_->SetRecvParameters(parameters));
3282 ASSERT_EQ(1U, fake_call_->GetVideoReceiveStreams().size());
3283 const webrtc::VideoReceiveStream::Config& config_after =
3284 fake_call_->GetVideoReceiveStreams()[0]->GetConfig();
nisse26e3abb2017-08-25 04:44:25 -07003285 EXPECT_EQ(1U, config_after.rtp.rtx_associated_payload_types.size());
3286 const int* payload_type_after = FindKeyByValue(
3287 config_after.rtp.rtx_associated_payload_types, GetEngineCodec("VP8").id);
3288 ASSERT_NE(payload_type_after, nullptr);
3289 EXPECT_EQ(kUnusedPayloadType2, *payload_type_after);
brandtr14742122017-01-27 04:53:07 -08003290 EXPECT_EQ(kRtxSsrcs1[0], config_after.rtp.rtx_ssrc);
3291}
3292
eladalonf1841382017-06-12 01:16:46 -07003293TEST_F(WebRtcVideoChannelTest, SetRecvCodecsDifferentPayloadType) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003294 cricket::VideoRecvParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08003295 parameters.codecs.push_back(GetEngineCodec("VP8"));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003296 parameters.codecs[0].id = 99;
3297 EXPECT_TRUE(channel_->SetRecvParameters(parameters));
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00003298}
3299
eladalonf1841382017-06-12 01:16:46 -07003300TEST_F(WebRtcVideoChannelTest, SetRecvCodecsAcceptDefaultCodecs) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003301 cricket::VideoRecvParameters parameters;
3302 parameters.codecs = engine_.codecs();
3303 EXPECT_TRUE(channel_->SetRecvParameters(parameters));
pbos@webrtc.orgccbed3b2014-07-11 13:02:54 +00003304
3305 FakeVideoReceiveStream* stream = AddRecvStream();
Tommi733b5472016-06-10 17:58:01 +02003306 const webrtc::VideoReceiveStream::Config& config = stream->GetConfig();
pbos@webrtc.org776e6f22014-10-29 15:28:39 +00003307 EXPECT_EQ(engine_.codecs()[0].name, config.decoders[0].payload_name);
3308 EXPECT_EQ(engine_.codecs()[0].id, config.decoders[0].payload_type);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00003309}
3310
eladalonf1841382017-06-12 01:16:46 -07003311TEST_F(WebRtcVideoChannelTest, SetRecvCodecsRejectUnsupportedCodec) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003312 cricket::VideoRecvParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08003313 parameters.codecs.push_back(GetEngineCodec("VP8"));
perkj26752742016-10-24 01:21:16 -07003314 parameters.codecs.push_back(VideoCodec(101, "WTF3"));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003315 EXPECT_FALSE(channel_->SetRecvParameters(parameters));
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00003316}
3317
eladalonf1841382017-06-12 01:16:46 -07003318TEST_F(WebRtcVideoChannelTest, SetRecvCodecsAcceptsMultipleVideoCodecs) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003319 cricket::VideoRecvParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08003320 parameters.codecs.push_back(GetEngineCodec("VP8"));
3321 parameters.codecs.push_back(GetEngineCodec("VP9"));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003322 EXPECT_TRUE(channel_->SetRecvParameters(parameters));
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00003323}
3324
eladalonf1841382017-06-12 01:16:46 -07003325TEST_F(WebRtcVideoChannelTest, SetRecvCodecsWithoutFecDisablesFec) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003326 cricket::VideoSendParameters send_parameters;
magjed509e4fe2016-11-18 01:34:11 -08003327 send_parameters.codecs.push_back(GetEngineCodec("VP8"));
3328 send_parameters.codecs.push_back(GetEngineCodec("red"));
3329 send_parameters.codecs.push_back(GetEngineCodec("ulpfec"));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003330 ASSERT_TRUE(channel_->SetSendParameters(send_parameters));
pbos@webrtc.orgd1ea06b2014-07-18 09:35:58 +00003331
3332 FakeVideoReceiveStream* stream = AddRecvStream();
pbos@webrtc.orgd1ea06b2014-07-18 09:35:58 +00003333
magjed509e4fe2016-11-18 01:34:11 -08003334 EXPECT_EQ(GetEngineCodec("ulpfec").id,
nisse3b3622f2017-09-26 02:49:21 -07003335 stream->GetConfig().rtp.ulpfec_payload_type);
pbos@webrtc.orgd1ea06b2014-07-18 09:35:58 +00003336
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003337 cricket::VideoRecvParameters recv_parameters;
magjed509e4fe2016-11-18 01:34:11 -08003338 recv_parameters.codecs.push_back(GetEngineCodec("VP8"));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003339 ASSERT_TRUE(channel_->SetRecvParameters(recv_parameters));
pbos@webrtc.org42684be2014-10-03 11:25:45 +00003340 stream = fake_call_->GetVideoReceiveStreams()[0];
brandtr468da7c2016-11-22 02:16:47 -08003341 ASSERT_TRUE(stream != nullptr);
nisse3b3622f2017-09-26 02:49:21 -07003342 EXPECT_EQ(-1, stream->GetConfig().rtp.ulpfec_payload_type)
brandtr468da7c2016-11-22 02:16:47 -08003343 << "SetSendCodec without ULPFEC should disable current ULPFEC.";
3344}
3345
eladalonf1841382017-06-12 01:16:46 -07003346TEST_F(WebRtcVideoChannelFlexfecRecvTest, SetRecvParamsWithoutFecDisablesFec) {
brandtr468da7c2016-11-22 02:16:47 -08003347 AddRecvStream(
3348 CreatePrimaryWithFecFrStreamParams("cname", kSsrcs1[0], kFlexfecSsrc));
brandtr9c3d4c42017-01-23 06:59:13 -08003349 const std::vector<FakeFlexfecReceiveStream*>& streams =
brandtr468da7c2016-11-22 02:16:47 -08003350 fake_call_->GetFlexfecReceiveStreams();
3351
3352 ASSERT_EQ(1U, streams.size());
brandtr9c3d4c42017-01-23 06:59:13 -08003353 const FakeFlexfecReceiveStream* stream = streams.front();
3354 EXPECT_EQ(GetEngineCodec("flexfec-03").id, stream->GetConfig().payload_type);
3355 EXPECT_EQ(kFlexfecSsrc, stream->GetConfig().remote_ssrc);
3356 ASSERT_EQ(1U, stream->GetConfig().protected_media_ssrcs.size());
3357 EXPECT_EQ(kSsrcs1[0], stream->GetConfig().protected_media_ssrcs[0]);
brandtr468da7c2016-11-22 02:16:47 -08003358
3359 cricket::VideoRecvParameters recv_parameters;
3360 recv_parameters.codecs.push_back(GetEngineCodec("VP8"));
3361 ASSERT_TRUE(channel_->SetRecvParameters(recv_parameters));
3362 EXPECT_TRUE(streams.empty())
3363 << "SetSendCodec without FlexFEC should disable current FlexFEC.";
pbos@webrtc.org269605c2014-06-26 08:49:03 +00003364}
3365
eladalonf1841382017-06-12 01:16:46 -07003366TEST_F(WebRtcVideoChannelTest, SetSendParamsWithFecEnablesFec) {
Stefan Holmer2b1f6512016-05-17 16:33:30 +02003367 FakeVideoReceiveStream* stream = AddRecvStream();
magjed509e4fe2016-11-18 01:34:11 -08003368 EXPECT_EQ(GetEngineCodec("ulpfec").id,
nisse3b3622f2017-09-26 02:49:21 -07003369 stream->GetConfig().rtp.ulpfec_payload_type);
Stefan Holmer2b1f6512016-05-17 16:33:30 +02003370
3371 cricket::VideoRecvParameters recv_parameters;
magjed509e4fe2016-11-18 01:34:11 -08003372 recv_parameters.codecs.push_back(GetEngineCodec("VP8"));
3373 recv_parameters.codecs.push_back(GetEngineCodec("red"));
3374 recv_parameters.codecs.push_back(GetEngineCodec("ulpfec"));
Stefan Holmer2b1f6512016-05-17 16:33:30 +02003375 ASSERT_TRUE(channel_->SetRecvParameters(recv_parameters));
3376 stream = fake_call_->GetVideoReceiveStreams()[0];
brandtr468da7c2016-11-22 02:16:47 -08003377 ASSERT_TRUE(stream != nullptr);
magjed509e4fe2016-11-18 01:34:11 -08003378 EXPECT_EQ(GetEngineCodec("ulpfec").id,
nisse3b3622f2017-09-26 02:49:21 -07003379 stream->GetConfig().rtp.ulpfec_payload_type)
brandtr468da7c2016-11-22 02:16:47 -08003380 << "ULPFEC should be enabled on the receive stream.";
Stefan Holmer2b1f6512016-05-17 16:33:30 +02003381
3382 cricket::VideoSendParameters send_parameters;
magjed509e4fe2016-11-18 01:34:11 -08003383 send_parameters.codecs.push_back(GetEngineCodec("VP8"));
3384 send_parameters.codecs.push_back(GetEngineCodec("red"));
3385 send_parameters.codecs.push_back(GetEngineCodec("ulpfec"));
Stefan Holmer2b1f6512016-05-17 16:33:30 +02003386 ASSERT_TRUE(channel_->SetSendParameters(send_parameters));
3387 stream = fake_call_->GetVideoReceiveStreams()[0];
magjed509e4fe2016-11-18 01:34:11 -08003388 EXPECT_EQ(GetEngineCodec("ulpfec").id,
nisse3b3622f2017-09-26 02:49:21 -07003389 stream->GetConfig().rtp.ulpfec_payload_type)
brandtr468da7c2016-11-22 02:16:47 -08003390 << "ULPFEC should be enabled on the receive stream.";
3391}
3392
eladalonf1841382017-06-12 01:16:46 -07003393TEST_F(WebRtcVideoChannelFlexfecSendRecvTest,
brandtr31bd2242017-05-19 05:47:46 -07003394 SetSendRecvParamsWithFecEnablesFec) {
brandtr468da7c2016-11-22 02:16:47 -08003395 AddRecvStream(
3396 CreatePrimaryWithFecFrStreamParams("cname", kSsrcs1[0], kFlexfecSsrc));
brandtr9c3d4c42017-01-23 06:59:13 -08003397 const std::vector<FakeFlexfecReceiveStream*>& streams =
brandtr468da7c2016-11-22 02:16:47 -08003398 fake_call_->GetFlexfecReceiveStreams();
3399
3400 cricket::VideoRecvParameters recv_parameters;
3401 recv_parameters.codecs.push_back(GetEngineCodec("VP8"));
3402 recv_parameters.codecs.push_back(GetEngineCodec("flexfec-03"));
3403 ASSERT_TRUE(channel_->SetRecvParameters(recv_parameters));
3404 ASSERT_EQ(1U, streams.size());
brandtr9c3d4c42017-01-23 06:59:13 -08003405 const FakeFlexfecReceiveStream* stream_with_recv_params = streams.front();
brandtr468da7c2016-11-22 02:16:47 -08003406 EXPECT_EQ(GetEngineCodec("flexfec-03").id,
brandtr9c3d4c42017-01-23 06:59:13 -08003407 stream_with_recv_params->GetConfig().payload_type);
3408 EXPECT_EQ(kFlexfecSsrc, stream_with_recv_params->GetConfig().remote_ssrc);
brandtr468da7c2016-11-22 02:16:47 -08003409 EXPECT_EQ(1U,
brandtr9c3d4c42017-01-23 06:59:13 -08003410 stream_with_recv_params->GetConfig().protected_media_ssrcs.size());
brandtr468da7c2016-11-22 02:16:47 -08003411 EXPECT_EQ(kSsrcs1[0],
brandtr9c3d4c42017-01-23 06:59:13 -08003412 stream_with_recv_params->GetConfig().protected_media_ssrcs[0]);
brandtr468da7c2016-11-22 02:16:47 -08003413
3414 cricket::VideoSendParameters send_parameters;
3415 send_parameters.codecs.push_back(GetEngineCodec("VP8"));
3416 send_parameters.codecs.push_back(GetEngineCodec("flexfec-03"));
3417 ASSERT_TRUE(channel_->SetSendParameters(send_parameters));
3418 ASSERT_EQ(1U, streams.size());
brandtr9c3d4c42017-01-23 06:59:13 -08003419 const FakeFlexfecReceiveStream* stream_with_send_params = streams.front();
brandtr468da7c2016-11-22 02:16:47 -08003420 EXPECT_EQ(GetEngineCodec("flexfec-03").id,
brandtr9c3d4c42017-01-23 06:59:13 -08003421 stream_with_send_params->GetConfig().payload_type);
3422 EXPECT_EQ(kFlexfecSsrc, stream_with_send_params->GetConfig().remote_ssrc);
brandtr468da7c2016-11-22 02:16:47 -08003423 EXPECT_EQ(1U,
brandtr9c3d4c42017-01-23 06:59:13 -08003424 stream_with_send_params->GetConfig().protected_media_ssrcs.size());
brandtr468da7c2016-11-22 02:16:47 -08003425 EXPECT_EQ(kSsrcs1[0],
brandtr9c3d4c42017-01-23 06:59:13 -08003426 stream_with_send_params->GetConfig().protected_media_ssrcs[0]);
Stefan Holmer2b1f6512016-05-17 16:33:30 +02003427}
3428
eladalonf1841382017-06-12 01:16:46 -07003429TEST_F(WebRtcVideoChannelTest, SetRecvCodecsRejectDuplicateFecPayloads) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003430 cricket::VideoRecvParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08003431 parameters.codecs.push_back(GetEngineCodec("VP8"));
3432 parameters.codecs.push_back(GetEngineCodec("red"));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003433 parameters.codecs[1].id = parameters.codecs[0].id;
3434 EXPECT_FALSE(channel_->SetRecvParameters(parameters));
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00003435}
3436
eladalonf1841382017-06-12 01:16:46 -07003437TEST_F(WebRtcVideoChannelFlexfecRecvTest,
brandtr31bd2242017-05-19 05:47:46 -07003438 SetRecvCodecsRejectDuplicateFecPayloads) {
brandtr468da7c2016-11-22 02:16:47 -08003439 cricket::VideoRecvParameters parameters;
3440 parameters.codecs.push_back(GetEngineCodec("VP8"));
3441 parameters.codecs.push_back(GetEngineCodec("flexfec-03"));
3442 parameters.codecs[1].id = parameters.codecs[0].id;
3443 EXPECT_FALSE(channel_->SetRecvParameters(parameters));
3444}
3445
eladalonf1841382017-06-12 01:16:46 -07003446TEST_F(WebRtcVideoChannelTest, SetRecvCodecsRejectDuplicateCodecPayloads) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003447 cricket::VideoRecvParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08003448 parameters.codecs.push_back(GetEngineCodec("VP8"));
3449 parameters.codecs.push_back(GetEngineCodec("VP9"));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003450 parameters.codecs[1].id = parameters.codecs[0].id;
3451 EXPECT_FALSE(channel_->SetRecvParameters(parameters));
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00003452}
3453
eladalonf1841382017-06-12 01:16:46 -07003454TEST_F(WebRtcVideoChannelTest,
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00003455 SetRecvCodecsAcceptSameCodecOnMultiplePayloadTypes) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003456 cricket::VideoRecvParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08003457 parameters.codecs.push_back(GetEngineCodec("VP8"));
3458 parameters.codecs.push_back(GetEngineCodec("VP8"));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003459 parameters.codecs[1].id += 1;
3460 EXPECT_TRUE(channel_->SetRecvParameters(parameters));
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00003461}
3462
deadbeef67cf2c12016-04-13 10:07:16 -07003463// Test that setting the same codecs but with a different order
deadbeef874ca3a2015-08-20 17:19:20 -07003464// doesn't result in the stream being recreated.
eladalonf1841382017-06-12 01:16:46 -07003465TEST_F(WebRtcVideoChannelTest,
deadbeef67cf2c12016-04-13 10:07:16 -07003466 SetRecvCodecsDifferentOrderDoesntRecreateStream) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003467 cricket::VideoRecvParameters parameters1;
magjed509e4fe2016-11-18 01:34:11 -08003468 parameters1.codecs.push_back(GetEngineCodec("VP8"));
3469 parameters1.codecs.push_back(GetEngineCodec("red"));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003470 EXPECT_TRUE(channel_->SetRecvParameters(parameters1));
deadbeef874ca3a2015-08-20 17:19:20 -07003471
3472 AddRecvStream(cricket::StreamParams::CreateLegacy(123));
3473 EXPECT_EQ(1, fake_call_->GetNumCreatedReceiveStreams());
3474
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003475 cricket::VideoRecvParameters parameters2;
magjed509e4fe2016-11-18 01:34:11 -08003476 parameters2.codecs.push_back(GetEngineCodec("red"));
3477 parameters2.codecs.push_back(GetEngineCodec("VP8"));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003478 EXPECT_TRUE(channel_->SetRecvParameters(parameters2));
deadbeef874ca3a2015-08-20 17:19:20 -07003479 EXPECT_EQ(1, fake_call_->GetNumCreatedReceiveStreams());
3480}
3481
eladalonf1841382017-06-12 01:16:46 -07003482TEST_F(WebRtcVideoChannelTest, SendStreamNotSendingByDefault) {
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00003483 EXPECT_FALSE(AddSendStream()->IsSending());
3484}
3485
eladalonf1841382017-06-12 01:16:46 -07003486TEST_F(WebRtcVideoChannelTest, ReceiveStreamReceivingByDefault) {
pbos@webrtc.org85f42942014-07-22 09:14:58 +00003487 EXPECT_TRUE(AddRecvStream()->IsReceiving());
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00003488}
3489
eladalonf1841382017-06-12 01:16:46 -07003490TEST_F(WebRtcVideoChannelTest, SetSend) {
pbos@webrtc.org5301b0f2014-07-17 08:51:46 +00003491 FakeVideoSendStream* stream = AddSendStream();
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00003492 EXPECT_FALSE(stream->IsSending());
3493
3494 // false->true
3495 EXPECT_TRUE(channel_->SetSend(true));
3496 EXPECT_TRUE(stream->IsSending());
3497 // true->true
3498 EXPECT_TRUE(channel_->SetSend(true));
3499 EXPECT_TRUE(stream->IsSending());
3500 // true->false
3501 EXPECT_TRUE(channel_->SetSend(false));
3502 EXPECT_FALSE(stream->IsSending());
3503 // false->false
3504 EXPECT_TRUE(channel_->SetSend(false));
3505 EXPECT_FALSE(stream->IsSending());
3506
3507 EXPECT_TRUE(channel_->SetSend(true));
3508 FakeVideoSendStream* new_stream = AddSendStream();
3509 EXPECT_TRUE(new_stream->IsSending())
3510 << "Send stream created after SetSend(true) not sending initially.";
3511}
3512
pbos@webrtc.orgd8198032014-11-10 14:41:43 +00003513// This test verifies DSCP settings are properly applied on video media channel.
eladalonf1841382017-06-12 01:16:46 -07003514TEST_F(WebRtcVideoChannelTest, TestSetDscpOptions) {
kwiberg686a8ef2016-02-26 03:00:35 -08003515 std::unique_ptr<cricket::FakeNetworkInterface> network_interface(
pbos@webrtc.orgd8198032014-11-10 14:41:43 +00003516 new cricket::FakeNetworkInterface);
nisse51542be2016-02-12 02:27:06 -08003517 MediaConfig config;
kwiberg686a8ef2016-02-26 03:00:35 -08003518 std::unique_ptr<VideoMediaChannel> channel;
nisse51542be2016-02-12 02:27:06 -08003519
3520 channel.reset(engine_.CreateChannel(call_.get(), config, VideoOptions()));
3521 channel->SetInterface(network_interface.get());
3522 // Default value when DSCP is disabled should be DSCP_DEFAULT.
pbos@webrtc.orgd8198032014-11-10 14:41:43 +00003523 EXPECT_EQ(rtc::DSCP_DEFAULT, network_interface->dscp());
nisse51542be2016-02-12 02:27:06 -08003524
3525 config.enable_dscp = true;
3526 channel.reset(engine_.CreateChannel(call_.get(), config, VideoOptions()));
3527 channel->SetInterface(network_interface.get());
3528 EXPECT_EQ(rtc::DSCP_AF41, network_interface->dscp());
3529
3530 // Verify that setting the option to false resets the
3531 // DiffServCodePoint.
3532 config.enable_dscp = false;
3533 channel.reset(engine_.CreateChannel(call_.get(), config, VideoOptions()));
3534 channel->SetInterface(network_interface.get());
3535 EXPECT_EQ(rtc::DSCP_DEFAULT, network_interface->dscp());
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00003536}
3537
deadbeef13871492015-12-09 12:37:51 -08003538// This test verifies that the RTCP reduced size mode is properly applied to
3539// send video streams.
eladalonf1841382017-06-12 01:16:46 -07003540TEST_F(WebRtcVideoChannelTest, TestSetSendRtcpReducedSize) {
deadbeef13871492015-12-09 12:37:51 -08003541 // Create stream, expecting that default mode is "compound".
3542 FakeVideoSendStream* stream1 = AddSendStream();
3543 EXPECT_EQ(webrtc::RtcpMode::kCompound, stream1->GetConfig().rtp.rtcp_mode);
3544
3545 // Now enable reduced size mode.
3546 send_parameters_.rtcp.reduced_size = true;
3547 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
3548 stream1 = fake_call_->GetVideoSendStreams()[0];
3549 EXPECT_EQ(webrtc::RtcpMode::kReducedSize, stream1->GetConfig().rtp.rtcp_mode);
3550
3551 // Create a new stream and ensure it picks up the reduced size mode.
3552 FakeVideoSendStream* stream2 = AddSendStream();
3553 EXPECT_EQ(webrtc::RtcpMode::kReducedSize, stream2->GetConfig().rtp.rtcp_mode);
3554}
3555
3556// This test verifies that the RTCP reduced size mode is properly applied to
3557// receive video streams.
eladalonf1841382017-06-12 01:16:46 -07003558TEST_F(WebRtcVideoChannelTest, TestSetRecvRtcpReducedSize) {
deadbeef13871492015-12-09 12:37:51 -08003559 // Create stream, expecting that default mode is "compound".
3560 FakeVideoReceiveStream* stream1 = AddRecvStream();
3561 EXPECT_EQ(webrtc::RtcpMode::kCompound, stream1->GetConfig().rtp.rtcp_mode);
3562
3563 // Now enable reduced size mode.
Taylor Brandstetter5f0b83b2016-03-18 15:02:07 -07003564 // TODO(deadbeef): Once "recv_parameters" becomes "receiver_parameters",
3565 // the reduced_size flag should come from that.
3566 send_parameters_.rtcp.reduced_size = true;
3567 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
deadbeef13871492015-12-09 12:37:51 -08003568 stream1 = fake_call_->GetVideoReceiveStreams()[0];
3569 EXPECT_EQ(webrtc::RtcpMode::kReducedSize, stream1->GetConfig().rtp.rtcp_mode);
3570
3571 // Create a new stream and ensure it picks up the reduced size mode.
3572 FakeVideoReceiveStream* stream2 = AddRecvStream();
3573 EXPECT_EQ(webrtc::RtcpMode::kReducedSize, stream2->GetConfig().rtp.rtcp_mode);
3574}
3575
eladalonf1841382017-06-12 01:16:46 -07003576TEST_F(WebRtcVideoChannelTest, OnReadyToSendSignalsNetworkState) {
skvlad7a43d252016-03-22 15:32:27 -07003577 EXPECT_EQ(webrtc::kNetworkUp,
3578 fake_call_->GetNetworkState(webrtc::MediaType::VIDEO));
3579 EXPECT_EQ(webrtc::kNetworkUp,
3580 fake_call_->GetNetworkState(webrtc::MediaType::AUDIO));
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003581
3582 channel_->OnReadyToSend(false);
skvlad7a43d252016-03-22 15:32:27 -07003583 EXPECT_EQ(webrtc::kNetworkDown,
3584 fake_call_->GetNetworkState(webrtc::MediaType::VIDEO));
3585 EXPECT_EQ(webrtc::kNetworkUp,
3586 fake_call_->GetNetworkState(webrtc::MediaType::AUDIO));
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003587
3588 channel_->OnReadyToSend(true);
skvlad7a43d252016-03-22 15:32:27 -07003589 EXPECT_EQ(webrtc::kNetworkUp,
3590 fake_call_->GetNetworkState(webrtc::MediaType::VIDEO));
3591 EXPECT_EQ(webrtc::kNetworkUp,
3592 fake_call_->GetNetworkState(webrtc::MediaType::AUDIO));
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00003593}
3594
eladalonf1841382017-06-12 01:16:46 -07003595TEST_F(WebRtcVideoChannelTest, GetStatsReportsSentCodecName) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003596 cricket::VideoSendParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08003597 parameters.codecs.push_back(GetEngineCodec("VP8"));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003598 EXPECT_TRUE(channel_->SetSendParameters(parameters));
Peter Boström74d9ed72015-03-26 16:28:31 +01003599
3600 AddSendStream();
3601
3602 cricket::VideoMediaInfo info;
3603 ASSERT_TRUE(channel_->GetStats(&info));
magjed509e4fe2016-11-18 01:34:11 -08003604 EXPECT_EQ("VP8", info.senders[0].codec_name);
Peter Boström74d9ed72015-03-26 16:28:31 +01003605}
3606
eladalonf1841382017-06-12 01:16:46 -07003607TEST_F(WebRtcVideoChannelTest, GetStatsReportsEncoderImplementationName) {
Peter Boströmb7d9a972015-12-18 16:01:11 +01003608 FakeVideoSendStream* stream = AddSendStream();
3609 webrtc::VideoSendStream::Stats stats;
3610 stats.encoder_implementation_name = "encoder_implementation_name";
3611 stream->SetStats(stats);
3612
3613 cricket::VideoMediaInfo info;
3614 ASSERT_TRUE(channel_->GetStats(&info));
3615 EXPECT_EQ(stats.encoder_implementation_name,
3616 info.senders[0].encoder_implementation_name);
3617}
3618
eladalonf1841382017-06-12 01:16:46 -07003619TEST_F(WebRtcVideoChannelTest, GetStatsReportsCpuOveruseMetrics) {
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00003620 FakeVideoSendStream* stream = AddSendStream();
3621 webrtc::VideoSendStream::Stats stats;
3622 stats.avg_encode_time_ms = 13;
3623 stats.encode_usage_percent = 42;
3624 stream->SetStats(stats);
3625
3626 cricket::VideoMediaInfo info;
pbos@webrtc.org058b1f12015-03-04 08:54:32 +00003627 ASSERT_TRUE(channel_->GetStats(&info));
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00003628 EXPECT_EQ(stats.avg_encode_time_ms, info.senders[0].avg_encode_ms);
3629 EXPECT_EQ(stats.encode_usage_percent, info.senders[0].encode_usage_percent);
3630}
3631
eladalonf1841382017-06-12 01:16:46 -07003632TEST_F(WebRtcVideoChannelTest, GetStatsReportsFramesEncoded) {
sakal43536c32016-10-24 01:46:43 -07003633 FakeVideoSendStream* stream = AddSendStream();
3634 webrtc::VideoSendStream::Stats stats;
3635 stats.frames_encoded = 13;
3636 stream->SetStats(stats);
3637
3638 cricket::VideoMediaInfo info;
3639 ASSERT_TRUE(channel_->GetStats(&info));
3640 EXPECT_EQ(stats.frames_encoded, info.senders[0].frames_encoded);
3641}
3642
eladalonf1841382017-06-12 01:16:46 -07003643TEST_F(WebRtcVideoChannelTest, GetStatsReportsQpSum) {
sakal87da4042016-10-31 06:53:47 -07003644 FakeVideoSendStream* stream = AddSendStream();
3645 webrtc::VideoSendStream::Stats stats;
3646 stats.qp_sum = rtc::Optional<uint64_t>(13);
3647 stream->SetStats(stats);
3648
3649 cricket::VideoMediaInfo info;
3650 ASSERT_TRUE(channel_->GetStats(&info));
3651 EXPECT_EQ(stats.qp_sum, info.senders[0].qp_sum);
3652}
3653
eladalonf1841382017-06-12 01:16:46 -07003654TEST_F(WebRtcVideoChannelTest, GetStatsReportsUpperResolution) {
pbos@webrtc.org273a4142014-12-01 15:23:21 +00003655 FakeVideoSendStream* stream = AddSendStream();
3656 webrtc::VideoSendStream::Stats stats;
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00003657 stats.substreams[17].width = 123;
3658 stats.substreams[17].height = 40;
3659 stats.substreams[42].width = 80;
3660 stats.substreams[42].height = 31;
3661 stats.substreams[11].width = 20;
3662 stats.substreams[11].height = 90;
pbos@webrtc.org273a4142014-12-01 15:23:21 +00003663 stream->SetStats(stats);
3664
3665 cricket::VideoMediaInfo info;
pbos@webrtc.org058b1f12015-03-04 08:54:32 +00003666 ASSERT_TRUE(channel_->GetStats(&info));
pbos@webrtc.org273a4142014-12-01 15:23:21 +00003667 ASSERT_EQ(1u, info.senders.size());
3668 EXPECT_EQ(123, info.senders[0].send_frame_width);
3669 EXPECT_EQ(90, info.senders[0].send_frame_height);
3670}
3671
eladalonf1841382017-06-12 01:16:46 -07003672TEST_F(WebRtcVideoChannelTest, GetStatsReportsPreferredBitrate) {
Pera48ddb72016-09-29 11:48:50 +02003673 FakeVideoSendStream* stream = AddSendStream();
3674 webrtc::VideoSendStream::Stats stats;
3675 stats.preferred_media_bitrate_bps = 5;
3676 stream->SetStats(stats);
3677
3678 cricket::VideoMediaInfo info;
3679 ASSERT_TRUE(channel_->GetStats(&info));
3680 ASSERT_EQ(1u, info.senders.size());
3681 EXPECT_EQ(5, info.senders[0].preferred_bitrate);
3682}
3683
eladalonf1841382017-06-12 01:16:46 -07003684TEST_F(WebRtcVideoChannelTest, GetStatsReportsCpuAdaptationStats) {
perkj803d97f2016-11-01 11:45:46 -07003685 FakeVideoSendStream* stream = AddSendStream();
3686 webrtc::VideoSendStream::Stats stats;
3687 stats.number_of_cpu_adapt_changes = 2;
3688 stats.cpu_limited_resolution = true;
3689 stream->SetStats(stats);
pbos@webrtc.org9a4410e2015-02-26 10:03:39 +00003690
pbos@webrtc.org9a4410e2015-02-26 10:03:39 +00003691 cricket::VideoMediaInfo info;
pbos@webrtc.org058b1f12015-03-04 08:54:32 +00003692 EXPECT_TRUE(channel_->GetStats(&info));
pbos@webrtc.org9a4410e2015-02-26 10:03:39 +00003693 ASSERT_EQ(1U, info.senders.size());
eladalonf1841382017-06-12 01:16:46 -07003694 EXPECT_EQ(WebRtcVideoChannel::ADAPTREASON_CPU, info.senders[0].adapt_reason);
perkj803d97f2016-11-01 11:45:46 -07003695 EXPECT_EQ(stats.number_of_cpu_adapt_changes, info.senders[0].adapt_changes);
pbos@webrtc.org9a4410e2015-02-26 10:03:39 +00003696}
3697
eladalonf1841382017-06-12 01:16:46 -07003698TEST_F(WebRtcVideoChannelTest, GetStatsReportsAdaptationAndBandwidthStats) {
perkj803d97f2016-11-01 11:45:46 -07003699 FakeVideoSendStream* stream = AddSendStream();
asapersson17821db2015-12-14 02:08:12 -08003700 webrtc::VideoSendStream::Stats stats;
perkj803d97f2016-11-01 11:45:46 -07003701 stats.number_of_cpu_adapt_changes = 2;
3702 stats.cpu_limited_resolution = true;
asapersson17821db2015-12-14 02:08:12 -08003703 stats.bw_limited_resolution = true;
perkj803d97f2016-11-01 11:45:46 -07003704 stream->SetStats(stats);
3705
3706 cricket::VideoMediaInfo info;
asapersson17821db2015-12-14 02:08:12 -08003707 EXPECT_TRUE(channel_->GetStats(&info));
3708 ASSERT_EQ(1U, info.senders.size());
eladalonf1841382017-06-12 01:16:46 -07003709 EXPECT_EQ(WebRtcVideoChannel::ADAPTREASON_CPU |
3710 WebRtcVideoChannel::ADAPTREASON_BANDWIDTH,
asapersson17821db2015-12-14 02:08:12 -08003711 info.senders[0].adapt_reason);
perkj803d97f2016-11-01 11:45:46 -07003712 EXPECT_EQ(stats.number_of_cpu_adapt_changes, info.senders[0].adapt_changes);
asapersson17821db2015-12-14 02:08:12 -08003713}
3714
eladalonf1841382017-06-12 01:16:46 -07003715TEST_F(WebRtcVideoChannelTest,
asapersson17821db2015-12-14 02:08:12 -08003716 GetStatsTranslatesBandwidthLimitedResolutionCorrectly) {
3717 FakeVideoSendStream* stream = AddSendStream();
3718 webrtc::VideoSendStream::Stats stats;
3719 stats.bw_limited_resolution = true;
3720 stream->SetStats(stats);
3721
3722 cricket::VideoMediaInfo info;
3723 EXPECT_TRUE(channel_->GetStats(&info));
3724 ASSERT_EQ(1U, info.senders.size());
eladalonf1841382017-06-12 01:16:46 -07003725 EXPECT_EQ(WebRtcVideoChannel::ADAPTREASON_BANDWIDTH,
asapersson17821db2015-12-14 02:08:12 -08003726 info.senders[0].adapt_reason);
3727}
3728
eladalonf1841382017-06-12 01:16:46 -07003729TEST_F(WebRtcVideoChannelTest,
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003730 GetStatsTranslatesSendRtcpPacketTypesCorrectly) {
3731 FakeVideoSendStream* stream = AddSendStream();
3732 webrtc::VideoSendStream::Stats stats;
3733 stats.substreams[17].rtcp_packet_type_counts.fir_packets = 2;
3734 stats.substreams[17].rtcp_packet_type_counts.nack_packets = 3;
3735 stats.substreams[17].rtcp_packet_type_counts.pli_packets = 4;
3736
3737 stats.substreams[42].rtcp_packet_type_counts.fir_packets = 5;
3738 stats.substreams[42].rtcp_packet_type_counts.nack_packets = 7;
3739 stats.substreams[42].rtcp_packet_type_counts.pli_packets = 9;
3740
3741 stream->SetStats(stats);
3742
3743 cricket::VideoMediaInfo info;
pbos@webrtc.org058b1f12015-03-04 08:54:32 +00003744 ASSERT_TRUE(channel_->GetStats(&info));
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003745 EXPECT_EQ(7, info.senders[0].firs_rcvd);
3746 EXPECT_EQ(10, info.senders[0].nacks_rcvd);
3747 EXPECT_EQ(13, info.senders[0].plis_rcvd);
3748}
3749
eladalonf1841382017-06-12 01:16:46 -07003750TEST_F(WebRtcVideoChannelTest,
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003751 GetStatsTranslatesReceiveRtcpPacketTypesCorrectly) {
3752 FakeVideoReceiveStream* stream = AddRecvStream();
3753 webrtc::VideoReceiveStream::Stats stats;
3754 stats.rtcp_packet_type_counts.fir_packets = 2;
3755 stats.rtcp_packet_type_counts.nack_packets = 3;
3756 stats.rtcp_packet_type_counts.pli_packets = 4;
3757 stream->SetStats(stats);
3758
3759 cricket::VideoMediaInfo info;
pbos@webrtc.org058b1f12015-03-04 08:54:32 +00003760 ASSERT_TRUE(channel_->GetStats(&info));
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003761 EXPECT_EQ(stats.rtcp_packet_type_counts.fir_packets,
3762 info.receivers[0].firs_sent);
3763 EXPECT_EQ(stats.rtcp_packet_type_counts.nack_packets,
3764 info.receivers[0].nacks_sent);
3765 EXPECT_EQ(stats.rtcp_packet_type_counts.pli_packets,
3766 info.receivers[0].plis_sent);
3767}
3768
eladalonf1841382017-06-12 01:16:46 -07003769TEST_F(WebRtcVideoChannelTest, GetStatsTranslatesDecodeStatsCorrectly) {
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00003770 FakeVideoReceiveStream* stream = AddRecvStream();
3771 webrtc::VideoReceiveStream::Stats stats;
Peter Boströmb7d9a972015-12-18 16:01:11 +01003772 stats.decoder_implementation_name = "decoder_implementation_name";
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00003773 stats.decode_ms = 2;
3774 stats.max_decode_ms = 3;
3775 stats.current_delay_ms = 4;
3776 stats.target_delay_ms = 5;
3777 stats.jitter_buffer_ms = 6;
3778 stats.min_playout_delay_ms = 7;
3779 stats.render_delay_ms = 8;
asapersson26dd92b2016-08-30 00:45:45 -07003780 stats.width = 9;
3781 stats.height = 10;
hbos42f6d2f2017-01-20 03:56:50 -08003782 stats.frame_counts.key_frames = 11;
3783 stats.frame_counts.delta_frames = 12;
hbos50cfe1f2017-01-23 07:21:55 -08003784 stats.frames_rendered = 13;
3785 stats.frames_decoded = 14;
sakalcc452e12017-02-09 04:53:45 -08003786 stats.qp_sum = rtc::Optional<uint64_t>(15);
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00003787 stream->SetStats(stats);
3788
3789 cricket::VideoMediaInfo info;
pbos@webrtc.org058b1f12015-03-04 08:54:32 +00003790 ASSERT_TRUE(channel_->GetStats(&info));
Peter Boströmb7d9a972015-12-18 16:01:11 +01003791 EXPECT_EQ(stats.decoder_implementation_name,
3792 info.receivers[0].decoder_implementation_name);
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00003793 EXPECT_EQ(stats.decode_ms, info.receivers[0].decode_ms);
3794 EXPECT_EQ(stats.max_decode_ms, info.receivers[0].max_decode_ms);
3795 EXPECT_EQ(stats.current_delay_ms, info.receivers[0].current_delay_ms);
3796 EXPECT_EQ(stats.target_delay_ms, info.receivers[0].target_delay_ms);
3797 EXPECT_EQ(stats.jitter_buffer_ms, info.receivers[0].jitter_buffer_ms);
3798 EXPECT_EQ(stats.min_playout_delay_ms, info.receivers[0].min_playout_delay_ms);
3799 EXPECT_EQ(stats.render_delay_ms, info.receivers[0].render_delay_ms);
asapersson26dd92b2016-08-30 00:45:45 -07003800 EXPECT_EQ(stats.width, info.receivers[0].frame_width);
3801 EXPECT_EQ(stats.height, info.receivers[0].frame_height);
hbos42f6d2f2017-01-20 03:56:50 -08003802 EXPECT_EQ(stats.frame_counts.key_frames + stats.frame_counts.delta_frames,
3803 info.receivers[0].frames_received);
hbos50cfe1f2017-01-23 07:21:55 -08003804 EXPECT_EQ(stats.frames_rendered, info.receivers[0].frames_rendered);
sakale5ba44e2016-10-26 07:09:24 -07003805 EXPECT_EQ(stats.frames_decoded, info.receivers[0].frames_decoded);
sakalcc452e12017-02-09 04:53:45 -08003806 EXPECT_EQ(stats.qp_sum, info.receivers[0].qp_sum);
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00003807}
3808
eladalonf1841382017-06-12 01:16:46 -07003809TEST_F(WebRtcVideoChannelTest, GetStatsTranslatesReceivePacketStatsCorrectly) {
Peter Boström393347f2015-04-22 14:52:45 +02003810 FakeVideoReceiveStream* stream = AddRecvStream();
3811 webrtc::VideoReceiveStream::Stats stats;
3812 stats.rtp_stats.transmitted.payload_bytes = 2;
3813 stats.rtp_stats.transmitted.header_bytes = 3;
3814 stats.rtp_stats.transmitted.padding_bytes = 4;
3815 stats.rtp_stats.transmitted.packets = 5;
srte186d9c32017-08-04 05:03:53 -07003816 stats.rtcp_stats.packets_lost = 6;
Peter Boström393347f2015-04-22 14:52:45 +02003817 stats.rtcp_stats.fraction_lost = 7;
3818 stream->SetStats(stats);
3819
3820 cricket::VideoMediaInfo info;
3821 ASSERT_TRUE(channel_->GetStats(&info));
3822 EXPECT_EQ(stats.rtp_stats.transmitted.payload_bytes +
3823 stats.rtp_stats.transmitted.header_bytes +
3824 stats.rtp_stats.transmitted.padding_bytes,
3825 info.receivers[0].bytes_rcvd);
3826 EXPECT_EQ(stats.rtp_stats.transmitted.packets,
3827 info.receivers[0].packets_rcvd);
srte186d9c32017-08-04 05:03:53 -07003828 EXPECT_EQ(stats.rtcp_stats.packets_lost, info.receivers[0].packets_lost);
Peter Boström393347f2015-04-22 14:52:45 +02003829 EXPECT_EQ(static_cast<float>(stats.rtcp_stats.fraction_lost) / (1 << 8),
3830 info.receivers[0].fraction_lost);
3831}
3832
eladalonf1841382017-06-12 01:16:46 -07003833TEST_F(WebRtcVideoChannelTest, TranslatesCallStatsCorrectly) {
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003834 AddSendStream();
3835 AddSendStream();
3836 webrtc::Call::Stats stats;
3837 stats.rtt_ms = 123;
3838 fake_call_->SetStats(stats);
3839
3840 cricket::VideoMediaInfo info;
pbos@webrtc.org058b1f12015-03-04 08:54:32 +00003841 ASSERT_TRUE(channel_->GetStats(&info));
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003842 ASSERT_EQ(2u, info.senders.size());
3843 EXPECT_EQ(stats.rtt_ms, info.senders[0].rtt_ms);
3844 EXPECT_EQ(stats.rtt_ms, info.senders[1].rtt_ms);
3845}
3846
eladalonf1841382017-06-12 01:16:46 -07003847TEST_F(WebRtcVideoChannelTest, TranslatesSenderBitrateStatsCorrectly) {
pbos@webrtc.org77e11bb2015-02-23 16:39:07 +00003848 FakeVideoSendStream* stream = AddSendStream();
3849 webrtc::VideoSendStream::Stats stats;
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003850 stats.target_media_bitrate_bps = 156;
pbos@webrtc.org77e11bb2015-02-23 16:39:07 +00003851 stats.media_bitrate_bps = 123;
3852 stats.substreams[17].total_bitrate_bps = 1;
3853 stats.substreams[17].retransmit_bitrate_bps = 2;
3854 stats.substreams[42].total_bitrate_bps = 3;
3855 stats.substreams[42].retransmit_bitrate_bps = 4;
3856 stream->SetStats(stats);
3857
3858 FakeVideoSendStream* stream2 = AddSendStream();
3859 webrtc::VideoSendStream::Stats stats2;
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003860 stats2.target_media_bitrate_bps = 200;
pbos@webrtc.org77e11bb2015-02-23 16:39:07 +00003861 stats2.media_bitrate_bps = 321;
3862 stats2.substreams[13].total_bitrate_bps = 5;
3863 stats2.substreams[13].retransmit_bitrate_bps = 6;
3864 stats2.substreams[21].total_bitrate_bps = 7;
3865 stats2.substreams[21].retransmit_bitrate_bps = 8;
3866 stream2->SetStats(stats2);
3867
3868 cricket::VideoMediaInfo info;
pbos@webrtc.org058b1f12015-03-04 08:54:32 +00003869 ASSERT_TRUE(channel_->GetStats(&info));
pbos@webrtc.org77e11bb2015-02-23 16:39:07 +00003870 ASSERT_EQ(2u, info.senders.size());
stefanf79ade12017-06-02 06:44:03 -07003871 BandwidthEstimationInfo bwe_info;
3872 channel_->FillBitrateInfo(&bwe_info);
pbos@webrtc.org77e11bb2015-02-23 16:39:07 +00003873 // Assuming stream and stream2 corresponds to senders[0] and [1] respectively
3874 // is OK as std::maps are sorted and AddSendStream() gives increasing SSRCs.
3875 EXPECT_EQ(stats.media_bitrate_bps, info.senders[0].nominal_bitrate);
3876 EXPECT_EQ(stats2.media_bitrate_bps, info.senders[1].nominal_bitrate);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003877 EXPECT_EQ(stats.target_media_bitrate_bps + stats2.target_media_bitrate_bps,
stefanf79ade12017-06-02 06:44:03 -07003878 bwe_info.target_enc_bitrate);
pbos@webrtc.org77e11bb2015-02-23 16:39:07 +00003879 EXPECT_EQ(stats.media_bitrate_bps + stats2.media_bitrate_bps,
stefanf79ade12017-06-02 06:44:03 -07003880 bwe_info.actual_enc_bitrate);
3881 EXPECT_EQ(1 + 3 + 5 + 7, bwe_info.transmit_bitrate)
pbos@webrtc.org77e11bb2015-02-23 16:39:07 +00003882 << "Bandwidth stats should take all streams into account.";
stefanf79ade12017-06-02 06:44:03 -07003883 EXPECT_EQ(2 + 4 + 6 + 8, bwe_info.retransmit_bitrate)
pbos@webrtc.org77e11bb2015-02-23 16:39:07 +00003884 << "Bandwidth stats should take all streams into account.";
3885}
3886
eladalonf1841382017-06-12 01:16:46 -07003887TEST_F(WebRtcVideoChannelTest, DefaultReceiveStreamReconfiguresToUseRtx) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003888 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
pbos@webrtc.orga2a6fe62015-03-06 15:35:19 +00003889
Peter Boström0c4e06b2015-10-07 12:23:21 +02003890 const std::vector<uint32_t> ssrcs = MAKE_VECTOR(kSsrcs1);
3891 const std::vector<uint32_t> rtx_ssrcs = MAKE_VECTOR(kRtxSsrcs1);
pbos@webrtc.orga2a6fe62015-03-06 15:35:19 +00003892
3893 ASSERT_EQ(0u, fake_call_->GetVideoReceiveStreams().size());
3894 const size_t kDataLength = 12;
3895 uint8_t data[kDataLength];
3896 memset(data, 0, sizeof(data));
3897 rtc::SetBE32(&data[8], ssrcs[0]);
jbaucheec21bd2016-03-20 06:15:43 -07003898 rtc::CopyOnWriteBuffer packet(data, kDataLength);
pbos@webrtc.orga2a6fe62015-03-06 15:35:19 +00003899 rtc::PacketTime packet_time;
3900 channel_->OnPacketReceived(&packet, packet_time);
3901
3902 ASSERT_EQ(1u, fake_call_->GetVideoReceiveStreams().size())
3903 << "No default receive stream created.";
3904 FakeVideoReceiveStream* recv_stream = fake_call_->GetVideoReceiveStreams()[0];
brandtr14742122017-01-27 04:53:07 -08003905 EXPECT_EQ(0u, recv_stream->GetConfig().rtp.rtx_ssrc)
pbos@webrtc.orga2a6fe62015-03-06 15:35:19 +00003906 << "Default receive stream should not have configured RTX";
3907
3908 EXPECT_TRUE(channel_->AddRecvStream(
3909 cricket::CreateSimWithRtxStreamParams("cname", ssrcs, rtx_ssrcs)));
3910 ASSERT_EQ(1u, fake_call_->GetVideoReceiveStreams().size())
brandtr14742122017-01-27 04:53:07 -08003911 << "AddRecvStream should have reconfigured, not added a new receiver.";
pbos@webrtc.orga2a6fe62015-03-06 15:35:19 +00003912 recv_stream = fake_call_->GetVideoReceiveStreams()[0];
nisse26e3abb2017-08-25 04:44:25 -07003913 EXPECT_FALSE(
3914 recv_stream->GetConfig().rtp.rtx_associated_payload_types.empty());
nisseca5706d2017-09-11 02:32:16 -07003915 EXPECT_TRUE(VerifyRtxReceiveAssociations(recv_stream->GetConfig()))
Peter Boströmd8b01092016-05-12 16:44:36 +02003916 << "RTX should be mapped for all decoders/payload types.";
nisseca5706d2017-09-11 02:32:16 -07003917 EXPECT_TRUE(HasRtxReceiveAssociation(recv_stream->GetConfig(),
3918 GetEngineCodec("red").id))
3919 << "RTX should be mapped also for the RED payload type";
brandtr14742122017-01-27 04:53:07 -08003920 EXPECT_EQ(rtx_ssrcs[0], recv_stream->GetConfig().rtp.rtx_ssrc);
pbos@webrtc.orga2a6fe62015-03-06 15:35:19 +00003921}
3922
eladalonf1841382017-06-12 01:16:46 -07003923TEST_F(WebRtcVideoChannelTest, RejectsAddingStreamsWithMissingSsrcsForRtx) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003924 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
Peter Boströmd4362cd2015-03-25 14:17:23 +01003925
Peter Boström0c4e06b2015-10-07 12:23:21 +02003926 const std::vector<uint32_t> ssrcs = MAKE_VECTOR(kSsrcs1);
3927 const std::vector<uint32_t> rtx_ssrcs = MAKE_VECTOR(kRtxSsrcs1);
Peter Boströmd4362cd2015-03-25 14:17:23 +01003928
3929 StreamParams sp =
3930 cricket::CreateSimWithRtxStreamParams("cname", ssrcs, rtx_ssrcs);
3931 sp.ssrcs = ssrcs; // Without RTXs, this is the important part.
3932
3933 EXPECT_FALSE(channel_->AddSendStream(sp));
3934 EXPECT_FALSE(channel_->AddRecvStream(sp));
3935}
3936
eladalonf1841382017-06-12 01:16:46 -07003937TEST_F(WebRtcVideoChannelTest, RejectsAddingStreamsWithOverlappingRtxSsrcs) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003938 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
Peter Boströmd6f4c252015-03-26 16:23:04 +01003939
Peter Boström0c4e06b2015-10-07 12:23:21 +02003940 const std::vector<uint32_t> ssrcs = MAKE_VECTOR(kSsrcs1);
3941 const std::vector<uint32_t> rtx_ssrcs = MAKE_VECTOR(kRtxSsrcs1);
Peter Boströmd6f4c252015-03-26 16:23:04 +01003942
3943 StreamParams sp =
3944 cricket::CreateSimWithRtxStreamParams("cname", ssrcs, rtx_ssrcs);
3945
3946 EXPECT_TRUE(channel_->AddSendStream(sp));
3947 EXPECT_TRUE(channel_->AddRecvStream(sp));
3948
3949 // The RTX SSRC is already used in previous streams, using it should fail.
3950 sp = cricket::StreamParams::CreateLegacy(rtx_ssrcs[0]);
3951 EXPECT_FALSE(channel_->AddSendStream(sp));
3952 EXPECT_FALSE(channel_->AddRecvStream(sp));
3953
3954 // After removing the original stream this should be fine to add (makes sure
3955 // that RTX ssrcs are not forever taken).
3956 EXPECT_TRUE(channel_->RemoveSendStream(ssrcs[0]));
3957 EXPECT_TRUE(channel_->RemoveRecvStream(ssrcs[0]));
3958 EXPECT_TRUE(channel_->AddSendStream(sp));
3959 EXPECT_TRUE(channel_->AddRecvStream(sp));
3960}
3961
eladalonf1841382017-06-12 01:16:46 -07003962TEST_F(WebRtcVideoChannelTest,
Peter Boströmd6f4c252015-03-26 16:23:04 +01003963 RejectsAddingStreamsWithOverlappingSimulcastSsrcs) {
Peter Boström0c4e06b2015-10-07 12:23:21 +02003964 static const uint32_t kFirstStreamSsrcs[] = {1, 2, 3};
3965 static const uint32_t kOverlappingStreamSsrcs[] = {4, 3, 5};
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003966 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
Peter Boströmd6f4c252015-03-26 16:23:04 +01003967
Peter Boströmd6f4c252015-03-26 16:23:04 +01003968 StreamParams sp =
3969 cricket::CreateSimStreamParams("cname", MAKE_VECTOR(kFirstStreamSsrcs));
3970
3971 EXPECT_TRUE(channel_->AddSendStream(sp));
3972 EXPECT_TRUE(channel_->AddRecvStream(sp));
3973
3974 // One of the SSRCs is already used in previous streams, using it should fail.
3975 sp = cricket::CreateSimStreamParams("cname",
3976 MAKE_VECTOR(kOverlappingStreamSsrcs));
3977 EXPECT_FALSE(channel_->AddSendStream(sp));
3978 EXPECT_FALSE(channel_->AddRecvStream(sp));
3979
3980 // After removing the original stream this should be fine to add (makes sure
3981 // that RTX ssrcs are not forever taken).
Peter Boström3548dd22015-05-22 18:48:36 +02003982 EXPECT_TRUE(channel_->RemoveSendStream(kFirstStreamSsrcs[0]));
3983 EXPECT_TRUE(channel_->RemoveRecvStream(kFirstStreamSsrcs[0]));
Peter Boströmd6f4c252015-03-26 16:23:04 +01003984 EXPECT_TRUE(channel_->AddSendStream(sp));
3985 EXPECT_TRUE(channel_->AddRecvStream(sp));
3986}
3987
eladalonf1841382017-06-12 01:16:46 -07003988TEST_F(WebRtcVideoChannelTest, ReportsSsrcGroupsInStats) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003989 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
Peter Boström259bd202015-05-28 13:39:50 +02003990
3991 static const uint32_t kSenderSsrcs[] = {4, 7, 10};
3992 static const uint32_t kSenderRtxSsrcs[] = {5, 8, 11};
3993
3994 StreamParams sender_sp = cricket::CreateSimWithRtxStreamParams(
3995 "cname", MAKE_VECTOR(kSenderSsrcs), MAKE_VECTOR(kSenderRtxSsrcs));
3996
3997 EXPECT_TRUE(channel_->AddSendStream(sender_sp));
3998
3999 static const uint32_t kReceiverSsrcs[] = {3};
4000 static const uint32_t kReceiverRtxSsrcs[] = {2};
4001
4002 StreamParams receiver_sp = cricket::CreateSimWithRtxStreamParams(
4003 "cname", MAKE_VECTOR(kReceiverSsrcs), MAKE_VECTOR(kReceiverRtxSsrcs));
4004 EXPECT_TRUE(channel_->AddRecvStream(receiver_sp));
4005
4006 cricket::VideoMediaInfo info;
4007 ASSERT_TRUE(channel_->GetStats(&info));
4008
4009 ASSERT_EQ(1u, info.senders.size());
4010 ASSERT_EQ(1u, info.receivers.size());
4011
4012 EXPECT_NE(sender_sp.ssrc_groups, receiver_sp.ssrc_groups);
4013 EXPECT_EQ(sender_sp.ssrc_groups, info.senders[0].ssrc_groups);
4014 EXPECT_EQ(receiver_sp.ssrc_groups, info.receivers[0].ssrc_groups);
4015}
4016
eladalonf1841382017-06-12 01:16:46 -07004017TEST_F(WebRtcVideoChannelTest, MapsReceivedPayloadTypeToCodecName) {
pbosf42376c2015-08-28 07:35:32 -07004018 FakeVideoReceiveStream* stream = AddRecvStream();
4019 webrtc::VideoReceiveStream::Stats stats;
4020 cricket::VideoMediaInfo info;
4021
4022 // Report no codec name before receiving.
4023 stream->SetStats(stats);
4024 ASSERT_TRUE(channel_->GetStats(&info));
4025 EXPECT_STREQ("", info.receivers[0].codec_name.c_str());
4026
4027 // Report VP8 if we're receiving it.
magjed509e4fe2016-11-18 01:34:11 -08004028 stats.current_payload_type = GetEngineCodec("VP8").id;
pbosf42376c2015-08-28 07:35:32 -07004029 stream->SetStats(stats);
4030 ASSERT_TRUE(channel_->GetStats(&info));
4031 EXPECT_STREQ(kVp8CodecName, info.receivers[0].codec_name.c_str());
4032
4033 // Report no codec name for unknown playload types.
4034 stats.current_payload_type = 3;
4035 stream->SetStats(stats);
4036 ASSERT_TRUE(channel_->GetStats(&info));
4037 EXPECT_STREQ("", info.receivers[0].codec_name.c_str());
4038}
4039
eladalonf1841382017-06-12 01:16:46 -07004040void WebRtcVideoChannelTest::TestReceiveUnsignaledSsrcPacket(
noahricd10a68e2015-07-10 11:27:55 -07004041 uint8_t payload_type,
4042 bool expect_created_receive_stream) {
magjed509e4fe2016-11-18 01:34:11 -08004043 // kRedRtxPayloadType must currently be unused.
4044 EXPECT_FALSE(FindCodecById(engine_.codecs(), kRedRtxPayloadType));
4045
noahricd10a68e2015-07-10 11:27:55 -07004046 // Add a RED RTX codec.
4047 VideoCodec red_rtx_codec =
magjed509e4fe2016-11-18 01:34:11 -08004048 VideoCodec::CreateRtxCodec(kRedRtxPayloadType, GetEngineCodec("red").id);
Fredrik Solenbergb071a192015-09-17 16:42:56 +02004049 recv_parameters_.codecs.push_back(red_rtx_codec);
4050 EXPECT_TRUE(channel_->SetRecvParameters(recv_parameters_));
noahricd10a68e2015-07-10 11:27:55 -07004051
4052 ASSERT_EQ(0u, fake_call_->GetVideoReceiveStreams().size());
4053 const size_t kDataLength = 12;
4054 uint8_t data[kDataLength];
4055 memset(data, 0, sizeof(data));
4056
4057 rtc::Set8(data, 1, payload_type);
4058 rtc::SetBE32(&data[8], kIncomingUnsignalledSsrc);
jbaucheec21bd2016-03-20 06:15:43 -07004059 rtc::CopyOnWriteBuffer packet(data, kDataLength);
noahricd10a68e2015-07-10 11:27:55 -07004060 rtc::PacketTime packet_time;
4061 channel_->OnPacketReceived(&packet, packet_time);
4062
4063 if (expect_created_receive_stream) {
4064 EXPECT_EQ(1u, fake_call_->GetVideoReceiveStreams().size())
4065 << "Should have created a receive stream for payload type: "
4066 << payload_type;
4067 } else {
4068 EXPECT_EQ(0u, fake_call_->GetVideoReceiveStreams().size())
4069 << "Shouldn't have created a receive stream for payload type: "
4070 << payload_type;
4071 }
4072}
4073
eladalonf1841382017-06-12 01:16:46 -07004074TEST_F(WebRtcVideoChannelTest, Vp8PacketCreatesUnsignalledStream) {
magjed509e4fe2016-11-18 01:34:11 -08004075 TestReceiveUnsignaledSsrcPacket(GetEngineCodec("VP8").id,
4076 true /* expect_created_receive_stream */);
noahricd10a68e2015-07-10 11:27:55 -07004077}
4078
eladalonf1841382017-06-12 01:16:46 -07004079TEST_F(WebRtcVideoChannelTest, Vp9PacketCreatesUnsignalledStream) {
magjed509e4fe2016-11-18 01:34:11 -08004080 TestReceiveUnsignaledSsrcPacket(GetEngineCodec("VP9").id,
4081 true /* expect_created_receive_stream */);
noahricd10a68e2015-07-10 11:27:55 -07004082}
4083
eladalonf1841382017-06-12 01:16:46 -07004084TEST_F(WebRtcVideoChannelTest, RtxPacketDoesntCreateUnsignalledStream) {
magjed509e4fe2016-11-18 01:34:11 -08004085 const cricket::VideoCodec vp8 = GetEngineCodec("VP8");
4086 const int rtx_vp8_payload_type = default_apt_rtx_types_[vp8.id];
4087 TestReceiveUnsignaledSsrcPacket(rtx_vp8_payload_type,
4088 false /* expect_created_receive_stream */);
noahricd10a68e2015-07-10 11:27:55 -07004089}
4090
eladalonf1841382017-06-12 01:16:46 -07004091TEST_F(WebRtcVideoChannelTest, UlpfecPacketDoesntCreateUnsignalledStream) {
magjed509e4fe2016-11-18 01:34:11 -08004092 TestReceiveUnsignaledSsrcPacket(GetEngineCodec("ulpfec").id,
4093 false /* expect_created_receive_stream */);
noahricd10a68e2015-07-10 11:27:55 -07004094}
4095
eladalonf1841382017-06-12 01:16:46 -07004096TEST_F(WebRtcVideoChannelFlexfecRecvTest,
brandtr468da7c2016-11-22 02:16:47 -08004097 FlexfecPacketDoesntCreateUnsignalledStream) {
4098 TestReceiveUnsignaledSsrcPacket(GetEngineCodec("flexfec-03").id,
4099 false /* expect_created_receive_stream */);
4100}
4101
eladalonf1841382017-06-12 01:16:46 -07004102TEST_F(WebRtcVideoChannelTest, RedRtxPacketDoesntCreateUnsignalledStream) {
magjed509e4fe2016-11-18 01:34:11 -08004103 TestReceiveUnsignaledSsrcPacket(kRedRtxPayloadType,
4104 false /* expect_created_receive_stream */);
noahricd10a68e2015-07-10 11:27:55 -07004105}
4106
mzanaty8a855d62017-02-17 15:46:43 -08004107// Test that receiving any unsignalled SSRC works even if it changes.
4108// The first unsignalled SSRC received will create a default receive stream.
4109// Any different unsignalled SSRC received will replace the default.
eladalonf1841382017-06-12 01:16:46 -07004110TEST_F(WebRtcVideoChannelTest, ReceiveDifferentUnsignaledSsrc) {
mzanaty8a855d62017-02-17 15:46:43 -08004111 // Allow receiving VP8, VP9, H264 (if enabled).
4112 cricket::VideoRecvParameters parameters;
4113 parameters.codecs.push_back(GetEngineCodec("VP8"));
4114 parameters.codecs.push_back(GetEngineCodec("VP9"));
4115
4116#if defined(WEBRTC_USE_H264)
4117 cricket::VideoCodec H264codec(126, "H264");
4118 parameters.codecs.push_back(H264codec);
4119#endif
4120
4121 EXPECT_TRUE(channel_->SetRecvParameters(parameters));
4122 // No receive streams yet.
4123 ASSERT_EQ(0u, fake_call_->GetVideoReceiveStreams().size());
4124 cricket::FakeVideoRenderer renderer;
4125 EXPECT_TRUE(channel_->SetSink(kDefaultRecvSsrc, &renderer));
4126
4127 // Receive VP8 packet on first SSRC.
4128 uint8_t data[kMinRtpPacketLen];
4129 cricket::RtpHeader rtpHeader;
4130 rtpHeader.payload_type = GetEngineCodec("VP8").id;
4131 rtpHeader.seq_num = rtpHeader.timestamp = 0;
4132 rtpHeader.ssrc = kIncomingUnsignalledSsrc+1;
4133 cricket::SetRtpHeader(data, sizeof(data), rtpHeader);
4134 rtc::CopyOnWriteBuffer packet(data, sizeof(data));
4135 rtc::PacketTime packet_time;
4136 channel_->OnPacketReceived(&packet, packet_time);
4137 // VP8 packet should create default receive stream.
4138 ASSERT_EQ(1u, fake_call_->GetVideoReceiveStreams().size());
4139 FakeVideoReceiveStream* recv_stream =
4140 fake_call_->GetVideoReceiveStreams()[0];
4141 EXPECT_EQ(rtpHeader.ssrc, recv_stream->GetConfig().rtp.remote_ssrc);
4142 // Verify that the receive stream sinks to a renderer.
4143 webrtc::VideoFrame video_frame(CreateBlackFrameBuffer(4, 4), 100, 0,
4144 webrtc::kVideoRotation_0);
4145 recv_stream->InjectFrame(video_frame);
4146 EXPECT_EQ(1, renderer.num_rendered_frames());
4147
4148 // Receive VP9 packet on second SSRC.
4149 rtpHeader.payload_type = GetEngineCodec("VP9").id;
4150 rtpHeader.ssrc = kIncomingUnsignalledSsrc+2;
4151 cricket::SetRtpHeader(data, sizeof(data), rtpHeader);
4152 rtc::CopyOnWriteBuffer packet2(data, sizeof(data));
4153 channel_->OnPacketReceived(&packet2, packet_time);
4154 // VP9 packet should replace the default receive SSRC.
4155 ASSERT_EQ(1u, fake_call_->GetVideoReceiveStreams().size());
4156 recv_stream = fake_call_->GetVideoReceiveStreams()[0];
4157 EXPECT_EQ(rtpHeader.ssrc, recv_stream->GetConfig().rtp.remote_ssrc);
4158 // Verify that the receive stream sinks to a renderer.
4159 webrtc::VideoFrame video_frame2(CreateBlackFrameBuffer(4, 4), 200, 0,
ilnik00d802b2017-04-11 10:34:31 -07004160 webrtc::kVideoRotation_0);
mzanaty8a855d62017-02-17 15:46:43 -08004161 recv_stream->InjectFrame(video_frame2);
4162 EXPECT_EQ(2, renderer.num_rendered_frames());
4163
4164#if defined(WEBRTC_USE_H264)
4165 // Receive H264 packet on third SSRC.
4166 rtpHeader.payload_type = 126;
4167 rtpHeader.ssrc = kIncomingUnsignalledSsrc+3;
4168 cricket::SetRtpHeader(data, sizeof(data), rtpHeader);
4169 rtc::CopyOnWriteBuffer packet3(data, sizeof(data));
4170 channel_->OnPacketReceived(&packet3, packet_time);
4171 // H264 packet should replace the default receive SSRC.
4172 ASSERT_EQ(1u, fake_call_->GetVideoReceiveStreams().size());
4173 recv_stream = fake_call_->GetVideoReceiveStreams()[0];
4174 EXPECT_EQ(rtpHeader.ssrc, recv_stream->GetConfig().rtp.remote_ssrc);
4175 // Verify that the receive stream sinks to a renderer.
4176 webrtc::VideoFrame video_frame3(CreateBlackFrameBuffer(4, 4), 300, 0,
ilnik00d802b2017-04-11 10:34:31 -07004177 webrtc::kVideoRotation_0);
mzanaty8a855d62017-02-17 15:46:43 -08004178 recv_stream->InjectFrame(video_frame3);
4179 EXPECT_EQ(3, renderer.num_rendered_frames());
4180#endif
4181}
4182
brandtr0dc57ea2017-05-29 23:33:31 -07004183// This test verifies that when a new default stream is created for a new
4184// unsignaled SSRC, the new stream does not overwrite any old stream that had
4185// been the default receive stream before being properly signaled.
eladalonf1841382017-06-12 01:16:46 -07004186TEST_F(WebRtcVideoChannelTest,
brandtr0dc57ea2017-05-29 23:33:31 -07004187 NewUnsignaledStreamDoesNotDestroyPreviouslyUnsignaledStream) {
4188 cricket::VideoRecvParameters parameters;
4189 parameters.codecs.push_back(GetEngineCodec("VP8"));
4190 ASSERT_TRUE(channel_->SetRecvParameters(parameters));
4191
4192 // No streams signaled and no packets received, so we should not have any
4193 // stream objects created yet.
4194 EXPECT_EQ(0u, fake_call_->GetVideoReceiveStreams().size());
4195
4196 // Receive packet on an unsignaled SSRC.
4197 uint8_t data[kMinRtpPacketLen];
4198 cricket::RtpHeader rtp_header;
4199 rtp_header.payload_type = GetEngineCodec("VP8").id;
4200 rtp_header.seq_num = rtp_header.timestamp = 0;
4201 rtp_header.ssrc = kSsrcs3[0];
4202 cricket::SetRtpHeader(data, sizeof(data), rtp_header);
4203 rtc::CopyOnWriteBuffer packet(data, sizeof(data));
4204 rtc::PacketTime packet_time;
4205 channel_->OnPacketReceived(&packet, packet_time);
4206 // Default receive stream should be created.
4207 ASSERT_EQ(1u, fake_call_->GetVideoReceiveStreams().size());
4208 FakeVideoReceiveStream* recv_stream0 =
4209 fake_call_->GetVideoReceiveStreams()[0];
4210 EXPECT_EQ(kSsrcs3[0], recv_stream0->GetConfig().rtp.remote_ssrc);
4211
4212 // Signal the SSRC.
4213 EXPECT_TRUE(
4214 channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(kSsrcs3[0])));
4215 ASSERT_EQ(1u, fake_call_->GetVideoReceiveStreams().size());
4216 recv_stream0 = fake_call_->GetVideoReceiveStreams()[0];
4217 EXPECT_EQ(kSsrcs3[0], recv_stream0->GetConfig().rtp.remote_ssrc);
4218
4219 // Receive packet on a different unsignaled SSRC.
4220 rtp_header.ssrc = kSsrcs3[1];
4221 cricket::SetRtpHeader(data, sizeof(data), rtp_header);
4222 packet.SetData(data, sizeof(data));
4223 channel_->OnPacketReceived(&packet, packet_time);
4224 // New default receive stream should be created, but old stream should remain.
4225 ASSERT_EQ(2u, fake_call_->GetVideoReceiveStreams().size());
4226 EXPECT_EQ(recv_stream0, fake_call_->GetVideoReceiveStreams()[0]);
4227 FakeVideoReceiveStream* recv_stream1 =
4228 fake_call_->GetVideoReceiveStreams()[1];
4229 EXPECT_EQ(kSsrcs3[1], recv_stream1->GetConfig().rtp.remote_ssrc);
4230}
4231
eladalonf1841382017-06-12 01:16:46 -07004232TEST_F(WebRtcVideoChannelTest, CanSentMaxBitrateForExistingStream) {
skvladdc1c62c2016-03-16 19:07:43 -07004233 AddSendStream();
4234
4235 cricket::FakeVideoCapturer capturer;
deadbeef5a4a75a2016-06-02 16:23:38 -07004236 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, &capturer));
skvladdc1c62c2016-03-16 19:07:43 -07004237 cricket::VideoFormat capture_format_hd =
4238 capturer.GetSupportedFormats()->front();
4239 EXPECT_EQ(1280, capture_format_hd.width);
4240 EXPECT_EQ(720, capture_format_hd.height);
4241 EXPECT_EQ(cricket::CS_RUNNING, capturer.Start(capture_format_hd));
4242 EXPECT_TRUE(channel_->SetSend(true));
perkjfa10b552016-10-02 23:45:26 -07004243 capturer.CaptureFrame();
skvladdc1c62c2016-03-16 19:07:43 -07004244
perkjfa10b552016-10-02 23:45:26 -07004245 int default_encoder_bitrate = GetMaxEncoderBitrate();
brandtr468da7c2016-11-22 02:16:47 -08004246 EXPECT_GT(default_encoder_bitrate, 1000);
skvladdc1c62c2016-03-16 19:07:43 -07004247
4248 // TODO(skvlad): Resolve the inconsistency between the interpretation
4249 // of the global bitrate limit for audio and video:
4250 // - Audio: max_bandwidth_bps = 0 - fail the operation,
4251 // max_bandwidth_bps = -1 - remove the bandwidth limit
4252 // - Video: max_bandwidth_bps = 0 - remove the bandwidth limit,
pbos5c7760a2017-03-10 11:23:12 -08004253 // max_bandwidth_bps = -1 - remove the bandwidth limit
skvladdc1c62c2016-03-16 19:07:43 -07004254
perkjfa10b552016-10-02 23:45:26 -07004255 SetAndExpectMaxBitrate(1000, 0, 1000);
4256 SetAndExpectMaxBitrate(1000, 800, 800);
4257 SetAndExpectMaxBitrate(600, 800, 600);
4258 SetAndExpectMaxBitrate(0, 800, 800);
4259 SetAndExpectMaxBitrate(0, 0, default_encoder_bitrate);
skvladdc1c62c2016-03-16 19:07:43 -07004260
deadbeef5a4a75a2016-06-02 16:23:38 -07004261 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, nullptr));
skvladdc1c62c2016-03-16 19:07:43 -07004262}
4263
eladalonf1841382017-06-12 01:16:46 -07004264TEST_F(WebRtcVideoChannelTest, CannotSetMaxBitrateForNonexistentStream) {
skvladdc1c62c2016-03-16 19:07:43 -07004265 webrtc::RtpParameters nonexistent_parameters =
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07004266 channel_->GetRtpSendParameters(last_ssrc_);
skvladdc1c62c2016-03-16 19:07:43 -07004267 EXPECT_EQ(0, nonexistent_parameters.encodings.size());
4268
4269 nonexistent_parameters.encodings.push_back(webrtc::RtpEncodingParameters());
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07004270 EXPECT_FALSE(
4271 channel_->SetRtpSendParameters(last_ssrc_, nonexistent_parameters));
skvladdc1c62c2016-03-16 19:07:43 -07004272}
4273
eladalonf1841382017-06-12 01:16:46 -07004274TEST_F(WebRtcVideoChannelTest,
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07004275 CannotSetRtpSendParametersWithIncorrectNumberOfEncodings) {
skvladdc1c62c2016-03-16 19:07:43 -07004276 // This test verifies that setting RtpParameters succeeds only if
4277 // the structure contains exactly one encoding.
deadbeefdbe2b872016-03-22 15:42:00 -07004278 // TODO(skvlad): Update this test when we start supporting setting parameters
skvladdc1c62c2016-03-16 19:07:43 -07004279 // for each encoding individually.
4280
4281 AddSendStream();
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07004282 webrtc::RtpParameters parameters = channel_->GetRtpSendParameters(last_ssrc_);
skvladdc1c62c2016-03-16 19:07:43 -07004283 // Two or more encodings should result in failure.
4284 parameters.encodings.push_back(webrtc::RtpEncodingParameters());
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07004285 EXPECT_FALSE(channel_->SetRtpSendParameters(last_ssrc_, parameters));
deadbeeffb2aced2017-01-06 23:05:37 -08004286 // Zero encodings should also fail.
4287 parameters.encodings.clear();
4288 EXPECT_FALSE(channel_->SetRtpSendParameters(last_ssrc_, parameters));
4289}
4290
4291// Changing the SSRC through RtpParameters is not allowed.
eladalonf1841382017-06-12 01:16:46 -07004292TEST_F(WebRtcVideoChannelTest, CannotSetSsrcInRtpSendParameters) {
deadbeeffb2aced2017-01-06 23:05:37 -08004293 AddSendStream();
4294 webrtc::RtpParameters parameters = channel_->GetRtpSendParameters(last_ssrc_);
4295 parameters.encodings[0].ssrc = rtc::Optional<uint32_t>(0xdeadbeef);
4296 EXPECT_FALSE(channel_->SetRtpSendParameters(last_ssrc_, parameters));
skvladdc1c62c2016-03-16 19:07:43 -07004297}
4298
Taylor Brandstetter14b9d792016-09-07 17:16:54 -07004299// Test that a stream will not be sending if its encoding is made inactive
4300// through SetRtpSendParameters.
deadbeefdbe2b872016-03-22 15:42:00 -07004301// TODO(deadbeef): Update this test when we start supporting setting parameters
4302// for each encoding individually.
eladalonf1841382017-06-12 01:16:46 -07004303TEST_F(WebRtcVideoChannelTest, SetRtpSendParametersEncodingsActive) {
deadbeefdbe2b872016-03-22 15:42:00 -07004304 FakeVideoSendStream* stream = AddSendStream();
4305 EXPECT_TRUE(channel_->SetSend(true));
4306 EXPECT_TRUE(stream->IsSending());
4307
4308 // Get current parameters and change "active" to false.
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07004309 webrtc::RtpParameters parameters = channel_->GetRtpSendParameters(last_ssrc_);
deadbeefdbe2b872016-03-22 15:42:00 -07004310 ASSERT_EQ(1u, parameters.encodings.size());
4311 ASSERT_TRUE(parameters.encodings[0].active);
4312 parameters.encodings[0].active = false;
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07004313 EXPECT_TRUE(channel_->SetRtpSendParameters(last_ssrc_, parameters));
deadbeefdbe2b872016-03-22 15:42:00 -07004314 EXPECT_FALSE(stream->IsSending());
4315
4316 // Now change it back to active and verify we resume sending.
4317 parameters.encodings[0].active = true;
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07004318 EXPECT_TRUE(channel_->SetRtpSendParameters(last_ssrc_, parameters));
deadbeefdbe2b872016-03-22 15:42:00 -07004319 EXPECT_TRUE(stream->IsSending());
4320}
4321
Taylor Brandstetter14b9d792016-09-07 17:16:54 -07004322// Test that if a stream is reconfigured (due to a codec change or other
4323// change) while its encoding is still inactive, it doesn't start sending.
eladalonf1841382017-06-12 01:16:46 -07004324TEST_F(WebRtcVideoChannelTest,
Taylor Brandstetter14b9d792016-09-07 17:16:54 -07004325 InactiveStreamDoesntStartSendingWhenReconfigured) {
4326 // Set an initial codec list, which will be modified later.
4327 cricket::VideoSendParameters parameters1;
magjed509e4fe2016-11-18 01:34:11 -08004328 parameters1.codecs.push_back(GetEngineCodec("VP8"));
4329 parameters1.codecs.push_back(GetEngineCodec("VP9"));
Taylor Brandstetter14b9d792016-09-07 17:16:54 -07004330 EXPECT_TRUE(channel_->SetSendParameters(parameters1));
4331
4332 FakeVideoSendStream* stream = AddSendStream();
4333 EXPECT_TRUE(channel_->SetSend(true));
4334 EXPECT_TRUE(stream->IsSending());
4335
4336 // Get current parameters and change "active" to false.
4337 webrtc::RtpParameters parameters = channel_->GetRtpSendParameters(last_ssrc_);
4338 ASSERT_EQ(1u, parameters.encodings.size());
4339 ASSERT_TRUE(parameters.encodings[0].active);
4340 parameters.encodings[0].active = false;
4341 EXPECT_EQ(1u, GetFakeSendStreams().size());
4342 EXPECT_EQ(1, fake_call_->GetNumCreatedSendStreams());
4343 EXPECT_TRUE(channel_->SetRtpSendParameters(last_ssrc_, parameters));
4344 EXPECT_FALSE(stream->IsSending());
4345
4346 // Reorder the codec list, causing the stream to be reconfigured.
4347 cricket::VideoSendParameters parameters2;
magjed509e4fe2016-11-18 01:34:11 -08004348 parameters2.codecs.push_back(GetEngineCodec("VP9"));
4349 parameters2.codecs.push_back(GetEngineCodec("VP8"));
Taylor Brandstetter14b9d792016-09-07 17:16:54 -07004350 EXPECT_TRUE(channel_->SetSendParameters(parameters2));
4351 auto new_streams = GetFakeSendStreams();
4352 // Assert that a new underlying stream was created due to the codec change.
4353 // Otherwise, this test isn't testing what it set out to test.
4354 EXPECT_EQ(1u, GetFakeSendStreams().size());
4355 EXPECT_EQ(2, fake_call_->GetNumCreatedSendStreams());
4356
4357 // Verify that we still are not sending anything, due to the inactive
4358 // encoding.
4359 EXPECT_FALSE(new_streams[0]->IsSending());
4360}
4361
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07004362// Test that GetRtpSendParameters returns the currently configured codecs.
eladalonf1841382017-06-12 01:16:46 -07004363TEST_F(WebRtcVideoChannelTest, GetRtpSendParametersCodecs) {
Taylor Brandstetter0cd086b2016-04-20 16:23:10 -07004364 AddSendStream();
4365 cricket::VideoSendParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08004366 parameters.codecs.push_back(GetEngineCodec("VP8"));
4367 parameters.codecs.push_back(GetEngineCodec("VP9"));
Taylor Brandstetter0cd086b2016-04-20 16:23:10 -07004368 EXPECT_TRUE(channel_->SetSendParameters(parameters));
4369
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07004370 webrtc::RtpParameters rtp_parameters =
4371 channel_->GetRtpSendParameters(last_ssrc_);
Taylor Brandstetter0cd086b2016-04-20 16:23:10 -07004372 ASSERT_EQ(2u, rtp_parameters.codecs.size());
magjed509e4fe2016-11-18 01:34:11 -08004373 EXPECT_EQ(GetEngineCodec("VP8").ToCodecParameters(),
4374 rtp_parameters.codecs[0]);
4375 EXPECT_EQ(GetEngineCodec("VP9").ToCodecParameters(),
4376 rtp_parameters.codecs[1]);
Taylor Brandstetter0cd086b2016-04-20 16:23:10 -07004377}
4378
deadbeeffb2aced2017-01-06 23:05:37 -08004379// Test that RtpParameters for send stream has one encoding and it has
4380// the correct SSRC.
eladalonf1841382017-06-12 01:16:46 -07004381TEST_F(WebRtcVideoChannelTest, GetRtpSendParametersSsrc) {
deadbeeffb2aced2017-01-06 23:05:37 -08004382 AddSendStream();
4383
4384 webrtc::RtpParameters rtp_parameters =
4385 channel_->GetRtpSendParameters(last_ssrc_);
4386 ASSERT_EQ(1u, rtp_parameters.encodings.size());
4387 EXPECT_EQ(rtc::Optional<uint32_t>(last_ssrc_),
4388 rtp_parameters.encodings[0].ssrc);
4389}
4390
Taylor Brandstetter0cd086b2016-04-20 16:23:10 -07004391// Test that if we set/get parameters multiple times, we get the same results.
eladalonf1841382017-06-12 01:16:46 -07004392TEST_F(WebRtcVideoChannelTest, SetAndGetRtpSendParameters) {
Taylor Brandstetter0cd086b2016-04-20 16:23:10 -07004393 AddSendStream();
4394 cricket::VideoSendParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08004395 parameters.codecs.push_back(GetEngineCodec("VP8"));
4396 parameters.codecs.push_back(GetEngineCodec("VP9"));
Taylor Brandstetter0cd086b2016-04-20 16:23:10 -07004397 EXPECT_TRUE(channel_->SetSendParameters(parameters));
4398
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07004399 webrtc::RtpParameters initial_params =
4400 channel_->GetRtpSendParameters(last_ssrc_);
Taylor Brandstetter0cd086b2016-04-20 16:23:10 -07004401
4402 // We should be able to set the params we just got.
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07004403 EXPECT_TRUE(channel_->SetRtpSendParameters(last_ssrc_, initial_params));
Taylor Brandstetter0cd086b2016-04-20 16:23:10 -07004404
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07004405 // ... And this shouldn't change the params returned by GetRtpSendParameters.
4406 EXPECT_EQ(initial_params, channel_->GetRtpSendParameters(last_ssrc_));
4407}
4408
4409// Test that GetRtpReceiveParameters returns the currently configured codecs.
eladalonf1841382017-06-12 01:16:46 -07004410TEST_F(WebRtcVideoChannelTest, GetRtpReceiveParametersCodecs) {
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07004411 AddRecvStream();
4412 cricket::VideoRecvParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08004413 parameters.codecs.push_back(GetEngineCodec("VP8"));
4414 parameters.codecs.push_back(GetEngineCodec("VP9"));
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07004415 EXPECT_TRUE(channel_->SetRecvParameters(parameters));
4416
4417 webrtc::RtpParameters rtp_parameters =
4418 channel_->GetRtpReceiveParameters(last_ssrc_);
4419 ASSERT_EQ(2u, rtp_parameters.codecs.size());
magjed509e4fe2016-11-18 01:34:11 -08004420 EXPECT_EQ(GetEngineCodec("VP8").ToCodecParameters(),
4421 rtp_parameters.codecs[0]);
4422 EXPECT_EQ(GetEngineCodec("VP9").ToCodecParameters(),
4423 rtp_parameters.codecs[1]);
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07004424}
4425
johan073ece42016-08-26 02:59:47 -07004426#if defined(WEBRTC_USE_H264)
eladalonf1841382017-06-12 01:16:46 -07004427TEST_F(WebRtcVideoChannelTest, GetRtpReceiveFmtpSprop) {
johan073ece42016-08-26 02:59:47 -07004428#else
eladalonf1841382017-06-12 01:16:46 -07004429TEST_F(WebRtcVideoChannelTest, DISABLED_GetRtpReceiveFmtpSprop) {
johan073ece42016-08-26 02:59:47 -07004430#endif
johan3859c892016-08-05 09:19:25 -07004431 cricket::VideoRecvParameters parameters;
perkj26752742016-10-24 01:21:16 -07004432 cricket::VideoCodec kH264sprop1(101, "H264");
magjed5dfac562016-11-25 03:56:37 -08004433 kH264sprop1.SetParam(kH264FmtpSpropParameterSets, "uvw");
johan3859c892016-08-05 09:19:25 -07004434 parameters.codecs.push_back(kH264sprop1);
perkj26752742016-10-24 01:21:16 -07004435 cricket::VideoCodec kH264sprop2(102, "H264");
magjed5dfac562016-11-25 03:56:37 -08004436 kH264sprop2.SetParam(kH264FmtpSpropParameterSets, "xyz");
johan3859c892016-08-05 09:19:25 -07004437 parameters.codecs.push_back(kH264sprop2);
4438 EXPECT_TRUE(channel_->SetRecvParameters(parameters));
4439
4440 FakeVideoReceiveStream* recv_stream = AddRecvStream();
4441 const webrtc::VideoReceiveStream::Config& cfg = recv_stream->GetConfig();
4442 webrtc::RtpParameters rtp_parameters =
4443 channel_->GetRtpReceiveParameters(last_ssrc_);
4444 ASSERT_EQ(2u, rtp_parameters.codecs.size());
4445 EXPECT_EQ(kH264sprop1.ToCodecParameters(), rtp_parameters.codecs[0]);
4446 ASSERT_EQ(2u, cfg.decoders.size());
4447 EXPECT_EQ(101, cfg.decoders[0].payload_type);
4448 EXPECT_EQ("H264", cfg.decoders[0].payload_name);
magjed5dfac562016-11-25 03:56:37 -08004449 const auto it0 =
4450 cfg.decoders[0].codec_params.find(kH264FmtpSpropParameterSets);
4451 ASSERT_TRUE(it0 != cfg.decoders[0].codec_params.end());
4452 EXPECT_EQ("uvw", it0->second);
johan3859c892016-08-05 09:19:25 -07004453
4454 EXPECT_EQ(102, cfg.decoders[1].payload_type);
4455 EXPECT_EQ("H264", cfg.decoders[1].payload_name);
magjed5dfac562016-11-25 03:56:37 -08004456 const auto it1 =
4457 cfg.decoders[1].codec_params.find(kH264FmtpSpropParameterSets);
4458 ASSERT_TRUE(it1 != cfg.decoders[1].codec_params.end());
4459 EXPECT_EQ("xyz", it1->second);
johan3859c892016-08-05 09:19:25 -07004460}
4461
sakal1fd95952016-06-22 00:46:15 -07004462// Test that RtpParameters for receive stream has one encoding and it has
4463// the correct SSRC.
eladalonf1841382017-06-12 01:16:46 -07004464TEST_F(WebRtcVideoChannelTest, GetRtpReceiveParametersSsrc) {
sakal1fd95952016-06-22 00:46:15 -07004465 AddRecvStream();
4466
4467 webrtc::RtpParameters rtp_parameters =
4468 channel_->GetRtpReceiveParameters(last_ssrc_);
4469 ASSERT_EQ(1u, rtp_parameters.encodings.size());
4470 EXPECT_EQ(rtc::Optional<uint32_t>(last_ssrc_),
4471 rtp_parameters.encodings[0].ssrc);
4472}
4473
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07004474// Test that if we set/get parameters multiple times, we get the same results.
eladalonf1841382017-06-12 01:16:46 -07004475TEST_F(WebRtcVideoChannelTest, SetAndGetRtpReceiveParameters) {
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07004476 AddRecvStream();
4477 cricket::VideoRecvParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08004478 parameters.codecs.push_back(GetEngineCodec("VP8"));
4479 parameters.codecs.push_back(GetEngineCodec("VP9"));
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07004480 EXPECT_TRUE(channel_->SetRecvParameters(parameters));
4481
4482 webrtc::RtpParameters initial_params =
4483 channel_->GetRtpReceiveParameters(last_ssrc_);
4484
4485 // We should be able to set the params we just got.
4486 EXPECT_TRUE(channel_->SetRtpReceiveParameters(last_ssrc_, initial_params));
4487
4488 // ... And this shouldn't change the params returned by
4489 // GetRtpReceiveParameters.
4490 EXPECT_EQ(initial_params, channel_->GetRtpReceiveParameters(last_ssrc_));
Taylor Brandstetter0cd086b2016-04-20 16:23:10 -07004491}
4492
deadbeef3bc15102017-04-20 19:25:07 -07004493// Test that GetRtpReceiveParameters returns parameters correctly when SSRCs
4494// aren't signaled. It should always return an empty "RtpEncodingParameters",
4495// even after a packet is received and the unsignaled SSRC is known.
eladalonf1841382017-06-12 01:16:46 -07004496TEST_F(WebRtcVideoChannelTest, GetRtpReceiveParametersWithUnsignaledSsrc) {
deadbeef3bc15102017-04-20 19:25:07 -07004497 // Call necessary methods to configure receiving a default stream as
4498 // soon as it arrives.
4499 cricket::VideoRecvParameters parameters;
4500 parameters.codecs.push_back(GetEngineCodec("VP8"));
4501 parameters.codecs.push_back(GetEngineCodec("VP9"));
4502 EXPECT_TRUE(channel_->SetRecvParameters(parameters));
4503
4504 // Call GetRtpReceiveParameters before configured to receive an unsignaled
4505 // stream. Should return nothing.
4506 EXPECT_EQ(webrtc::RtpParameters(), channel_->GetRtpReceiveParameters(0));
4507
4508 // Set a sink for an unsignaled stream.
4509 cricket::FakeVideoRenderer renderer;
4510 // Value of "0" means "unsignaled stream".
4511 EXPECT_TRUE(channel_->SetSink(0, &renderer));
4512
4513 // Call GetRtpReceiveParameters before the SSRC is known. Value of "0"
4514 // in this method means "unsignaled stream".
4515 webrtc::RtpParameters rtp_parameters = channel_->GetRtpReceiveParameters(0);
4516 ASSERT_EQ(1u, rtp_parameters.encodings.size());
4517 EXPECT_FALSE(rtp_parameters.encodings[0].ssrc);
4518
4519 // Receive VP8 packet.
4520 uint8_t data[kMinRtpPacketLen];
4521 cricket::RtpHeader rtpHeader;
4522 rtpHeader.payload_type = GetEngineCodec("VP8").id;
4523 rtpHeader.seq_num = rtpHeader.timestamp = 0;
4524 rtpHeader.ssrc = kIncomingUnsignalledSsrc;
4525 cricket::SetRtpHeader(data, sizeof(data), rtpHeader);
4526 rtc::CopyOnWriteBuffer packet(data, sizeof(data));
4527 rtc::PacketTime packet_time;
4528 channel_->OnPacketReceived(&packet, packet_time);
4529
4530 // The |ssrc| member should still be unset.
4531 rtp_parameters = channel_->GetRtpReceiveParameters(0);
4532 ASSERT_EQ(1u, rtp_parameters.encodings.size());
4533 EXPECT_FALSE(rtp_parameters.encodings[0].ssrc);
4534}
4535
eladalonf1841382017-06-12 01:16:46 -07004536void WebRtcVideoChannelTest::TestReceiverLocalSsrcConfiguration(
Peter Boström3548dd22015-05-22 18:48:36 +02004537 bool receiver_first) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02004538 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
Peter Boström3548dd22015-05-22 18:48:36 +02004539
4540 const uint32_t kSenderSsrc = 0xC0FFEE;
Peter Boströmdfa28152015-10-21 17:21:10 +02004541 const uint32_t kSecondSenderSsrc = 0xBADCAFE;
Peter Boström3548dd22015-05-22 18:48:36 +02004542 const uint32_t kReceiverSsrc = 0x4711;
Peter Boströmdfa28152015-10-21 17:21:10 +02004543 const uint32_t kExpectedDefaultReceiverSsrc = 1;
Peter Boström3548dd22015-05-22 18:48:36 +02004544
4545 if (receiver_first) {
4546 AddRecvStream(StreamParams::CreateLegacy(kReceiverSsrc));
4547 std::vector<FakeVideoReceiveStream*> receive_streams =
4548 fake_call_->GetVideoReceiveStreams();
4549 ASSERT_EQ(1u, receive_streams.size());
Peter Boströmdfa28152015-10-21 17:21:10 +02004550 // Default local SSRC when we have no sender.
4551 EXPECT_EQ(kExpectedDefaultReceiverSsrc,
4552 receive_streams[0]->GetConfig().rtp.local_ssrc);
Peter Boström3548dd22015-05-22 18:48:36 +02004553 }
4554 AddSendStream(StreamParams::CreateLegacy(kSenderSsrc));
4555 if (!receiver_first)
4556 AddRecvStream(StreamParams::CreateLegacy(kReceiverSsrc));
4557 std::vector<FakeVideoReceiveStream*> receive_streams =
4558 fake_call_->GetVideoReceiveStreams();
4559 ASSERT_EQ(1u, receive_streams.size());
4560 EXPECT_EQ(kSenderSsrc, receive_streams[0]->GetConfig().rtp.local_ssrc);
Peter Boströmdfa28152015-10-21 17:21:10 +02004561
4562 // Removing first sender should fall back to another (in this case the second)
4563 // local send stream's SSRC.
4564 AddSendStream(StreamParams::CreateLegacy(kSecondSenderSsrc));
4565 ASSERT_TRUE(channel_->RemoveSendStream(kSenderSsrc));
4566 receive_streams =
4567 fake_call_->GetVideoReceiveStreams();
4568 ASSERT_EQ(1u, receive_streams.size());
4569 EXPECT_EQ(kSecondSenderSsrc, receive_streams[0]->GetConfig().rtp.local_ssrc);
4570
4571 // Removing the last sender should fall back to default local SSRC.
4572 ASSERT_TRUE(channel_->RemoveSendStream(kSecondSenderSsrc));
4573 receive_streams =
4574 fake_call_->GetVideoReceiveStreams();
4575 ASSERT_EQ(1u, receive_streams.size());
4576 EXPECT_EQ(kExpectedDefaultReceiverSsrc,
4577 receive_streams[0]->GetConfig().rtp.local_ssrc);
Peter Boström3548dd22015-05-22 18:48:36 +02004578}
4579
eladalonf1841382017-06-12 01:16:46 -07004580TEST_F(WebRtcVideoChannelTest, ConfiguresLocalSsrc) {
Peter Boström3548dd22015-05-22 18:48:36 +02004581 TestReceiverLocalSsrcConfiguration(false);
4582}
4583
eladalonf1841382017-06-12 01:16:46 -07004584TEST_F(WebRtcVideoChannelTest, ConfiguresLocalSsrcOnExistingReceivers) {
Peter Boström3548dd22015-05-22 18:48:36 +02004585 TestReceiverLocalSsrcConfiguration(true);
4586}
4587
eladalonf1841382017-06-12 01:16:46 -07004588class WebRtcVideoChannelSimulcastTest : public testing::Test {
buildbot@webrtc.orga8530772014-12-10 09:01:18 +00004589 public:
eladalonf1841382017-06-12 01:16:46 -07004590 WebRtcVideoChannelSimulcastTest()
magjed2475ae22017-09-12 04:42:15 -07004591 : fake_call_(webrtc::Call::Config(&event_log_)),
Magnus Jedvert02e7a192017-09-23 17:21:32 +02004592 encoder_factory_(new cricket::FakeWebRtcVideoEncoderFactory),
4593 decoder_factory_(new cricket::FakeWebRtcVideoDecoderFactory),
4594 engine_(std::unique_ptr<cricket::WebRtcVideoEncoderFactory>(
4595 encoder_factory_),
4596 std::unique_ptr<cricket::WebRtcVideoDecoderFactory>(
4597 decoder_factory_)),
magjed2475ae22017-09-12 04:42:15 -07004598 last_ssrc_(0) {}
buildbot@webrtc.orga8530772014-12-10 09:01:18 +00004599
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00004600 void SetUp() override {
nisse51542be2016-02-12 02:27:06 -08004601 channel_.reset(
kthelgason2bc68642017-02-07 07:02:22 -08004602 engine_.CreateChannel(&fake_call_, GetMediaConfig(), VideoOptions()));
Sergey Ulanove2b15012016-11-22 16:08:30 -08004603 channel_->OnReadyToSend(true);
buildbot@webrtc.orga8530772014-12-10 09:01:18 +00004604 last_ssrc_ = 123;
4605 }
4606
4607 protected:
buildbot@webrtc.orga8530772014-12-10 09:01:18 +00004608 void VerifySimulcastSettings(const VideoCodec& codec,
perkj26752742016-10-24 01:21:16 -07004609 int capture_width,
4610 int capture_height,
buildbot@webrtc.orga8530772014-12-10 09:01:18 +00004611 size_t num_configured_streams,
sprang429600d2017-01-26 06:12:26 -08004612 size_t expected_num_streams,
4613 bool screenshare,
4614 bool conference_mode) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02004615 cricket::VideoSendParameters parameters;
Fredrik Solenbergb071a192015-09-17 16:42:56 +02004616 parameters.codecs.push_back(codec);
sprang429600d2017-01-26 06:12:26 -08004617 parameters.conference_mode = conference_mode;
Fredrik Solenbergb071a192015-09-17 16:42:56 +02004618 ASSERT_TRUE(channel_->SetSendParameters(parameters));
buildbot@webrtc.orga8530772014-12-10 09:01:18 +00004619
Peter Boström0c4e06b2015-10-07 12:23:21 +02004620 std::vector<uint32_t> ssrcs = MAKE_VECTOR(kSsrcs3);
henrikg91d6ede2015-09-17 00:24:34 -07004621 RTC_DCHECK(num_configured_streams <= ssrcs.size());
buildbot@webrtc.orga8530772014-12-10 09:01:18 +00004622 ssrcs.resize(num_configured_streams);
4623
sprangf24a0642017-02-28 13:23:26 -08004624 AddSendStream(CreateSimStreamParams("cname", ssrcs));
pbos@webrtc.org86196c42015-02-16 21:02:00 +00004625 // Send a full-size frame to trigger a stream reconfiguration to use all
4626 // expected simulcast layers.
4627 cricket::FakeVideoCapturer capturer;
sprangf24a0642017-02-28 13:23:26 -08004628 VideoOptions options;
4629 if (screenshare)
4630 options.is_screencast = rtc::Optional<bool>(screenshare);
deadbeef5a4a75a2016-06-02 16:23:38 -07004631 EXPECT_TRUE(
sprang429600d2017-01-26 06:12:26 -08004632 channel_->SetVideoSend(ssrcs.front(), true, &options, &capturer));
sprangf24a0642017-02-28 13:23:26 -08004633 // Fetch the latest stream since SetVideoSend() may recreate it if the
4634 // screen content setting is changed.
4635 FakeVideoSendStream* stream = fake_call_.GetVideoSendStreams().front();
pbos@webrtc.org86196c42015-02-16 21:02:00 +00004636 EXPECT_EQ(cricket::CS_RUNNING, capturer.Start(cricket::VideoFormat(
perkj26752742016-10-24 01:21:16 -07004637 capture_width, capture_height,
pbos@webrtc.org86196c42015-02-16 21:02:00 +00004638 cricket::VideoFormat::FpsToInterval(30),
4639 cricket::FOURCC_I420)));
4640 channel_->SetSend(true);
4641 EXPECT_TRUE(capturer.CaptureFrame());
buildbot@webrtc.orga8530772014-12-10 09:01:18 +00004642
4643 std::vector<webrtc::VideoStream> video_streams = stream->GetVideoStreams();
4644 ASSERT_EQ(expected_num_streams, video_streams.size());
4645
sprang429600d2017-01-26 06:12:26 -08004646 std::vector<webrtc::VideoStream> expected_streams;
4647 if (conference_mode) {
4648 expected_streams = GetSimulcastConfig(
4649 num_configured_streams, capture_width, capture_height, 0,
4650 kDefaultQpMax, kDefaultVideoMaxFramerate, screenshare);
sprang3ebabf12017-02-16 07:35:22 -08004651 if (screenshare) {
4652 for (const webrtc::VideoStream& stream : expected_streams) {
4653 // Never scale screen content.
4654 EXPECT_EQ(stream.width, capture_width);
4655 EXPECT_EQ(stream.height, capture_height);
4656 }
4657 }
sprang429600d2017-01-26 06:12:26 -08004658 } else {
4659 webrtc::VideoStream stream;
4660 stream.width = capture_width;
4661 stream.height = capture_height;
4662 stream.max_framerate = kDefaultVideoMaxFramerate;
4663 stream.min_bitrate_bps = cricket::kMinVideoBitrateKbps * 1000;
4664 int max_bitrate_kbps;
4665 if (capture_width * capture_height <= 320 * 240) {
4666 max_bitrate_kbps = 600;
4667 } else if (capture_width * capture_height <= 640 * 480) {
4668 max_bitrate_kbps = 1700;
4669 } else if (capture_width * capture_height <= 960 * 540) {
4670 max_bitrate_kbps = 2000;
4671 } else {
4672 max_bitrate_kbps = 2500;
4673 }
4674 stream.target_bitrate_bps = stream.max_bitrate_bps =
4675 max_bitrate_kbps * 1000;
4676 stream.max_qp = kDefaultQpMax;
4677 expected_streams.push_back(stream);
4678 }
buildbot@webrtc.orga8530772014-12-10 09:01:18 +00004679
4680 ASSERT_EQ(expected_streams.size(), video_streams.size());
4681
4682 size_t num_streams = video_streams.size();
pbos@webrtc.org77e11bb2015-02-23 16:39:07 +00004683 int total_max_bitrate_bps = 0;
buildbot@webrtc.orga8530772014-12-10 09:01:18 +00004684 for (size_t i = 0; i < num_streams; ++i) {
4685 EXPECT_EQ(expected_streams[i].width, video_streams[i].width);
4686 EXPECT_EQ(expected_streams[i].height, video_streams[i].height);
4687
4688 EXPECT_GT(video_streams[i].max_framerate, 0);
4689 EXPECT_EQ(expected_streams[i].max_framerate,
4690 video_streams[i].max_framerate);
4691
4692 EXPECT_GT(video_streams[i].min_bitrate_bps, 0);
4693 EXPECT_EQ(expected_streams[i].min_bitrate_bps,
4694 video_streams[i].min_bitrate_bps);
4695
4696 EXPECT_GT(video_streams[i].target_bitrate_bps, 0);
4697 EXPECT_EQ(expected_streams[i].target_bitrate_bps,
4698 video_streams[i].target_bitrate_bps);
4699
4700 EXPECT_GT(video_streams[i].max_bitrate_bps, 0);
4701 EXPECT_EQ(expected_streams[i].max_bitrate_bps,
4702 video_streams[i].max_bitrate_bps);
4703
4704 EXPECT_GT(video_streams[i].max_qp, 0);
4705 EXPECT_EQ(expected_streams[i].max_qp, video_streams[i].max_qp);
4706
sprang429600d2017-01-26 06:12:26 -08004707 EXPECT_EQ(!conference_mode,
4708 expected_streams[i].temporal_layer_thresholds_bps.empty());
buildbot@webrtc.orga8530772014-12-10 09:01:18 +00004709 EXPECT_EQ(expected_streams[i].temporal_layer_thresholds_bps,
4710 video_streams[i].temporal_layer_thresholds_bps);
pbos@webrtc.org77e11bb2015-02-23 16:39:07 +00004711
4712 if (i == num_streams - 1) {
4713 total_max_bitrate_bps += video_streams[i].max_bitrate_bps;
4714 } else {
4715 total_max_bitrate_bps += video_streams[i].target_bitrate_bps;
4716 }
buildbot@webrtc.orga8530772014-12-10 09:01:18 +00004717 }
pbos@webrtc.org77e11bb2015-02-23 16:39:07 +00004718
deadbeef5a4a75a2016-06-02 16:23:38 -07004719 EXPECT_TRUE(channel_->SetVideoSend(ssrcs.front(), true, nullptr, nullptr));
buildbot@webrtc.orga8530772014-12-10 09:01:18 +00004720 }
4721
4722 FakeVideoSendStream* AddSendStream() {
4723 return AddSendStream(StreamParams::CreateLegacy(last_ssrc_++));
4724 }
4725
4726 FakeVideoSendStream* AddSendStream(const StreamParams& sp) {
4727 size_t num_streams =
Fredrik Solenberg709ed672015-09-15 12:26:33 +02004728 fake_call_.GetVideoSendStreams().size();
buildbot@webrtc.orga8530772014-12-10 09:01:18 +00004729 EXPECT_TRUE(channel_->AddSendStream(sp));
4730 std::vector<FakeVideoSendStream*> streams =
Fredrik Solenberg709ed672015-09-15 12:26:33 +02004731 fake_call_.GetVideoSendStreams();
buildbot@webrtc.orga8530772014-12-10 09:01:18 +00004732 EXPECT_EQ(num_streams + 1, streams.size());
4733 return streams[streams.size() - 1];
4734 }
4735
4736 std::vector<FakeVideoSendStream*> GetFakeSendStreams() {
Fredrik Solenberg709ed672015-09-15 12:26:33 +02004737 return fake_call_.GetVideoSendStreams();
buildbot@webrtc.orga8530772014-12-10 09:01:18 +00004738 }
4739
4740 FakeVideoReceiveStream* AddRecvStream() {
4741 return AddRecvStream(StreamParams::CreateLegacy(last_ssrc_++));
4742 }
4743
4744 FakeVideoReceiveStream* AddRecvStream(const StreamParams& sp) {
4745 size_t num_streams =
Fredrik Solenberg709ed672015-09-15 12:26:33 +02004746 fake_call_.GetVideoReceiveStreams().size();
buildbot@webrtc.orga8530772014-12-10 09:01:18 +00004747 EXPECT_TRUE(channel_->AddRecvStream(sp));
4748 std::vector<FakeVideoReceiveStream*> streams =
Fredrik Solenberg709ed672015-09-15 12:26:33 +02004749 fake_call_.GetVideoReceiveStreams();
buildbot@webrtc.orga8530772014-12-10 09:01:18 +00004750 EXPECT_EQ(num_streams + 1, streams.size());
4751 return streams[streams.size() - 1];
4752 }
4753
skvlad11a9cbf2016-10-07 11:53:05 -07004754 webrtc::RtcEventLogNullImpl event_log_;
Fredrik Solenberg709ed672015-09-15 12:26:33 +02004755 FakeCall fake_call_;
Magnus Jedvert02e7a192017-09-23 17:21:32 +02004756 cricket::FakeWebRtcVideoEncoderFactory* encoder_factory_;
4757 cricket::FakeWebRtcVideoDecoderFactory* decoder_factory_;
eladalonf1841382017-06-12 01:16:46 -07004758 WebRtcVideoEngine engine_;
kwiberg686a8ef2016-02-26 03:00:35 -08004759 std::unique_ptr<VideoMediaChannel> channel_;
Peter Boström0c4e06b2015-10-07 12:23:21 +02004760 uint32_t last_ssrc_;
buildbot@webrtc.orga8530772014-12-10 09:01:18 +00004761};
4762
eladalonf1841382017-06-12 01:16:46 -07004763TEST_F(WebRtcVideoChannelSimulcastTest, SetSendCodecsWith2SimulcastStreams) {
sprang429600d2017-01-26 06:12:26 -08004764 VerifySimulcastSettings(cricket::VideoCodec("VP8"), 640, 360, 2, 2, false,
4765 true);
buildbot@webrtc.orga8530772014-12-10 09:01:18 +00004766}
4767
eladalonf1841382017-06-12 01:16:46 -07004768TEST_F(WebRtcVideoChannelSimulcastTest, SetSendCodecsWith3SimulcastStreams) {
sprang429600d2017-01-26 06:12:26 -08004769 VerifySimulcastSettings(cricket::VideoCodec("VP8"), 1280, 720, 3, 3, false,
4770 true);
buildbot@webrtc.orga8530772014-12-10 09:01:18 +00004771}
4772
4773// Test that we normalize send codec format size in simulcast.
eladalonf1841382017-06-12 01:16:46 -07004774TEST_F(WebRtcVideoChannelSimulcastTest, SetSendCodecsWithOddSizeInSimulcast) {
sprang429600d2017-01-26 06:12:26 -08004775 VerifySimulcastSettings(cricket::VideoCodec("VP8"), 541, 271, 2, 2, false,
4776 true);
buildbot@webrtc.orga8530772014-12-10 09:01:18 +00004777}
sprang429600d2017-01-26 06:12:26 -08004778
eladalonf1841382017-06-12 01:16:46 -07004779TEST_F(WebRtcVideoChannelSimulcastTest, SetSendCodecsForScreenshare) {
sprang429600d2017-01-26 06:12:26 -08004780 VerifySimulcastSettings(cricket::VideoCodec("VP8"), 1280, 720, 3, 1, true,
4781 false);
4782}
4783
eladalonf1841382017-06-12 01:16:46 -07004784TEST_F(WebRtcVideoChannelSimulcastTest,
sprang429600d2017-01-26 06:12:26 -08004785 SetSendCodecsForConferenceModeScreenshare) {
4786 VerifySimulcastSettings(cricket::VideoCodec("VP8"), 1280, 720, 3, 1, true,
4787 true);
4788}
4789
eladalonf1841382017-06-12 01:16:46 -07004790TEST_F(WebRtcVideoChannelSimulcastTest, SetSendCodecsForSimulcastScreenshare) {
sprang429600d2017-01-26 06:12:26 -08004791 webrtc::test::ScopedFieldTrials override_field_trials_(
4792 "WebRTC-SimulcastScreenshare/Enabled/");
4793 VerifySimulcastSettings(cricket::VideoCodec("VP8"), 1280, 720, 3, 2, true,
4794 true);
4795}
4796
eladalonf1841382017-06-12 01:16:46 -07004797TEST_F(WebRtcVideoChannelSimulcastTest,
sprangfe627f32017-03-29 08:24:59 -07004798 NoSimulcastScreenshareWithoutConference) {
4799 webrtc::test::ScopedFieldTrials override_field_trials_(
4800 "WebRTC-SimulcastScreenshare/Enabled/");
4801 VerifySimulcastSettings(cricket::VideoCodec("VP8"), 1280, 720, 3, 1, true,
4802 false);
4803}
4804
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00004805} // namespace cricket