blob: 7fc5924c926da8edab9734d1a8917b6bf1dacb78 [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()) {
Magnus Jedvert8deb8182017-10-05 13:13:32 +0200567 if (!CodecNamesEq(name, engine_codec.name))
568 continue;
569 // The tests only use H264 Constrained Baseline. Make sure we don't return
570 // an internal H264 codec from the engine with a different H264 profile.
571 if (CodecNamesEq(name.c_str(), kH264CodecName)) {
572 const rtc::Optional<webrtc::H264::ProfileLevelId> profile_level_id =
573 webrtc::H264::ParseSdpProfileLevelId(engine_codec.params);
574 if (profile_level_id->profile !=
575 webrtc::H264::kProfileConstrainedBaseline) {
576 continue;
577 }
578 }
579 return engine_codec;
magjed509e4fe2016-11-18 01:34:11 -0800580 }
581 // This point should never be reached.
582 ADD_FAILURE() << "Unrecognized codec name: " << name;
583 return cricket::VideoCodec();
584}
585
magjed2475ae22017-09-12 04:42:15 -0700586VideoMediaChannel* WebRtcVideoEngineTest::SetUpForExternalEncoderFactory() {
buildbot@webrtc.org1ecbe452014-10-14 20:29:28 +0000587 VideoMediaChannel* channel =
kthelgason2bc68642017-02-07 07:02:22 -0800588 engine_.CreateChannel(call_.get(), GetMediaConfig(), VideoOptions());
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200589 cricket::VideoSendParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -0800590 // We need to look up the codec in the engine to get the correct payload type.
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200591 for (const VideoCodec& codec : encoder_factory_->supported_codecs())
magjed509e4fe2016-11-18 01:34:11 -0800592 parameters.codecs.push_back(GetEngineCodec(codec.name));
593
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200594 EXPECT_TRUE(channel->SetSendParameters(parameters));
pbos@webrtc.org7fe1e032014-10-14 04:25:33 +0000595
596 return channel;
597}
598
eladalonf1841382017-06-12 01:16:46 -0700599VideoMediaChannel* WebRtcVideoEngineTest::SetUpForExternalDecoderFactory(
pbos@webrtc.org96a93252014-11-03 14:46:44 +0000600 const std::vector<VideoCodec>& codecs) {
pbos@webrtc.org96a93252014-11-03 14:46:44 +0000601 VideoMediaChannel* channel =
kthelgason2bc68642017-02-07 07:02:22 -0800602 engine_.CreateChannel(call_.get(), GetMediaConfig(), VideoOptions());
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200603 cricket::VideoRecvParameters parameters;
604 parameters.codecs = codecs;
605 EXPECT_TRUE(channel->SetRecvParameters(parameters));
pbos@webrtc.org96a93252014-11-03 14:46:44 +0000606
607 return channel;
608}
609
eladalonf1841382017-06-12 01:16:46 -0700610TEST_F(WebRtcVideoEngineTest, UsesSimulcastAdapterForVp8Factories) {
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200611 encoder_factory_->AddSupportedVideoCodecType("VP8");
pbos@webrtc.orgf18fba22015-01-14 16:26:23 +0000612
magjed2475ae22017-09-12 04:42:15 -0700613 std::unique_ptr<VideoMediaChannel> channel(SetUpForExternalEncoderFactory());
pbos@webrtc.orgf18fba22015-01-14 16:26:23 +0000614
Peter Boström0c4e06b2015-10-07 12:23:21 +0200615 std::vector<uint32_t> ssrcs = MAKE_VECTOR(kSsrcs3);
pbos@webrtc.orgf18fba22015-01-14 16:26:23 +0000616
617 EXPECT_TRUE(
618 channel->AddSendStream(CreateSimStreamParams("cname", ssrcs)));
619 EXPECT_TRUE(channel->SetSend(true));
620
pbos@webrtc.org86196c42015-02-16 21:02:00 +0000621 cricket::FakeVideoCapturer capturer;
deadbeef5a4a75a2016-06-02 16:23:38 -0700622 EXPECT_TRUE(channel->SetVideoSend(ssrcs.front(), true, nullptr, &capturer));
pbos@webrtc.org86196c42015-02-16 21:02:00 +0000623 EXPECT_EQ(cricket::CS_RUNNING,
624 capturer.Start(capturer.GetSupportedFormats()->front()));
625 EXPECT_TRUE(capturer.CaptureFrame());
626
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200627 ASSERT_TRUE(encoder_factory_->WaitForCreatedVideoEncoders(2));
pbos@webrtc.orgf18fba22015-01-14 16:26:23 +0000628
629 // Verify that encoders are configured for simulcast through adapter
630 // (increasing resolution and only configured to send one stream each).
631 int prev_width = -1;
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200632 for (size_t i = 0; i < encoder_factory_->encoders().size(); ++i) {
633 ASSERT_TRUE(encoder_factory_->encoders()[i]->WaitForInitEncode());
pbos@webrtc.orgf18fba22015-01-14 16:26:23 +0000634 webrtc::VideoCodec codec_settings =
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200635 encoder_factory_->encoders()[i]->GetCodecSettings();
pbos@webrtc.orgf18fba22015-01-14 16:26:23 +0000636 EXPECT_EQ(0, codec_settings.numberOfSimulcastStreams);
637 EXPECT_GT(codec_settings.width, prev_width);
638 prev_width = codec_settings.width;
639 }
pbos@webrtc.org86196c42015-02-16 21:02:00 +0000640
deadbeef5a4a75a2016-06-02 16:23:38 -0700641 EXPECT_TRUE(channel->SetVideoSend(ssrcs.front(), true, nullptr, nullptr));
pthatcher@webrtc.org818c4982015-03-06 02:20:58 +0000642
643 channel.reset();
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200644 ASSERT_EQ(0u, encoder_factory_->encoders().size());
pbos@webrtc.orgf18fba22015-01-14 16:26:23 +0000645}
646
eladalonf1841382017-06-12 01:16:46 -0700647TEST_F(WebRtcVideoEngineTest, ChannelWithExternalH264CanChangeToInternalVp8) {
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200648 encoder_factory_->AddSupportedVideoCodecType("H264");
pbos@webrtc.org7fe1e032014-10-14 04:25:33 +0000649
magjed2475ae22017-09-12 04:42:15 -0700650 std::unique_ptr<VideoMediaChannel> channel(SetUpForExternalEncoderFactory());
pbos@webrtc.org7fe1e032014-10-14 04:25:33 +0000651
652 EXPECT_TRUE(
653 channel->AddSendStream(cricket::StreamParams::CreateLegacy(kSsrc)));
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200654 ASSERT_EQ(1u, encoder_factory_->encoders().size());
pbos@webrtc.org7fe1e032014-10-14 04:25:33 +0000655
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200656 cricket::VideoSendParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -0800657 parameters.codecs.push_back(GetEngineCodec("VP8"));
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200658 EXPECT_TRUE(channel->SetSendParameters(parameters));
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200659 ASSERT_EQ(0u, encoder_factory_->encoders().size());
pbos@webrtc.org7fe1e032014-10-14 04:25:33 +0000660}
661
eladalonf1841382017-06-12 01:16:46 -0700662TEST_F(WebRtcVideoEngineTest,
pbos@webrtc.org7fe1e032014-10-14 04:25:33 +0000663 DontUseExternalEncoderFactoryForUnsupportedCodecs) {
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200664 encoder_factory_->AddSupportedVideoCodecType("H264");
pbos@webrtc.org7fe1e032014-10-14 04:25:33 +0000665
kwiberg686a8ef2016-02-26 03:00:35 -0800666 std::unique_ptr<VideoMediaChannel> channel(
kthelgason2bc68642017-02-07 07:02:22 -0800667 engine_.CreateChannel(call_.get(), GetMediaConfig(), VideoOptions()));
magjed509e4fe2016-11-18 01:34:11 -0800668 cricket::VideoSendParameters parameters;
669 parameters.codecs.push_back(GetEngineCodec("VP8"));
670 EXPECT_TRUE(channel->SetSendParameters(parameters));
pbos@webrtc.org7fe1e032014-10-14 04:25:33 +0000671
672 EXPECT_TRUE(
673 channel->AddSendStream(cricket::StreamParams::CreateLegacy(kSsrc)));
pthatcher@webrtc.org818c4982015-03-06 02:20:58 +0000674 // Make sure DestroyVideoEncoder was called on the factory.
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200675 ASSERT_EQ(0u, encoder_factory_->encoders().size());
pthatcher@webrtc.org818c4982015-03-06 02:20:58 +0000676}
677
eladalonf1841382017-06-12 01:16:46 -0700678TEST_F(WebRtcVideoEngineTest,
pthatcher@webrtc.org818c4982015-03-06 02:20:58 +0000679 UsesSimulcastAdapterForVp8WithCombinedVP8AndH264Factory) {
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200680 encoder_factory_->AddSupportedVideoCodecType("VP8");
681 encoder_factory_->AddSupportedVideoCodecType("H264");
pthatcher@webrtc.org818c4982015-03-06 02:20:58 +0000682
kwiberg686a8ef2016-02-26 03:00:35 -0800683 std::unique_ptr<VideoMediaChannel> channel(
kthelgason2bc68642017-02-07 07:02:22 -0800684 engine_.CreateChannel(call_.get(), GetMediaConfig(), VideoOptions()));
magjed509e4fe2016-11-18 01:34:11 -0800685 cricket::VideoSendParameters parameters;
686 parameters.codecs.push_back(GetEngineCodec("VP8"));
687 EXPECT_TRUE(channel->SetSendParameters(parameters));
pthatcher@webrtc.org818c4982015-03-06 02:20:58 +0000688
Peter Boström0c4e06b2015-10-07 12:23:21 +0200689 std::vector<uint32_t> ssrcs = MAKE_VECTOR(kSsrcs3);
pthatcher@webrtc.org818c4982015-03-06 02:20:58 +0000690
691 EXPECT_TRUE(
692 channel->AddSendStream(CreateSimStreamParams("cname", ssrcs)));
693 EXPECT_TRUE(channel->SetSend(true));
694
695 // Send a fake frame, or else the media engine will configure the simulcast
696 // encoder adapter at a low-enough size that it'll only create a single
697 // encoder layer.
698 cricket::FakeVideoCapturer capturer;
deadbeef5a4a75a2016-06-02 16:23:38 -0700699 EXPECT_TRUE(channel->SetVideoSend(ssrcs.front(), true, nullptr, &capturer));
pthatcher@webrtc.org818c4982015-03-06 02:20:58 +0000700 EXPECT_EQ(cricket::CS_RUNNING,
701 capturer.Start(capturer.GetSupportedFormats()->front()));
702 EXPECT_TRUE(capturer.CaptureFrame());
703
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200704 ASSERT_TRUE(encoder_factory_->WaitForCreatedVideoEncoders(2));
705 ASSERT_TRUE(encoder_factory_->encoders()[0]->WaitForInitEncode());
pthatcher@webrtc.org818c4982015-03-06 02:20:58 +0000706 EXPECT_EQ(webrtc::kVideoCodecVP8,
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200707 encoder_factory_->encoders()[0]->GetCodecSettings().codecType);
pthatcher@webrtc.org818c4982015-03-06 02:20:58 +0000708
709 channel.reset();
710 // Make sure DestroyVideoEncoder was called on the factory.
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200711 EXPECT_EQ(0u, encoder_factory_->encoders().size());
pthatcher@webrtc.org818c4982015-03-06 02:20:58 +0000712}
713
eladalonf1841382017-06-12 01:16:46 -0700714TEST_F(WebRtcVideoEngineTest,
pthatcher@webrtc.org818c4982015-03-06 02:20:58 +0000715 DestroysNonSimulcastEncoderFromCombinedVP8AndH264Factory) {
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200716 encoder_factory_->AddSupportedVideoCodecType("VP8");
717 encoder_factory_->AddSupportedVideoCodecType("H264");
pthatcher@webrtc.org818c4982015-03-06 02:20:58 +0000718
kwiberg686a8ef2016-02-26 03:00:35 -0800719 std::unique_ptr<VideoMediaChannel> channel(
kthelgason2bc68642017-02-07 07:02:22 -0800720 engine_.CreateChannel(call_.get(), GetMediaConfig(), VideoOptions()));
magjed509e4fe2016-11-18 01:34:11 -0800721 cricket::VideoSendParameters parameters;
722 parameters.codecs.push_back(GetEngineCodec("H264"));
723 EXPECT_TRUE(channel->SetSendParameters(parameters));
pthatcher@webrtc.org818c4982015-03-06 02:20:58 +0000724
725 EXPECT_TRUE(
726 channel->AddSendStream(cricket::StreamParams::CreateLegacy(kSsrc)));
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200727 ASSERT_EQ(1u, encoder_factory_->encoders().size());
Per21d45d22016-10-30 21:37:57 +0100728
729 // Send a frame of 720p. This should trigger a "real" encoder initialization.
730 cricket::VideoFormat format(
731 1280, 720, cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420);
732 cricket::FakeVideoCapturer capturer;
733 EXPECT_TRUE(channel->SetVideoSend(kSsrc, true, nullptr, &capturer));
734 EXPECT_EQ(cricket::CS_RUNNING, capturer.Start(format));
735 EXPECT_TRUE(capturer.CaptureFrame());
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200736 ASSERT_TRUE(encoder_factory_->encoders()[0]->WaitForInitEncode());
pthatcher@webrtc.org818c4982015-03-06 02:20:58 +0000737 EXPECT_EQ(webrtc::kVideoCodecH264,
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200738 encoder_factory_->encoders()[0]->GetCodecSettings().codecType);
pthatcher@webrtc.org818c4982015-03-06 02:20:58 +0000739
740 channel.reset();
741 // Make sure DestroyVideoEncoder was called on the factory.
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200742 ASSERT_EQ(0u, encoder_factory_->encoders().size());
pbos@webrtc.org7fe1e032014-10-14 04:25:33 +0000743}
744
eladalonf1841382017-06-12 01:16:46 -0700745TEST_F(WebRtcVideoEngineTest, SimulcastDisabledForH264) {
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200746 encoder_factory_->AddSupportedVideoCodecType("H264");
noahricfdac5162015-08-27 01:59:29 -0700747
magjed2475ae22017-09-12 04:42:15 -0700748 std::unique_ptr<VideoMediaChannel> channel(SetUpForExternalEncoderFactory());
noahricfdac5162015-08-27 01:59:29 -0700749
Peter Boström0c4e06b2015-10-07 12:23:21 +0200750 const std::vector<uint32_t> ssrcs = MAKE_VECTOR(kSsrcs3);
noahricfdac5162015-08-27 01:59:29 -0700751 EXPECT_TRUE(
752 channel->AddSendStream(cricket::CreateSimStreamParams("cname", ssrcs)));
Peter Boströmce23bee2016-02-02 14:14:30 +0100753
754 // Send a frame of 720p. This should trigger a "real" encoder initialization.
noahricfdac5162015-08-27 01:59:29 -0700755 cricket::VideoFormat format(
756 1280, 720, cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420);
Peter Boströmce23bee2016-02-02 14:14:30 +0100757 cricket::FakeVideoCapturer capturer;
deadbeef5a4a75a2016-06-02 16:23:38 -0700758 EXPECT_TRUE(channel->SetVideoSend(ssrcs[0], true, nullptr, &capturer));
Peter Boströmce23bee2016-02-02 14:14:30 +0100759 EXPECT_EQ(cricket::CS_RUNNING, capturer.Start(format));
760 EXPECT_TRUE(capturer.CaptureFrame());
761
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200762 ASSERT_EQ(1u, encoder_factory_->encoders().size());
763 FakeWebRtcVideoEncoder* encoder = encoder_factory_->encoders()[0];
764 ASSERT_TRUE(encoder_factory_->encoders()[0]->WaitForInitEncode());
noahricfdac5162015-08-27 01:59:29 -0700765 EXPECT_EQ(webrtc::kVideoCodecH264, encoder->GetCodecSettings().codecType);
766 EXPECT_EQ(1u, encoder->GetCodecSettings().numberOfSimulcastStreams);
deadbeef5a4a75a2016-06-02 16:23:38 -0700767 EXPECT_TRUE(channel->SetVideoSend(ssrcs[0], true, nullptr, nullptr));
noahricfdac5162015-08-27 01:59:29 -0700768}
769
brandtrffc61182016-11-28 06:02:22 -0800770// Test that the FlexFEC field trial properly alters the output of
eladalonf1841382017-06-12 01:16:46 -0700771// WebRtcVideoEngine::codecs(), for an existing |engine_| object.
brandtrffc61182016-11-28 06:02:22 -0800772//
773// TODO(brandtr): Remove this test, when the FlexFEC field trial is gone.
eladalonf1841382017-06-12 01:16:46 -0700774TEST_F(WebRtcVideoEngineTest,
brandtrffc61182016-11-28 06:02:22 -0800775 Flexfec03SupportedAsInternalCodecBehindFieldTrial) {
776 auto is_flexfec = [](const VideoCodec& codec) {
777 if (codec.name == "flexfec-03")
778 return true;
779 return false;
780 };
781
782 // FlexFEC is not active without field trial.
brandtrffc61182016-11-28 06:02:22 -0800783 const std::vector<VideoCodec> codecs_before = engine_.codecs();
784 EXPECT_EQ(codecs_before.end(), std::find_if(codecs_before.begin(),
785 codecs_before.end(), is_flexfec));
786
787 // FlexFEC is active with field trial.
788 webrtc::test::ScopedFieldTrials override_field_trials_(
brandtr340e3fd2017-02-28 15:43:10 -0800789 "WebRTC-FlexFEC-03-Advertised/Enabled/");
brandtrffc61182016-11-28 06:02:22 -0800790 const std::vector<VideoCodec> codecs_after = engine_.codecs();
791 EXPECT_NE(codecs_after.end(),
792 std::find_if(codecs_after.begin(), codecs_after.end(), is_flexfec));
793}
794
hbosbab934b2016-01-27 01:36:03 -0800795// Test that external codecs are added to the end of the supported codec list.
eladalonf1841382017-06-12 01:16:46 -0700796TEST_F(WebRtcVideoEngineTest, ReportSupportedExternalCodecs) {
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200797 encoder_factory_->AddSupportedVideoCodecType("FakeExternalCodec");
pbos@webrtc.org7fe1e032014-10-14 04:25:33 +0000798
799 std::vector<cricket::VideoCodec> codecs(engine_.codecs());
800 ASSERT_GE(codecs.size(), 2u);
minyuef032e402017-07-17 08:45:17 -0700801 cricket::VideoCodec internal_codec = codecs.front();
802 cricket::VideoCodec external_codec = codecs.back();
pbos@webrtc.org7fe1e032014-10-14 04:25:33 +0000803
minyuef032e402017-07-17 08:45:17 -0700804 // The external codec will appear last in the vector.
magjed06f3aae2017-07-14 10:36:23 -0700805 EXPECT_EQ("VP8", internal_codec.name);
minyuef032e402017-07-17 08:45:17 -0700806 EXPECT_EQ("FakeExternalCodec", external_codec.name);
pbos@webrtc.org7fe1e032014-10-14 04:25:33 +0000807}
808
brandtrffc61182016-11-28 06:02:22 -0800809// Test that an external codec that was added after the engine was initialized
810// does show up in the codec list after it was added.
eladalonf1841382017-06-12 01:16:46 -0700811TEST_F(WebRtcVideoEngineTest, ReportSupportedExternalCodecsWithAddedCodec) {
brandtrffc61182016-11-28 06:02:22 -0800812 // Set up external encoder factory with first codec, and initialize engine.
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200813 encoder_factory_->AddSupportedVideoCodecType("FakeExternalCodec1");
brandtrffc61182016-11-28 06:02:22 -0800814
minyuef032e402017-07-17 08:45:17 -0700815 // The first external codec will appear last in the vector.
brandtrffc61182016-11-28 06:02:22 -0800816 std::vector<cricket::VideoCodec> codecs_before(engine_.codecs());
minyuef032e402017-07-17 08:45:17 -0700817 EXPECT_EQ("FakeExternalCodec1", codecs_before.back().name);
brandtrffc61182016-11-28 06:02:22 -0800818
819 // Add second codec.
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200820 encoder_factory_->AddSupportedVideoCodecType("FakeExternalCodec2");
brandtrffc61182016-11-28 06:02:22 -0800821 std::vector<cricket::VideoCodec> codecs_after(engine_.codecs());
822 EXPECT_EQ(codecs_before.size() + 1, codecs_after.size());
minyuef032e402017-07-17 08:45:17 -0700823 EXPECT_EQ("FakeExternalCodec2", codecs_after.back().name);
brandtrffc61182016-11-28 06:02:22 -0800824}
825
eladalonf1841382017-06-12 01:16:46 -0700826TEST_F(WebRtcVideoEngineTest, RegisterExternalDecodersIfSupported) {
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200827 decoder_factory_->AddSupportedVideoCodecType(webrtc::kVideoCodecVP8);
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200828 cricket::VideoRecvParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -0800829 parameters.codecs.push_back(GetEngineCodec("VP8"));
pbos@webrtc.org96a93252014-11-03 14:46:44 +0000830
kwiberg686a8ef2016-02-26 03:00:35 -0800831 std::unique_ptr<VideoMediaChannel> channel(
magjed2475ae22017-09-12 04:42:15 -0700832 SetUpForExternalDecoderFactory(parameters.codecs));
pbos@webrtc.org96a93252014-11-03 14:46:44 +0000833
834 EXPECT_TRUE(
835 channel->AddRecvStream(cricket::StreamParams::CreateLegacy(kSsrc)));
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200836 ASSERT_EQ(1u, decoder_factory_->decoders().size());
pbos@webrtc.org96a93252014-11-03 14:46:44 +0000837
838 // Setting codecs of the same type should not reallocate the decoder.
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200839 EXPECT_TRUE(channel->SetRecvParameters(parameters));
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200840 EXPECT_EQ(1, decoder_factory_->GetNumCreatedDecoders());
pbos@webrtc.org96a93252014-11-03 14:46:44 +0000841
842 // Remove stream previously added to free the external decoder instance.
843 EXPECT_TRUE(channel->RemoveRecvStream(kSsrc));
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200844 EXPECT_EQ(0u, decoder_factory_->decoders().size());
pbos@webrtc.org96a93252014-11-03 14:46:44 +0000845}
846
847// Verifies that we can set up decoders that are not internally supported.
eladalonf1841382017-06-12 01:16:46 -0700848TEST_F(WebRtcVideoEngineTest, RegisterExternalH264DecoderIfSupported) {
pbos@webrtc.org96a93252014-11-03 14:46:44 +0000849 // TODO(pbos): Do not assume that encoder/decoder support is symmetric. We
850 // can't even query the WebRtcVideoDecoderFactory for supported codecs.
851 // For now we add a FakeWebRtcVideoEncoderFactory to add H264 to supported
852 // codecs.
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200853 encoder_factory_->AddSupportedVideoCodecType("H264");
854 decoder_factory_->AddSupportedVideoCodecType(webrtc::kVideoCodecH264);
pbos@webrtc.org96a93252014-11-03 14:46:44 +0000855 std::vector<cricket::VideoCodec> codecs;
magjed509e4fe2016-11-18 01:34:11 -0800856 codecs.push_back(GetEngineCodec("H264"));
pbos@webrtc.org96a93252014-11-03 14:46:44 +0000857
kwiberg686a8ef2016-02-26 03:00:35 -0800858 std::unique_ptr<VideoMediaChannel> channel(
magjed2475ae22017-09-12 04:42:15 -0700859 SetUpForExternalDecoderFactory(codecs));
pbos@webrtc.org96a93252014-11-03 14:46:44 +0000860
861 EXPECT_TRUE(
862 channel->AddRecvStream(cricket::StreamParams::CreateLegacy(kSsrc)));
Magnus Jedvert02e7a192017-09-23 17:21:32 +0200863 ASSERT_EQ(1u, decoder_factory_->decoders().size());
pbos@webrtc.org96a93252014-11-03 14:46:44 +0000864}
865
Magnus Jedvertd4b0c052017-09-14 10:24:54 +0200866class MockVideoEncoderFactory : public webrtc::VideoEncoderFactory {
867 public:
868 MOCK_CONST_METHOD0(GetSupportedFormats,
869 std::vector<webrtc::SdpVideoFormat>());
870 MOCK_CONST_METHOD1(QueryVideoEncoder,
871 CodecInfo(const webrtc::SdpVideoFormat&));
872
873 // We need to proxy to a return type that is copyable.
874 std::unique_ptr<webrtc::VideoEncoder> CreateVideoEncoder(
875 const webrtc::SdpVideoFormat& format) {
876 return std::unique_ptr<webrtc::VideoEncoder>(
877 CreateVideoEncoderProxy(format));
878 }
879 MOCK_METHOD1(CreateVideoEncoderProxy,
880 webrtc::VideoEncoder*(const webrtc::SdpVideoFormat&));
881
882 MOCK_METHOD0(Die, void());
883 ~MockVideoEncoderFactory() { Die(); }
884};
885
886class MockVideoDecoderFactory : public webrtc::VideoDecoderFactory {
887 public:
888 MOCK_CONST_METHOD0(GetSupportedFormats,
889 std::vector<webrtc::SdpVideoFormat>());
890
891 // We need to proxy to a return type that is copyable.
892 std::unique_ptr<webrtc::VideoDecoder> CreateVideoDecoder(
893 const webrtc::SdpVideoFormat& format) {
894 return std::unique_ptr<webrtc::VideoDecoder>(
895 CreateVideoDecoderProxy(format));
896 }
897 MOCK_METHOD1(CreateVideoDecoderProxy,
898 webrtc::VideoDecoder*(const webrtc::SdpVideoFormat&));
899
900 MOCK_METHOD0(Die, void());
901 ~MockVideoDecoderFactory() { Die(); }
902};
903
904TEST(WebRtcVideoEngineNewVideoCodecFactoryTest, NullFactories) {
905 std::unique_ptr<webrtc::VideoEncoderFactory> encoder_factory;
906 std::unique_ptr<webrtc::VideoDecoderFactory> decoder_factory;
907 WebRtcVideoEngine engine(std::move(encoder_factory),
908 std::move(decoder_factory));
909 EXPECT_EQ(0u, engine.codecs().size());
910}
911
912TEST(WebRtcVideoEngineNewVideoCodecFactoryTest, EmptyFactories) {
913 // |engine| take ownership of the factories.
914 MockVideoEncoderFactory* encoder_factory = new MockVideoEncoderFactory();
915 MockVideoDecoderFactory* decoder_factory = new MockVideoDecoderFactory();
916 WebRtcVideoEngine engine(
917 (std::unique_ptr<webrtc::VideoEncoderFactory>(encoder_factory)),
918 (std::unique_ptr<webrtc::VideoDecoderFactory>(decoder_factory)));
919 EXPECT_CALL(*encoder_factory, GetSupportedFormats());
920 EXPECT_EQ(0u, engine.codecs().size());
921 EXPECT_CALL(*encoder_factory, Die());
922 EXPECT_CALL(*decoder_factory, Die());
923}
924
925// Test full behavior in the video engine when video codec factories of the new
926// type are injected supporting the single codec Vp8. Check the returned codecs
927// from the engine and that we will create a Vp8 encoder and decoder using the
928// new factories.
929TEST(WebRtcVideoEngineNewVideoCodecFactoryTest, Vp8) {
930 // |engine| take ownership of the factories.
931 MockVideoEncoderFactory* encoder_factory = new MockVideoEncoderFactory();
932 MockVideoDecoderFactory* decoder_factory = new MockVideoDecoderFactory();
933 WebRtcVideoEngine engine(
934 (std::unique_ptr<webrtc::VideoEncoderFactory>(encoder_factory)),
935 (std::unique_ptr<webrtc::VideoDecoderFactory>(decoder_factory)));
936 const webrtc::SdpVideoFormat vp8_format("VP8");
937 const std::vector<webrtc::SdpVideoFormat> supported_formats = {vp8_format};
938 EXPECT_CALL(*encoder_factory, GetSupportedFormats())
939 .WillRepeatedly(testing::Return(supported_formats));
940
941 // Verify the codecs from the engine.
942 const std::vector<VideoCodec> engine_codecs = engine.codecs();
943 // Verify an RTX codec has been added correctly.
944 EXPECT_EQ(2u, engine_codecs.size());
945 EXPECT_EQ("VP8", engine_codecs.at(0).name);
946 EXPECT_EQ("rtx", engine_codecs.at(1).name);
947 int associated_payload_type;
948 EXPECT_TRUE(engine_codecs.at(1).GetParam(
949 cricket::kCodecParamAssociatedPayloadType, &associated_payload_type));
950 EXPECT_EQ(engine_codecs.at(0).id, associated_payload_type);
951 // Verify default parameters has been added to the VP8 codec.
952 VerifyCodecHasDefaultFeedbackParams(engine_codecs.at(0));
953
954 // Mock encoder creation. |engine| take ownership of the encoder.
955 webrtc::VideoEncoderFactory::CodecInfo codec_info;
956 codec_info.is_hardware_accelerated = false;
957 codec_info.has_internal_source = false;
958 const webrtc::SdpVideoFormat format("VP8");
959 EXPECT_CALL(*encoder_factory, QueryVideoEncoder(format))
960 .WillRepeatedly(testing::Return(codec_info));
961 FakeWebRtcVideoEncoder* const encoder = new FakeWebRtcVideoEncoder();
962 EXPECT_CALL(*encoder_factory, CreateVideoEncoderProxy(format))
963 .WillOnce(testing::Return(encoder));
964
965 // Mock decoder creation. |engine| take ownership of the decoder.
966 FakeWebRtcVideoDecoder* const decoder = new FakeWebRtcVideoDecoder();
967 EXPECT_CALL(*decoder_factory, CreateVideoDecoderProxy(format))
968 .WillOnce(testing::Return(decoder));
969
970 // Create a call.
971 webrtc::RtcEventLogNullImpl event_log;
972 std::unique_ptr<webrtc::Call> call(
973 webrtc::Call::Create(webrtc::Call::Config(&event_log)));
974
975 // Create send channel.
976 const int send_ssrc = 123;
977 std::unique_ptr<VideoMediaChannel> send_channel(
978 engine.CreateChannel(call.get(), GetMediaConfig(), VideoOptions()));
979 cricket::VideoSendParameters send_parameters;
980 send_parameters.codecs.push_back(engine_codecs.at(0));
981 EXPECT_TRUE(send_channel->SetSendParameters(send_parameters));
982 send_channel->OnReadyToSend(true);
983 EXPECT_TRUE(
984 send_channel->AddSendStream(StreamParams::CreateLegacy(send_ssrc)));
985 EXPECT_TRUE(send_channel->SetSend(true));
986
987 // Create recv channel.
988 const int recv_ssrc = 321;
989 std::unique_ptr<VideoMediaChannel> recv_channel(
990 engine.CreateChannel(call.get(), GetMediaConfig(), VideoOptions()));
991 cricket::VideoRecvParameters recv_parameters;
992 recv_parameters.codecs.push_back(engine_codecs.at(0));
993 EXPECT_TRUE(recv_channel->SetRecvParameters(recv_parameters));
994 EXPECT_TRUE(recv_channel->AddRecvStream(
995 cricket::StreamParams::CreateLegacy(recv_ssrc)));
996
997 // Remove streams previously added to free the encoder and decoder instance.
998 EXPECT_CALL(*encoder_factory, Die());
999 EXPECT_CALL(*decoder_factory, Die());
1000 EXPECT_TRUE(send_channel->RemoveSendStream(send_ssrc));
1001 EXPECT_TRUE(recv_channel->RemoveRecvStream(recv_ssrc));
1002}
1003
eladalonf1841382017-06-12 01:16:46 -07001004class WebRtcVideoChannelBaseTest
1005 : public VideoMediaChannelTest<WebRtcVideoEngine, WebRtcVideoChannel> {
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001006 protected:
eladalonf1841382017-06-12 01:16:46 -07001007 typedef VideoMediaChannelTest<WebRtcVideoEngine, WebRtcVideoChannel> Base;
pbos@webrtc.org42684be2014-10-03 11:25:45 +00001008
magjed509e4fe2016-11-18 01:34:11 -08001009 cricket::VideoCodec GetEngineCodec(const std::string& name) {
1010 for (const cricket::VideoCodec& engine_codec : engine_.codecs()) {
1011 if (CodecNamesEq(name, engine_codec.name))
1012 return engine_codec;
1013 }
1014 // This point should never be reached.
1015 ADD_FAILURE() << "Unrecognized codec name: " << name;
1016 return cricket::VideoCodec();
1017 }
1018
1019 cricket::VideoCodec DefaultCodec() override { return GetEngineCodec("VP8"); }
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001020};
1021
sakal1fd95952016-06-22 00:46:15 -07001022// Verifies that id given in stream params is passed to the decoder factory.
eladalonf1841382017-06-12 01:16:46 -07001023TEST_F(WebRtcVideoEngineTest, StreamParamsIdPassedToDecoderFactory) {
Magnus Jedvert02e7a192017-09-23 17:21:32 +02001024 decoder_factory_->AddSupportedVideoCodecType(webrtc::kVideoCodecVP8);
sakal1fd95952016-06-22 00:46:15 -07001025 cricket::VideoRecvParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08001026 parameters.codecs.push_back(GetEngineCodec("VP8"));
sakal1fd95952016-06-22 00:46:15 -07001027
1028 std::unique_ptr<VideoMediaChannel> channel(
magjed2475ae22017-09-12 04:42:15 -07001029 SetUpForExternalDecoderFactory(parameters.codecs));
sakal1fd95952016-06-22 00:46:15 -07001030
1031 StreamParams sp = cricket::StreamParams::CreateLegacy(kSsrc);
1032 sp.id = "FakeStreamParamsId";
1033 EXPECT_TRUE(channel->AddRecvStream(sp));
Magnus Jedvert02e7a192017-09-23 17:21:32 +02001034 EXPECT_EQ(1u, decoder_factory_->decoders().size());
sakal1fd95952016-06-22 00:46:15 -07001035
Magnus Jedvert02e7a192017-09-23 17:21:32 +02001036 std::vector<cricket::VideoDecoderParams> params = decoder_factory_->params();
sakal1fd95952016-06-22 00:46:15 -07001037 ASSERT_EQ(1u, params.size());
1038 EXPECT_EQ(sp.id, params[0].receive_stream_id);
1039}
1040
eladalonf1841382017-06-12 01:16:46 -07001041TEST_F(WebRtcVideoEngineTest, DISABLED_RecreatesEncoderOnContentTypeChange) {
Magnus Jedvert02e7a192017-09-23 17:21:32 +02001042 encoder_factory_->AddSupportedVideoCodecType("VP8");
sprangf24a0642017-02-28 13:23:26 -08001043 std::unique_ptr<FakeCall> fake_call(
1044 new FakeCall(webrtc::Call::Config(&event_log_)));
magjed2475ae22017-09-12 04:42:15 -07001045 std::unique_ptr<VideoMediaChannel> channel(SetUpForExternalEncoderFactory());
sprangf24a0642017-02-28 13:23:26 -08001046 ASSERT_TRUE(
1047 channel->AddSendStream(cricket::StreamParams::CreateLegacy(kSsrc)));
1048 cricket::VideoCodec codec = GetEngineCodec("VP8");
1049 cricket::VideoSendParameters parameters;
1050 parameters.codecs.push_back(codec);
1051 channel->OnReadyToSend(true);
1052 channel->SetSend(true);
1053 ASSERT_TRUE(channel->SetSendParameters(parameters));
1054
1055 cricket::FakeVideoCapturer capturer;
1056 VideoOptions options;
1057 EXPECT_TRUE(channel->SetVideoSend(kSsrc, true, &options, &capturer));
1058
1059 EXPECT_EQ(cricket::CS_RUNNING,
1060 capturer.Start(capturer.GetSupportedFormats()->front()));
1061 EXPECT_TRUE(capturer.CaptureFrame());
Magnus Jedvert02e7a192017-09-23 17:21:32 +02001062 ASSERT_TRUE(encoder_factory_->WaitForCreatedVideoEncoders(1));
sprangf24a0642017-02-28 13:23:26 -08001063 EXPECT_EQ(webrtc::kRealtimeVideo,
Magnus Jedvert02e7a192017-09-23 17:21:32 +02001064 encoder_factory_->encoders().back()->GetCodecSettings().mode);
sprangf24a0642017-02-28 13:23:26 -08001065
1066 EXPECT_TRUE(channel->SetVideoSend(kSsrc, true, &options, &capturer));
1067 EXPECT_TRUE(capturer.CaptureFrame());
1068 // No change in content type, keep current encoder.
Magnus Jedvert02e7a192017-09-23 17:21:32 +02001069 EXPECT_EQ(1, encoder_factory_->GetNumCreatedEncoders());
sprangf24a0642017-02-28 13:23:26 -08001070
1071 options.is_screencast.emplace(true);
1072 EXPECT_TRUE(channel->SetVideoSend(kSsrc, true, &options, &capturer));
1073 EXPECT_TRUE(capturer.CaptureFrame());
1074 // Change to screen content, recreate encoder. For the simulcast encoder
1075 // adapter case, this will result in two calls since InitEncode triggers a
1076 // a new instance.
Magnus Jedvert02e7a192017-09-23 17:21:32 +02001077 ASSERT_TRUE(encoder_factory_->WaitForCreatedVideoEncoders(2));
sprangf24a0642017-02-28 13:23:26 -08001078 EXPECT_EQ(webrtc::kScreensharing,
Magnus Jedvert02e7a192017-09-23 17:21:32 +02001079 encoder_factory_->encoders().back()->GetCodecSettings().mode);
sprangf24a0642017-02-28 13:23:26 -08001080
1081 EXPECT_TRUE(channel->SetVideoSend(kSsrc, true, &options, &capturer));
1082 EXPECT_TRUE(capturer.CaptureFrame());
1083 // Still screen content, no need to update encoder.
Magnus Jedvert02e7a192017-09-23 17:21:32 +02001084 EXPECT_EQ(2, encoder_factory_->GetNumCreatedEncoders());
sprangf24a0642017-02-28 13:23:26 -08001085
1086 options.is_screencast.emplace(false);
1087 options.video_noise_reduction.emplace(false);
1088 EXPECT_TRUE(channel->SetVideoSend(kSsrc, true, &options, &capturer));
1089 // Change back to regular video content, update encoder. Also change
1090 // a non |is_screencast| option just to verify it doesn't affect recreation.
1091 EXPECT_TRUE(capturer.CaptureFrame());
Magnus Jedvert02e7a192017-09-23 17:21:32 +02001092 ASSERT_TRUE(encoder_factory_->WaitForCreatedVideoEncoders(3));
sprangf24a0642017-02-28 13:23:26 -08001093 EXPECT_EQ(webrtc::kRealtimeVideo,
Magnus Jedvert02e7a192017-09-23 17:21:32 +02001094 encoder_factory_->encoders().back()->GetCodecSettings().mode);
sprangf24a0642017-02-28 13:23:26 -08001095
1096 // Remove stream previously added to free the external encoder instance.
1097 EXPECT_TRUE(channel->RemoveSendStream(kSsrc));
Magnus Jedvert02e7a192017-09-23 17:21:32 +02001098 EXPECT_EQ(0u, encoder_factory_->encoders().size());
sprangf24a0642017-02-28 13:23:26 -08001099}
1100
pbos@webrtc.org8fdeee62014-07-20 14:40:23 +00001101#define WEBRTC_BASE_TEST(test) \
eladalonf1841382017-06-12 01:16:46 -07001102 TEST_F(WebRtcVideoChannelBaseTest, test) { Base::test(); }
pbos@webrtc.org8fdeee62014-07-20 14:40:23 +00001103
1104#define WEBRTC_DISABLED_BASE_TEST(test) \
eladalonf1841382017-06-12 01:16:46 -07001105 TEST_F(WebRtcVideoChannelBaseTest, DISABLED_##test) { Base::test(); }
pbos@webrtc.org8fdeee62014-07-20 14:40:23 +00001106
pbos@webrtc.org8fdeee62014-07-20 14:40:23 +00001107WEBRTC_BASE_TEST(SetSend);
1108WEBRTC_BASE_TEST(SetSendWithoutCodecs);
1109WEBRTC_BASE_TEST(SetSendSetsTransportBufferSizes);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001110
pbos@webrtc.org8fdeee62014-07-20 14:40:23 +00001111WEBRTC_BASE_TEST(GetStats);
1112WEBRTC_BASE_TEST(GetStatsMultipleRecvStreams);
1113WEBRTC_BASE_TEST(GetStatsMultipleSendStreams);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001114
pbos@webrtc.org8fdeee62014-07-20 14:40:23 +00001115WEBRTC_BASE_TEST(SetSendBandwidth);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001116
pbos@webrtc.org8fdeee62014-07-20 14:40:23 +00001117WEBRTC_BASE_TEST(SetSendSsrc);
1118WEBRTC_BASE_TEST(SetSendSsrcAfterSetCodecs);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001119
nisse08582ff2016-02-04 01:24:52 -08001120WEBRTC_BASE_TEST(SetSink);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001121
pbos@webrtc.org8fdeee62014-07-20 14:40:23 +00001122WEBRTC_BASE_TEST(AddRemoveSendStreams);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001123
pbos@webrtc.org8fdeee62014-07-20 14:40:23 +00001124WEBRTC_BASE_TEST(SimulateConference);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001125
Alejandro Luebs947c02d2016-06-15 15:39:46 -07001126WEBRTC_DISABLED_BASE_TEST(AddRemoveCapturer);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001127
pbos@webrtc.org8fdeee62014-07-20 14:40:23 +00001128WEBRTC_BASE_TEST(RemoveCapturerWithoutAdd);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001129
pbos@webrtc.org8fdeee62014-07-20 14:40:23 +00001130WEBRTC_BASE_TEST(AddRemoveCapturerMultipleSources);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001131
pbos@webrtc.org8fdeee62014-07-20 14:40:23 +00001132WEBRTC_BASE_TEST(RejectEmptyStreamParams);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001133
pbos@webrtc.orgc4175b92014-09-03 15:25:49 +00001134WEBRTC_BASE_TEST(MultipleSendStreams);
1135
eladalonf1841382017-06-12 01:16:46 -07001136TEST_F(WebRtcVideoChannelBaseTest, SendAndReceiveVp8Vga) {
magjed509e4fe2016-11-18 01:34:11 -08001137 SendAndReceive(GetEngineCodec("VP8"));
pbos@webrtc.org9359cb32014-07-23 15:44:48 +00001138}
1139
eladalonf1841382017-06-12 01:16:46 -07001140TEST_F(WebRtcVideoChannelBaseTest, SendAndReceiveVp8Qvga) {
magjed509e4fe2016-11-18 01:34:11 -08001141 SendAndReceive(GetEngineCodec("VP8"));
pbos@webrtc.org9359cb32014-07-23 15:44:48 +00001142}
1143
eladalonf1841382017-06-12 01:16:46 -07001144TEST_F(WebRtcVideoChannelBaseTest, SendAndReceiveVp8SvcQqvga) {
magjed509e4fe2016-11-18 01:34:11 -08001145 SendAndReceive(GetEngineCodec("VP8"));
pbos@webrtc.org9359cb32014-07-23 15:44:48 +00001146}
1147
eladalonf1841382017-06-12 01:16:46 -07001148TEST_F(WebRtcVideoChannelBaseTest, TwoStreamsSendAndReceive) {
Peter Boströmd1f584b2016-04-20 16:31:53 +02001149 // Set a high bitrate to not be downscaled by VP8 due to low initial start
1150 // bitrates. This currently happens at <250k, and two streams sharing 300k
1151 // initially will use QVGA instead of VGA.
1152 // TODO(pbos): Set up the quality scaler so that both senders reliably start
1153 // at QVGA, then verify that instead.
magjed509e4fe2016-11-18 01:34:11 -08001154 cricket::VideoCodec codec = GetEngineCodec("VP8");
Peter Boströmd1f584b2016-04-20 16:31:53 +02001155 codec.params[kCodecParamStartBitrate] = "1000000";
1156 Base::TwoStreamsSendAndReceive(codec);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001157}
1158
eladalonf1841382017-06-12 01:16:46 -07001159class WebRtcVideoChannelTest : public WebRtcVideoEngineTest {
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001160 public:
eladalonf1841382017-06-12 01:16:46 -07001161 WebRtcVideoChannelTest() : WebRtcVideoChannelTest("") {}
1162 explicit WebRtcVideoChannelTest(const char* field_trials)
1163 : WebRtcVideoEngineTest(field_trials), last_ssrc_(0) {}
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001164 void SetUp() override {
skvlad11a9cbf2016-10-07 11:53:05 -07001165 fake_call_.reset(new FakeCall(webrtc::Call::Config(&event_log_)));
kthelgason2bc68642017-02-07 07:02:22 -08001166 channel_.reset(engine_.CreateChannel(fake_call_.get(), GetMediaConfig(),
1167 VideoOptions()));
Sergey Ulanove2b15012016-11-22 16:08:30 -08001168 channel_->OnReadyToSend(true);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001169 last_ssrc_ = 123;
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001170 send_parameters_.codecs = engine_.codecs();
1171 recv_parameters_.codecs = engine_.codecs();
1172 ASSERT_TRUE(channel_->SetSendParameters(send_parameters_));
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001173 }
1174
1175 protected:
1176 FakeVideoSendStream* AddSendStream() {
pbos@webrtc.org42684be2014-10-03 11:25:45 +00001177 return AddSendStream(StreamParams::CreateLegacy(++last_ssrc_));
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001178 }
1179
1180 FakeVideoSendStream* AddSendStream(const StreamParams& sp) {
pbos@webrtc.org42684be2014-10-03 11:25:45 +00001181 size_t num_streams = fake_call_->GetVideoSendStreams().size();
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001182 EXPECT_TRUE(channel_->AddSendStream(sp));
1183 std::vector<FakeVideoSendStream*> streams =
pbos@webrtc.org42684be2014-10-03 11:25:45 +00001184 fake_call_->GetVideoSendStreams();
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001185 EXPECT_EQ(num_streams + 1, streams.size());
1186 return streams[streams.size() - 1];
1187 }
1188
1189 std::vector<FakeVideoSendStream*> GetFakeSendStreams() {
pbos@webrtc.org42684be2014-10-03 11:25:45 +00001190 return fake_call_->GetVideoSendStreams();
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001191 }
1192
1193 FakeVideoReceiveStream* AddRecvStream() {
pbos@webrtc.org42684be2014-10-03 11:25:45 +00001194 return AddRecvStream(StreamParams::CreateLegacy(++last_ssrc_));
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001195 }
1196
1197 FakeVideoReceiveStream* AddRecvStream(const StreamParams& sp) {
pbos@webrtc.org42684be2014-10-03 11:25:45 +00001198 size_t num_streams = fake_call_->GetVideoReceiveStreams().size();
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001199 EXPECT_TRUE(channel_->AddRecvStream(sp));
1200 std::vector<FakeVideoReceiveStream*> streams =
pbos@webrtc.org42684be2014-10-03 11:25:45 +00001201 fake_call_->GetVideoReceiveStreams();
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001202 EXPECT_EQ(num_streams + 1, streams.size());
1203 return streams[streams.size() - 1];
1204 }
1205
pbos@webrtc.org00873182014-11-25 14:03:34 +00001206 void SetSendCodecsShouldWorkForBitrates(const char* min_bitrate_kbps,
1207 int expected_min_bitrate_bps,
1208 const char* start_bitrate_kbps,
1209 int expected_start_bitrate_bps,
1210 const char* max_bitrate_kbps,
1211 int expected_max_bitrate_bps) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001212 auto& codecs = send_parameters_.codecs;
1213 codecs.clear();
magjed509e4fe2016-11-18 01:34:11 -08001214 codecs.push_back(GetEngineCodec("VP8"));
pbos@webrtc.org00873182014-11-25 14:03:34 +00001215 codecs[0].params[kCodecParamMinBitrate] = min_bitrate_kbps;
1216 codecs[0].params[kCodecParamStartBitrate] = start_bitrate_kbps;
1217 codecs[0].params[kCodecParamMaxBitrate] = max_bitrate_kbps;
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001218 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001219
pbos@webrtc.org00873182014-11-25 14:03:34 +00001220 EXPECT_EQ(expected_min_bitrate_bps,
Stefan Holmere5904162015-03-26 11:11:06 +01001221 fake_call_->GetConfig().bitrate_config.min_bitrate_bps);
pbos@webrtc.org00873182014-11-25 14:03:34 +00001222 EXPECT_EQ(expected_start_bitrate_bps,
Stefan Holmere5904162015-03-26 11:11:06 +01001223 fake_call_->GetConfig().bitrate_config.start_bitrate_bps);
pbos@webrtc.org00873182014-11-25 14:03:34 +00001224 EXPECT_EQ(expected_max_bitrate_bps,
Stefan Holmere5904162015-03-26 11:11:06 +01001225 fake_call_->GetConfig().bitrate_config.max_bitrate_bps);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001226 }
1227
isheriff6f8d6862016-05-26 11:24:55 -07001228 void TestSetSendRtpHeaderExtensions(const std::string& ext_uri) {
pbos@webrtc.org587ef602014-06-16 17:32:02 +00001229 // Enable extension.
1230 const int id = 1;
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001231 cricket::VideoSendParameters parameters = send_parameters_;
isheriff6f8d6862016-05-26 11:24:55 -07001232 parameters.extensions.push_back(RtpExtension(ext_uri, id));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001233 EXPECT_TRUE(channel_->SetSendParameters(parameters));
pbos@webrtc.org587ef602014-06-16 17:32:02 +00001234 FakeVideoSendStream* send_stream =
1235 AddSendStream(cricket::StreamParams::CreateLegacy(123));
1236
1237 // Verify the send extension id.
1238 ASSERT_EQ(1u, send_stream->GetConfig().rtp.extensions.size());
1239 EXPECT_EQ(id, send_stream->GetConfig().rtp.extensions[0].id);
isheriff6f8d6862016-05-26 11:24:55 -07001240 EXPECT_EQ(ext_uri, send_stream->GetConfig().rtp.extensions[0].uri);
pbos@webrtc.org587ef602014-06-16 17:32:02 +00001241 // Verify call with same set of extensions returns true.
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001242 EXPECT_TRUE(channel_->SetSendParameters(parameters));
pbos@webrtc.org587ef602014-06-16 17:32:02 +00001243 // Verify that SetSendRtpHeaderExtensions doesn't implicitly add them for
1244 // receivers.
1245 EXPECT_TRUE(AddRecvStream(cricket::StreamParams::CreateLegacy(123))
1246 ->GetConfig()
1247 .rtp.extensions.empty());
1248
pbos@webrtc.orgd1ea06b2014-07-18 09:35:58 +00001249 // Verify that existing RTP header extensions can be removed.
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001250 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
Fredrik Solenberg709ed672015-09-15 12:26:33 +02001251 ASSERT_EQ(1u, fake_call_->GetVideoSendStreams().size());
1252 send_stream = fake_call_->GetVideoSendStreams()[0];
pbos@webrtc.orgd1ea06b2014-07-18 09:35:58 +00001253 EXPECT_TRUE(send_stream->GetConfig().rtp.extensions.empty());
1254
1255 // Verify that adding receive RTP header extensions adds them for existing
1256 // streams.
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001257 EXPECT_TRUE(channel_->SetSendParameters(parameters));
Fredrik Solenberg709ed672015-09-15 12:26:33 +02001258 send_stream = fake_call_->GetVideoSendStreams()[0];
pbos@webrtc.orgd1ea06b2014-07-18 09:35:58 +00001259 ASSERT_EQ(1u, send_stream->GetConfig().rtp.extensions.size());
1260 EXPECT_EQ(id, send_stream->GetConfig().rtp.extensions[0].id);
isheriff6f8d6862016-05-26 11:24:55 -07001261 EXPECT_EQ(ext_uri, send_stream->GetConfig().rtp.extensions[0].uri);
pbos@webrtc.org587ef602014-06-16 17:32:02 +00001262 }
1263
isheriff6f8d6862016-05-26 11:24:55 -07001264 void TestSetRecvRtpHeaderExtensions(const std::string& ext_uri) {
pbos@webrtc.org587ef602014-06-16 17:32:02 +00001265 // Enable extension.
1266 const int id = 1;
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001267 cricket::VideoRecvParameters parameters = recv_parameters_;
isheriff6f8d6862016-05-26 11:24:55 -07001268 parameters.extensions.push_back(RtpExtension(ext_uri, id));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001269 EXPECT_TRUE(channel_->SetRecvParameters(parameters));
pbos@webrtc.org587ef602014-06-16 17:32:02 +00001270
1271 FakeVideoReceiveStream* recv_stream =
1272 AddRecvStream(cricket::StreamParams::CreateLegacy(123));
1273
1274 // Verify the recv extension id.
1275 ASSERT_EQ(1u, recv_stream->GetConfig().rtp.extensions.size());
1276 EXPECT_EQ(id, recv_stream->GetConfig().rtp.extensions[0].id);
isheriff6f8d6862016-05-26 11:24:55 -07001277 EXPECT_EQ(ext_uri, recv_stream->GetConfig().rtp.extensions[0].uri);
pbos@webrtc.org587ef602014-06-16 17:32:02 +00001278 // Verify call with same set of extensions returns true.
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001279 EXPECT_TRUE(channel_->SetRecvParameters(parameters));
pbos@webrtc.orgd1ea06b2014-07-18 09:35:58 +00001280
pbos@webrtc.org587ef602014-06-16 17:32:02 +00001281 // Verify that SetRecvRtpHeaderExtensions doesn't implicitly add them for
1282 // senders.
1283 EXPECT_TRUE(AddSendStream(cricket::StreamParams::CreateLegacy(123))
1284 ->GetConfig()
1285 .rtp.extensions.empty());
1286
pbos@webrtc.orgd1ea06b2014-07-18 09:35:58 +00001287 // Verify that existing RTP header extensions can be removed.
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001288 EXPECT_TRUE(channel_->SetRecvParameters(recv_parameters_));
Fredrik Solenberg709ed672015-09-15 12:26:33 +02001289 ASSERT_EQ(1u, fake_call_->GetVideoReceiveStreams().size());
1290 recv_stream = fake_call_->GetVideoReceiveStreams()[0];
pbos@webrtc.orgd1ea06b2014-07-18 09:35:58 +00001291 EXPECT_TRUE(recv_stream->GetConfig().rtp.extensions.empty());
1292
1293 // Verify that adding receive RTP header extensions adds them for existing
1294 // streams.
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001295 EXPECT_TRUE(channel_->SetRecvParameters(parameters));
Fredrik Solenberg709ed672015-09-15 12:26:33 +02001296 recv_stream = fake_call_->GetVideoReceiveStreams()[0];
pbos@webrtc.orgd1ea06b2014-07-18 09:35:58 +00001297 ASSERT_EQ(1u, recv_stream->GetConfig().rtp.extensions.size());
1298 EXPECT_EQ(id, recv_stream->GetConfig().rtp.extensions[0].id);
isheriff6f8d6862016-05-26 11:24:55 -07001299 EXPECT_EQ(ext_uri, recv_stream->GetConfig().rtp.extensions[0].uri);
pbos@webrtc.org587ef602014-06-16 17:32:02 +00001300 }
1301
Stefan Holmerbbaf3632015-10-29 18:53:23 +01001302 void TestExtensionFilter(const std::vector<std::string>& extensions,
1303 const std::string& expected_extension) {
1304 cricket::VideoSendParameters parameters = send_parameters_;
1305 int expected_id = -1;
1306 int id = 1;
1307 for (const std::string& extension : extensions) {
1308 if (extension == expected_extension)
1309 expected_id = id;
isheriff6f8d6862016-05-26 11:24:55 -07001310 parameters.extensions.push_back(RtpExtension(extension, id++));
Stefan Holmerbbaf3632015-10-29 18:53:23 +01001311 }
1312 EXPECT_TRUE(channel_->SetSendParameters(parameters));
1313 FakeVideoSendStream* send_stream =
1314 AddSendStream(cricket::StreamParams::CreateLegacy(123));
1315
1316 // Verify that only one of them has been set, and that it is the one with
1317 // highest priority (transport sequence number).
1318 ASSERT_EQ(1u, send_stream->GetConfig().rtp.extensions.size());
1319 EXPECT_EQ(expected_id, send_stream->GetConfig().rtp.extensions[0].id);
1320 EXPECT_EQ(expected_extension,
isheriff6f8d6862016-05-26 11:24:55 -07001321 send_stream->GetConfig().rtp.extensions[0].uri);
Stefan Holmerbbaf3632015-10-29 18:53:23 +01001322 }
1323
asapersson3c81a1a2017-06-14 05:52:21 -07001324 void TestDegradationPreference(bool resolution_scaling_enabled,
1325 bool fps_scaling_enabled);
1326
Erik Språngefbde372015-04-29 16:21:28 +02001327 void TestCpuAdaptation(bool enable_overuse, bool is_screenshare);
Peter Boström3548dd22015-05-22 18:48:36 +02001328 void TestReceiverLocalSsrcConfiguration(bool receiver_first);
magjed509e4fe2016-11-18 01:34:11 -08001329 void TestReceiveUnsignaledSsrcPacket(uint8_t payload_type,
1330 bool expect_created_receive_stream);
pbos@webrtc.org42684be2014-10-03 11:25:45 +00001331
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001332 FakeVideoSendStream* SetDenoisingOption(
nisse05103312016-03-16 02:22:50 -07001333 uint32_t ssrc,
nisse0db023a2016-03-01 04:29:59 -08001334 cricket::FakeVideoCapturer* capturer,
1335 bool enabled) {
nisse05103312016-03-16 02:22:50 -07001336 cricket::VideoOptions options;
1337 options.video_noise_reduction = rtc::Optional<bool>(enabled);
deadbeef5a4a75a2016-06-02 16:23:38 -07001338 EXPECT_TRUE(channel_->SetVideoSend(ssrc, true, &options, capturer));
nisse0db023a2016-03-01 04:29:59 -08001339 // Options only take effect on the next frame.
1340 EXPECT_TRUE(capturer->CaptureFrame());
1341
Erik Språng143cec12015-04-28 10:01:41 +02001342 return fake_call_->GetVideoSendStreams().back();
1343 }
1344
Peter Boström2feafdb2015-09-09 14:32:14 +02001345 FakeVideoSendStream* SetUpSimulcast(bool enabled, bool with_rtx) {
1346 const int kRtxSsrcOffset = 0xDEADBEEF;
Erik Språng143cec12015-04-28 10:01:41 +02001347 last_ssrc_ += 3;
Peter Boström2feafdb2015-09-09 14:32:14 +02001348 std::vector<uint32_t> ssrcs;
1349 std::vector<uint32_t> rtx_ssrcs;
1350 uint32_t num_streams = enabled ? 3 : 1;
1351 for (uint32_t i = 0; i < num_streams; ++i) {
1352 uint32_t ssrc = last_ssrc_ + i;
1353 ssrcs.push_back(ssrc);
1354 if (with_rtx) {
1355 rtx_ssrcs.push_back(ssrc + kRtxSsrcOffset);
1356 }
Erik Språng143cec12015-04-28 10:01:41 +02001357 }
Peter Boström2feafdb2015-09-09 14:32:14 +02001358 if (with_rtx) {
1359 return AddSendStream(
1360 cricket::CreateSimWithRtxStreamParams("cname", ssrcs, rtx_ssrcs));
1361 }
1362 return AddSendStream(CreateSimStreamParams("cname", ssrcs));
Erik Språng143cec12015-04-28 10:01:41 +02001363 }
1364
perkjfa10b552016-10-02 23:45:26 -07001365 int GetMaxEncoderBitrate() {
skvladdc1c62c2016-03-16 19:07:43 -07001366 std::vector<FakeVideoSendStream*> streams =
1367 fake_call_->GetVideoSendStreams();
perkjfa10b552016-10-02 23:45:26 -07001368 EXPECT_EQ(1u, streams.size());
skvladdc1c62c2016-03-16 19:07:43 -07001369 FakeVideoSendStream* stream = streams[streams.size() - 1];
perkjfa10b552016-10-02 23:45:26 -07001370 EXPECT_EQ(1, stream->GetEncoderConfig().number_of_streams);
1371 return stream->GetVideoStreams()[0].max_bitrate_bps;
skvladdc1c62c2016-03-16 19:07:43 -07001372 }
1373
perkjfa10b552016-10-02 23:45:26 -07001374 void SetAndExpectMaxBitrate(int global_max,
skvladdc1c62c2016-03-16 19:07:43 -07001375 int stream_max,
1376 int expected_encoder_bitrate) {
1377 VideoSendParameters limited_send_params = send_parameters_;
1378 limited_send_params.max_bandwidth_bps = global_max;
1379 EXPECT_TRUE(channel_->SetSendParameters(limited_send_params));
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001380 webrtc::RtpParameters parameters =
1381 channel_->GetRtpSendParameters(last_ssrc_);
skvladdc1c62c2016-03-16 19:07:43 -07001382 EXPECT_EQ(1UL, parameters.encodings.size());
deadbeefe702b302017-02-04 12:09:01 -08001383 parameters.encodings[0].max_bitrate_bps = rtc::Optional<int>(stream_max);
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001384 EXPECT_TRUE(channel_->SetRtpSendParameters(last_ssrc_, parameters));
skvladdc1c62c2016-03-16 19:07:43 -07001385 // Read back the parameteres and verify they have the correct value
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001386 parameters = channel_->GetRtpSendParameters(last_ssrc_);
skvladdc1c62c2016-03-16 19:07:43 -07001387 EXPECT_EQ(1UL, parameters.encodings.size());
deadbeefe702b302017-02-04 12:09:01 -08001388 EXPECT_EQ(rtc::Optional<int>(stream_max),
1389 parameters.encodings[0].max_bitrate_bps);
skvladdc1c62c2016-03-16 19:07:43 -07001390 // Verify that the new value propagated down to the encoder
perkjfa10b552016-10-02 23:45:26 -07001391 EXPECT_EQ(expected_encoder_bitrate, GetMaxEncoderBitrate());
skvladdc1c62c2016-03-16 19:07:43 -07001392 }
1393
kwiberg686a8ef2016-02-26 03:00:35 -08001394 std::unique_ptr<FakeCall> fake_call_;
1395 std::unique_ptr<VideoMediaChannel> channel_;
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001396 cricket::VideoSendParameters send_parameters_;
1397 cricket::VideoRecvParameters recv_parameters_;
Peter Boström0c4e06b2015-10-07 12:23:21 +02001398 uint32_t last_ssrc_;
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001399};
1400
eladalonf1841382017-06-12 01:16:46 -07001401TEST_F(WebRtcVideoChannelTest, SetsSyncGroupFromSyncLabel) {
Peter Boström0c4e06b2015-10-07 12:23:21 +02001402 const uint32_t kVideoSsrc = 123;
pbos8fc7fa72015-07-15 08:02:58 -07001403 const std::string kSyncLabel = "AvSyncLabel";
1404
1405 cricket::StreamParams sp = cricket::StreamParams::CreateLegacy(kVideoSsrc);
1406 sp.sync_label = kSyncLabel;
1407 EXPECT_TRUE(channel_->AddRecvStream(sp));
1408
1409 EXPECT_EQ(1, fake_call_->GetVideoReceiveStreams().size());
1410 EXPECT_EQ(kSyncLabel,
1411 fake_call_->GetVideoReceiveStreams()[0]->GetConfig().sync_group)
1412 << "SyncGroup should be set based on sync_label";
1413}
1414
eladalonf1841382017-06-12 01:16:46 -07001415TEST_F(WebRtcVideoChannelTest, RecvStreamWithSimAndRtx) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001416 cricket::VideoSendParameters parameters;
1417 parameters.codecs = engine_.codecs();
1418 EXPECT_TRUE(channel_->SetSendParameters(parameters));
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001419 EXPECT_TRUE(channel_->SetSend(true));
nisse4b4dc862016-02-17 05:25:36 -08001420 parameters.conference_mode = true;
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001421 EXPECT_TRUE(channel_->SetSendParameters(parameters));
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001422
1423 // Send side.
Peter Boström0c4e06b2015-10-07 12:23:21 +02001424 const std::vector<uint32_t> ssrcs = MAKE_VECTOR(kSsrcs1);
1425 const std::vector<uint32_t> rtx_ssrcs = MAKE_VECTOR(kRtxSsrcs1);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001426 FakeVideoSendStream* send_stream = AddSendStream(
1427 cricket::CreateSimWithRtxStreamParams("cname", ssrcs, rtx_ssrcs));
1428
1429 ASSERT_EQ(rtx_ssrcs.size(), send_stream->GetConfig().rtp.rtx.ssrcs.size());
1430 for (size_t i = 0; i < rtx_ssrcs.size(); ++i)
1431 EXPECT_EQ(rtx_ssrcs[i], send_stream->GetConfig().rtp.rtx.ssrcs[i]);
1432
1433 // Receiver side.
1434 FakeVideoReceiveStream* recv_stream = AddRecvStream(
1435 cricket::CreateSimWithRtxStreamParams("cname", ssrcs, rtx_ssrcs));
nisse26e3abb2017-08-25 04:44:25 -07001436 EXPECT_FALSE(
1437 recv_stream->GetConfig().rtp.rtx_associated_payload_types.empty());
nisseca5706d2017-09-11 02:32:16 -07001438 EXPECT_TRUE(VerifyRtxReceiveAssociations(recv_stream->GetConfig()))
Peter Boströmd8b01092016-05-12 16:44:36 +02001439 << "RTX should be mapped for all decoders/payload types.";
nisseca5706d2017-09-11 02:32:16 -07001440 EXPECT_TRUE(HasRtxReceiveAssociation(recv_stream->GetConfig(),
1441 GetEngineCodec("red").id))
1442 << "RTX should be mapped for the RED payload type";
1443
brandtr14742122017-01-27 04:53:07 -08001444 EXPECT_EQ(rtx_ssrcs[0], recv_stream->GetConfig().rtp.rtx_ssrc);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001445}
1446
eladalonf1841382017-06-12 01:16:46 -07001447TEST_F(WebRtcVideoChannelTest, RecvStreamWithRtx) {
pbos@webrtc.orge322a172014-06-13 11:47:28 +00001448 // Setup one channel with an associated RTX stream.
1449 cricket::StreamParams params =
1450 cricket::StreamParams::CreateLegacy(kSsrcs1[0]);
1451 params.AddFidSsrc(kSsrcs1[0], kRtxSsrcs1[0]);
1452 FakeVideoReceiveStream* recv_stream = AddRecvStream(params);
brandtr14742122017-01-27 04:53:07 -08001453 EXPECT_EQ(kRtxSsrcs1[0], recv_stream->GetConfig().rtp.rtx_ssrc);
nisseca5706d2017-09-11 02:32:16 -07001454
1455 EXPECT_TRUE(VerifyRtxReceiveAssociations(recv_stream->GetConfig()))
1456 << "RTX should be mapped for all decoders/payload types.";
1457 EXPECT_TRUE(HasRtxReceiveAssociation(recv_stream->GetConfig(),
1458 GetEngineCodec("red").id))
1459 << "RTX should be mapped for the RED payload type";
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001460}
1461
eladalonf1841382017-06-12 01:16:46 -07001462TEST_F(WebRtcVideoChannelTest, RecvStreamNoRtx) {
pbos@webrtc.orge322a172014-06-13 11:47:28 +00001463 // Setup one channel without an associated RTX stream.
1464 cricket::StreamParams params =
1465 cricket::StreamParams::CreateLegacy(kSsrcs1[0]);
1466 FakeVideoReceiveStream* recv_stream = AddRecvStream(params);
brandtr14742122017-01-27 04:53:07 -08001467 ASSERT_EQ(0U, recv_stream->GetConfig().rtp.rtx_ssrc);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001468}
1469
eladalonf1841382017-06-12 01:16:46 -07001470TEST_F(WebRtcVideoChannelTest, NoHeaderExtesionsByDefault) {
pbos@webrtc.org587ef602014-06-16 17:32:02 +00001471 FakeVideoSendStream* send_stream =
1472 AddSendStream(cricket::StreamParams::CreateLegacy(kSsrcs1[0]));
1473 ASSERT_TRUE(send_stream->GetConfig().rtp.extensions.empty());
1474
1475 FakeVideoReceiveStream* recv_stream =
1476 AddRecvStream(cricket::StreamParams::CreateLegacy(kSsrcs1[0]));
1477 ASSERT_TRUE(recv_stream->GetConfig().rtp.extensions.empty());
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001478}
1479
pbos@webrtc.org587ef602014-06-16 17:32:02 +00001480// Test support for RTP timestamp offset header extension.
eladalonf1841382017-06-12 01:16:46 -07001481TEST_F(WebRtcVideoChannelTest, SendRtpTimestampOffsetHeaderExtensions) {
isheriff6f8d6862016-05-26 11:24:55 -07001482 TestSetSendRtpHeaderExtensions(RtpExtension::kTimestampOffsetUri);
pbos@webrtc.org587ef602014-06-16 17:32:02 +00001483}
isheriff6f8d6862016-05-26 11:24:55 -07001484
eladalonf1841382017-06-12 01:16:46 -07001485TEST_F(WebRtcVideoChannelTest, RecvRtpTimestampOffsetHeaderExtensions) {
isheriff6f8d6862016-05-26 11:24:55 -07001486 TestSetRecvRtpHeaderExtensions(RtpExtension::kTimestampOffsetUri);
pbos@webrtc.org587ef602014-06-16 17:32:02 +00001487}
1488
1489// Test support for absolute send time header extension.
eladalonf1841382017-06-12 01:16:46 -07001490TEST_F(WebRtcVideoChannelTest, SendAbsoluteSendTimeHeaderExtensions) {
isheriff6f8d6862016-05-26 11:24:55 -07001491 TestSetSendRtpHeaderExtensions(RtpExtension::kAbsSendTimeUri);
pbos@webrtc.org587ef602014-06-16 17:32:02 +00001492}
isheriff6f8d6862016-05-26 11:24:55 -07001493
eladalonf1841382017-06-12 01:16:46 -07001494TEST_F(WebRtcVideoChannelTest, RecvAbsoluteSendTimeHeaderExtensions) {
isheriff6f8d6862016-05-26 11:24:55 -07001495 TestSetRecvRtpHeaderExtensions(RtpExtension::kAbsSendTimeUri);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001496}
1497
eladalonf1841382017-06-12 01:16:46 -07001498TEST_F(WebRtcVideoChannelTest, FiltersExtensionsPicksTransportSeqNum) {
Stefan Holmerbbaf3632015-10-29 18:53:23 +01001499 // Enable three redundant extensions.
1500 std::vector<std::string> extensions;
isheriff6f8d6862016-05-26 11:24:55 -07001501 extensions.push_back(RtpExtension::kAbsSendTimeUri);
1502 extensions.push_back(RtpExtension::kTimestampOffsetUri);
1503 extensions.push_back(RtpExtension::kTransportSequenceNumberUri);
1504 TestExtensionFilter(extensions, RtpExtension::kTransportSequenceNumberUri);
Stefan Holmerbbaf3632015-10-29 18:53:23 +01001505}
1506
eladalonf1841382017-06-12 01:16:46 -07001507TEST_F(WebRtcVideoChannelTest, FiltersExtensionsPicksAbsSendTime) {
Stefan Holmerbbaf3632015-10-29 18:53:23 +01001508 // Enable two redundant extensions.
1509 std::vector<std::string> extensions;
isheriff6f8d6862016-05-26 11:24:55 -07001510 extensions.push_back(RtpExtension::kAbsSendTimeUri);
1511 extensions.push_back(RtpExtension::kTimestampOffsetUri);
1512 TestExtensionFilter(extensions, RtpExtension::kAbsSendTimeUri);
Stefan Holmerbbaf3632015-10-29 18:53:23 +01001513}
1514
stefanc1aeaf02015-10-15 07:26:07 -07001515// Test support for transport sequence number header extension.
eladalonf1841382017-06-12 01:16:46 -07001516TEST_F(WebRtcVideoChannelTest, SendTransportSequenceNumberHeaderExtensions) {
isheriff6f8d6862016-05-26 11:24:55 -07001517 TestSetSendRtpHeaderExtensions(RtpExtension::kTransportSequenceNumberUri);
stefanc1aeaf02015-10-15 07:26:07 -07001518}
eladalonf1841382017-06-12 01:16:46 -07001519TEST_F(WebRtcVideoChannelTest, RecvTransportSequenceNumberHeaderExtensions) {
isheriff6f8d6862016-05-26 11:24:55 -07001520 TestSetRecvRtpHeaderExtensions(RtpExtension::kTransportSequenceNumberUri);
stefanc1aeaf02015-10-15 07:26:07 -07001521}
1522
Guo-wei Shieh64c1e8c2015-04-01 15:33:06 -07001523// Test support for video rotation header extension.
eladalonf1841382017-06-12 01:16:46 -07001524TEST_F(WebRtcVideoChannelTest, SendVideoRotationHeaderExtensions) {
isheriff6f8d6862016-05-26 11:24:55 -07001525 TestSetSendRtpHeaderExtensions(RtpExtension::kVideoRotationUri);
Guo-wei Shieh64c1e8c2015-04-01 15:33:06 -07001526}
eladalonf1841382017-06-12 01:16:46 -07001527TEST_F(WebRtcVideoChannelTest, RecvVideoRotationHeaderExtensions) {
isheriff6f8d6862016-05-26 11:24:55 -07001528 TestSetRecvRtpHeaderExtensions(RtpExtension::kVideoRotationUri);
Guo-wei Shieh64c1e8c2015-04-01 15:33:06 -07001529}
1530
eladalonf1841382017-06-12 01:16:46 -07001531TEST_F(WebRtcVideoChannelTest, IdenticalSendExtensionsDoesntRecreateStream) {
Stefan Holmerbbaf3632015-10-29 18:53:23 +01001532 const int kAbsSendTimeId = 1;
1533 const int kVideoRotationId = 2;
isheriff6f8d6862016-05-26 11:24:55 -07001534 send_parameters_.extensions.push_back(
1535 RtpExtension(RtpExtension::kAbsSendTimeUri, kAbsSendTimeId));
1536 send_parameters_.extensions.push_back(
1537 RtpExtension(RtpExtension::kVideoRotationUri, kVideoRotationId));
pbos@webrtc.orgc37e72e2015-01-05 18:51:13 +00001538
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001539 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
pbos@webrtc.orgc37e72e2015-01-05 18:51:13 +00001540 FakeVideoSendStream* send_stream =
1541 AddSendStream(cricket::StreamParams::CreateLegacy(123));
1542
1543 EXPECT_EQ(1, fake_call_->GetNumCreatedSendStreams());
Stefan Holmerbbaf3632015-10-29 18:53:23 +01001544 ASSERT_EQ(2u, send_stream->GetConfig().rtp.extensions.size());
pbos@webrtc.orgc37e72e2015-01-05 18:51:13 +00001545
1546 // Setting the same extensions (even if in different order) shouldn't
1547 // reallocate the stream.
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001548 std::reverse(send_parameters_.extensions.begin(),
1549 send_parameters_.extensions.end());
1550 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
pbos@webrtc.orgc37e72e2015-01-05 18:51:13 +00001551
1552 EXPECT_EQ(1, fake_call_->GetNumCreatedSendStreams());
1553
1554 // Setting different extensions should recreate the stream.
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001555 send_parameters_.extensions.resize(1);
1556 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
pbos@webrtc.orgc37e72e2015-01-05 18:51:13 +00001557
1558 EXPECT_EQ(2, fake_call_->GetNumCreatedSendStreams());
1559}
1560
eladalonf1841382017-06-12 01:16:46 -07001561TEST_F(WebRtcVideoChannelTest, IdenticalRecvExtensionsDoesntRecreateStream) {
pbos@webrtc.orgc37e72e2015-01-05 18:51:13 +00001562 const int kTOffsetId = 1;
1563 const int kAbsSendTimeId = 2;
Guo-wei Shieh64c1e8c2015-04-01 15:33:06 -07001564 const int kVideoRotationId = 3;
isheriff6f8d6862016-05-26 11:24:55 -07001565 recv_parameters_.extensions.push_back(
1566 RtpExtension(RtpExtension::kAbsSendTimeUri, kAbsSendTimeId));
1567 recv_parameters_.extensions.push_back(
1568 RtpExtension(RtpExtension::kTimestampOffsetUri, kTOffsetId));
1569 recv_parameters_.extensions.push_back(
1570 RtpExtension(RtpExtension::kVideoRotationUri, kVideoRotationId));
pbos@webrtc.orgc37e72e2015-01-05 18:51:13 +00001571
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001572 EXPECT_TRUE(channel_->SetRecvParameters(recv_parameters_));
Peter Boström54be3e02015-05-25 15:04:24 +02001573 FakeVideoReceiveStream* recv_stream =
pbos@webrtc.orgc37e72e2015-01-05 18:51:13 +00001574 AddRecvStream(cricket::StreamParams::CreateLegacy(123));
1575
1576 EXPECT_EQ(1, fake_call_->GetNumCreatedReceiveStreams());
Peter Boström54be3e02015-05-25 15:04:24 +02001577 ASSERT_EQ(3u, recv_stream->GetConfig().rtp.extensions.size());
pbos@webrtc.orgc37e72e2015-01-05 18:51:13 +00001578
1579 // Setting the same extensions (even if in different order) shouldn't
1580 // reallocate the stream.
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001581 std::reverse(recv_parameters_.extensions.begin(),
1582 recv_parameters_.extensions.end());
1583 EXPECT_TRUE(channel_->SetRecvParameters(recv_parameters_));
pbos@webrtc.orgc37e72e2015-01-05 18:51:13 +00001584
1585 EXPECT_EQ(1, fake_call_->GetNumCreatedReceiveStreams());
1586
1587 // Setting different extensions should recreate the stream.
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001588 recv_parameters_.extensions.resize(1);
1589 EXPECT_TRUE(channel_->SetRecvParameters(recv_parameters_));
pbos@webrtc.orgc37e72e2015-01-05 18:51:13 +00001590
1591 EXPECT_EQ(2, fake_call_->GetNumCreatedReceiveStreams());
1592}
1593
eladalonf1841382017-06-12 01:16:46 -07001594TEST_F(WebRtcVideoChannelTest,
pbos@webrtc.org42684be2014-10-03 11:25:45 +00001595 SetSendRtpHeaderExtensionsExcludeUnsupportedExtensions) {
pbos@webrtc.org3c107582014-07-20 15:27:35 +00001596 const int kUnsupportedId = 1;
1597 const int kTOffsetId = 2;
1598
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001599 send_parameters_.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001600 RtpExtension(kUnsupportedExtensionName, kUnsupportedId));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001601 send_parameters_.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001602 RtpExtension(RtpExtension::kTimestampOffsetUri, kTOffsetId));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001603 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
pbos@webrtc.org3c107582014-07-20 15:27:35 +00001604 FakeVideoSendStream* send_stream =
1605 AddSendStream(cricket::StreamParams::CreateLegacy(123));
1606
1607 // Only timestamp offset extension is set to send stream,
1608 // unsupported rtp extension is ignored.
1609 ASSERT_EQ(1u, send_stream->GetConfig().rtp.extensions.size());
isheriff6f8d6862016-05-26 11:24:55 -07001610 EXPECT_STREQ(RtpExtension::kTimestampOffsetUri,
1611 send_stream->GetConfig().rtp.extensions[0].uri.c_str());
pbos@webrtc.org3c107582014-07-20 15:27:35 +00001612}
1613
eladalonf1841382017-06-12 01:16:46 -07001614TEST_F(WebRtcVideoChannelTest,
pbos@webrtc.org42684be2014-10-03 11:25:45 +00001615 SetRecvRtpHeaderExtensionsExcludeUnsupportedExtensions) {
pbos@webrtc.org3c107582014-07-20 15:27:35 +00001616 const int kUnsupportedId = 1;
1617 const int kTOffsetId = 2;
1618
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001619 recv_parameters_.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001620 RtpExtension(kUnsupportedExtensionName, kUnsupportedId));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001621 recv_parameters_.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001622 RtpExtension(RtpExtension::kTimestampOffsetUri, kTOffsetId));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001623 EXPECT_TRUE(channel_->SetRecvParameters(recv_parameters_));
pbos@webrtc.org3c107582014-07-20 15:27:35 +00001624 FakeVideoReceiveStream* recv_stream =
1625 AddRecvStream(cricket::StreamParams::CreateLegacy(123));
1626
1627 // Only timestamp offset extension is set to receive stream,
1628 // unsupported rtp extension is ignored.
1629 ASSERT_EQ(1u, recv_stream->GetConfig().rtp.extensions.size());
isheriff6f8d6862016-05-26 11:24:55 -07001630 EXPECT_STREQ(RtpExtension::kTimestampOffsetUri,
1631 recv_stream->GetConfig().rtp.extensions[0].uri.c_str());
pbos@webrtc.org3c107582014-07-20 15:27:35 +00001632}
1633
eladalonf1841382017-06-12 01:16:46 -07001634TEST_F(WebRtcVideoChannelTest, SetSendRtpHeaderExtensionsRejectsIncorrectIds) {
Peter Boström23914fe2015-03-31 15:08:04 +02001635 const int kIncorrectIds[] = {-2, -1, 0, 15, 16};
pkasting@chromium.orge7a4a122015-01-28 21:36:55 +00001636 for (size_t i = 0; i < arraysize(kIncorrectIds); ++i) {
isheriff6f8d6862016-05-26 11:24:55 -07001637 send_parameters_.extensions.push_back(
1638 RtpExtension(RtpExtension::kTimestampOffsetUri, kIncorrectIds[i]));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001639 EXPECT_FALSE(channel_->SetSendParameters(send_parameters_))
pbos@webrtc.org3c107582014-07-20 15:27:35 +00001640 << "Bad extension id '" << kIncorrectIds[i] << "' accepted.";
1641 }
1642}
1643
eladalonf1841382017-06-12 01:16:46 -07001644TEST_F(WebRtcVideoChannelTest, SetRecvRtpHeaderExtensionsRejectsIncorrectIds) {
Peter Boström23914fe2015-03-31 15:08:04 +02001645 const int kIncorrectIds[] = {-2, -1, 0, 15, 16};
pkasting@chromium.orge7a4a122015-01-28 21:36:55 +00001646 for (size_t i = 0; i < arraysize(kIncorrectIds); ++i) {
isheriff6f8d6862016-05-26 11:24:55 -07001647 recv_parameters_.extensions.push_back(
1648 RtpExtension(RtpExtension::kTimestampOffsetUri, kIncorrectIds[i]));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001649 EXPECT_FALSE(channel_->SetRecvParameters(recv_parameters_))
pbos@webrtc.org3c107582014-07-20 15:27:35 +00001650 << "Bad extension id '" << kIncorrectIds[i] << "' accepted.";
1651 }
1652}
1653
eladalonf1841382017-06-12 01:16:46 -07001654TEST_F(WebRtcVideoChannelTest, SetSendRtpHeaderExtensionsRejectsDuplicateIds) {
pbos@webrtc.org3c107582014-07-20 15:27:35 +00001655 const int id = 1;
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001656 send_parameters_.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001657 RtpExtension(RtpExtension::kTimestampOffsetUri, id));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001658 send_parameters_.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001659 RtpExtension(RtpExtension::kAbsSendTimeUri, id));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001660 EXPECT_FALSE(channel_->SetSendParameters(send_parameters_));
pbos@webrtc.org3c107582014-07-20 15:27:35 +00001661
1662 // Duplicate entries are also not supported.
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001663 send_parameters_.extensions.clear();
1664 send_parameters_.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001665 RtpExtension(RtpExtension::kTimestampOffsetUri, id));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001666 send_parameters_.extensions.push_back(send_parameters_.extensions.back());
1667 EXPECT_FALSE(channel_->SetSendParameters(send_parameters_));
pbos@webrtc.org3c107582014-07-20 15:27:35 +00001668}
1669
eladalonf1841382017-06-12 01:16:46 -07001670TEST_F(WebRtcVideoChannelTest, SetRecvRtpHeaderExtensionsRejectsDuplicateIds) {
pbos@webrtc.org3c107582014-07-20 15:27:35 +00001671 const int id = 1;
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001672 recv_parameters_.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001673 RtpExtension(RtpExtension::kTimestampOffsetUri, id));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001674 recv_parameters_.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001675 RtpExtension(RtpExtension::kAbsSendTimeUri, id));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001676 EXPECT_FALSE(channel_->SetRecvParameters(recv_parameters_));
pbos@webrtc.org3c107582014-07-20 15:27:35 +00001677
1678 // Duplicate entries are also not supported.
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001679 recv_parameters_.extensions.clear();
1680 recv_parameters_.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -07001681 RtpExtension(RtpExtension::kTimestampOffsetUri, id));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001682 recv_parameters_.extensions.push_back(recv_parameters_.extensions.back());
1683 EXPECT_FALSE(channel_->SetRecvParameters(recv_parameters_));
pbos@webrtc.org3c107582014-07-20 15:27:35 +00001684}
1685
eladalonf1841382017-06-12 01:16:46 -07001686TEST_F(WebRtcVideoChannelTest, AddRecvStreamOnlyUsesOneReceiveStream) {
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001687 EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(1)));
pbos@webrtc.org42684be2014-10-03 11:25:45 +00001688 EXPECT_EQ(1u, fake_call_->GetVideoReceiveStreams().size());
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001689}
1690
eladalonf1841382017-06-12 01:16:46 -07001691TEST_F(WebRtcVideoChannelTest, RtcpIsCompoundByDefault) {
Peter Boströmd7da1202015-06-05 14:09:38 +02001692 FakeVideoReceiveStream* stream = AddRecvStream();
pbosda903ea2015-10-02 02:36:56 -07001693 EXPECT_EQ(webrtc::RtcpMode::kCompound, stream->GetConfig().rtp.rtcp_mode);
Peter Boströmd7da1202015-06-05 14:09:38 +02001694}
1695
eladalonf1841382017-06-12 01:16:46 -07001696TEST_F(WebRtcVideoChannelTest, RembIsEnabledByDefault) {
pbos@webrtc.org257e1302014-07-25 19:01:32 +00001697 FakeVideoReceiveStream* stream = AddRecvStream();
1698 EXPECT_TRUE(stream->GetConfig().rtp.remb);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001699}
1700
eladalonf1841382017-06-12 01:16:46 -07001701TEST_F(WebRtcVideoChannelTest, TransportCcIsEnabledByDefault) {
stefan43edf0f2015-11-20 18:05:48 -08001702 FakeVideoReceiveStream* stream = AddRecvStream();
1703 EXPECT_TRUE(stream->GetConfig().rtp.transport_cc);
1704}
1705
eladalonf1841382017-06-12 01:16:46 -07001706TEST_F(WebRtcVideoChannelTest, RembCanBeEnabledAndDisabled) {
pbos@webrtc.org257e1302014-07-25 19:01:32 +00001707 FakeVideoReceiveStream* stream = AddRecvStream();
1708 EXPECT_TRUE(stream->GetConfig().rtp.remb);
1709
Peter Boström126c03e2015-05-11 12:48:12 +02001710 // Verify that REMB is turned off when send(!) codecs without REMB are set.
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001711 cricket::VideoSendParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08001712 parameters.codecs.push_back(RemoveFeedbackParams(GetEngineCodec("VP8")));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001713 EXPECT_TRUE(parameters.codecs[0].feedback_params.params().empty());
1714 EXPECT_TRUE(channel_->SetSendParameters(parameters));
pbos@webrtc.org42684be2014-10-03 11:25:45 +00001715 stream = fake_call_->GetVideoReceiveStreams()[0];
pbos@webrtc.org257e1302014-07-25 19:01:32 +00001716 EXPECT_FALSE(stream->GetConfig().rtp.remb);
1717
1718 // Verify that REMB is turned on when setting default codecs since the
1719 // default codecs have REMB enabled.
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001720 parameters.codecs = engine_.codecs();
1721 EXPECT_TRUE(channel_->SetSendParameters(parameters));
pbos@webrtc.org42684be2014-10-03 11:25:45 +00001722 stream = fake_call_->GetVideoReceiveStreams()[0];
pbos@webrtc.org257e1302014-07-25 19:01:32 +00001723 EXPECT_TRUE(stream->GetConfig().rtp.remb);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001724}
1725
eladalonf1841382017-06-12 01:16:46 -07001726TEST_F(WebRtcVideoChannelTest, TransportCcCanBeEnabledAndDisabled) {
stefan43edf0f2015-11-20 18:05:48 -08001727 FakeVideoReceiveStream* stream = AddRecvStream();
1728 EXPECT_TRUE(stream->GetConfig().rtp.transport_cc);
1729
1730 // Verify that transport cc feedback is turned off when send(!) codecs without
1731 // transport cc feedback are set.
1732 cricket::VideoSendParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08001733 parameters.codecs.push_back(RemoveFeedbackParams(GetEngineCodec("VP8")));
stefan43edf0f2015-11-20 18:05:48 -08001734 EXPECT_TRUE(parameters.codecs[0].feedback_params.params().empty());
1735 EXPECT_TRUE(channel_->SetSendParameters(parameters));
1736 stream = fake_call_->GetVideoReceiveStreams()[0];
1737 EXPECT_FALSE(stream->GetConfig().rtp.transport_cc);
1738
1739 // Verify that transport cc feedback is turned on when setting default codecs
1740 // since the default codecs have transport cc feedback enabled.
1741 parameters.codecs = engine_.codecs();
1742 EXPECT_TRUE(channel_->SetSendParameters(parameters));
1743 stream = fake_call_->GetVideoReceiveStreams()[0];
1744 EXPECT_TRUE(stream->GetConfig().rtp.transport_cc);
1745}
1746
eladalonf1841382017-06-12 01:16:46 -07001747TEST_F(WebRtcVideoChannelTest, NackIsEnabledByDefault) {
pbos@webrtc.orgf99c2f22014-06-13 12:27:38 +00001748 VerifyCodecHasDefaultFeedbackParams(default_codec_);
1749
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001750 cricket::VideoSendParameters parameters;
1751 parameters.codecs = engine_.codecs();
1752 EXPECT_TRUE(channel_->SetSendParameters(parameters));
pbos@webrtc.org19864742014-05-30 07:35:47 +00001753 EXPECT_TRUE(channel_->SetSend(true));
1754
1755 // Send side.
1756 FakeVideoSendStream* send_stream =
1757 AddSendStream(cricket::StreamParams::CreateLegacy(1));
1758 EXPECT_GT(send_stream->GetConfig().rtp.nack.rtp_history_ms, 0);
1759
1760 // Receiver side.
1761 FakeVideoReceiveStream* recv_stream =
1762 AddRecvStream(cricket::StreamParams::CreateLegacy(1));
1763 EXPECT_GT(recv_stream->GetConfig().rtp.nack.rtp_history_ms, 0);
1764
1765 // Nack history size should match between sender and receiver.
1766 EXPECT_EQ(send_stream->GetConfig().rtp.nack.rtp_history_ms,
1767 recv_stream->GetConfig().rtp.nack.rtp_history_ms);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001768}
1769
eladalonf1841382017-06-12 01:16:46 -07001770TEST_F(WebRtcVideoChannelTest, NackCanBeEnabledAndDisabled) {
Peter Boström67c9df72015-05-11 14:34:58 +02001771 FakeVideoSendStream* send_stream = AddSendStream();
Peter Boström3548dd22015-05-22 18:48:36 +02001772 FakeVideoReceiveStream* recv_stream = AddRecvStream();
Peter Boström67c9df72015-05-11 14:34:58 +02001773
1774 EXPECT_GT(recv_stream->GetConfig().rtp.nack.rtp_history_ms, 0);
1775 EXPECT_GT(send_stream->GetConfig().rtp.nack.rtp_history_ms, 0);
1776
1777 // Verify that NACK is turned off when send(!) codecs without NACK are set.
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001778 cricket::VideoSendParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08001779 parameters.codecs.push_back(RemoveFeedbackParams(GetEngineCodec("VP8")));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001780 EXPECT_TRUE(parameters.codecs[0].feedback_params.params().empty());
1781 EXPECT_TRUE(channel_->SetSendParameters(parameters));
Peter Boström67c9df72015-05-11 14:34:58 +02001782 recv_stream = fake_call_->GetVideoReceiveStreams()[0];
1783 EXPECT_EQ(0, recv_stream->GetConfig().rtp.nack.rtp_history_ms);
1784 send_stream = fake_call_->GetVideoSendStreams()[0];
pbos@webrtc.orgf99c2f22014-06-13 12:27:38 +00001785 EXPECT_EQ(0, send_stream->GetConfig().rtp.nack.rtp_history_ms);
1786
Peter Boström67c9df72015-05-11 14:34:58 +02001787 // Verify that NACK is turned on when setting default codecs since the
1788 // default codecs have NACK enabled.
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001789 parameters.codecs = engine_.codecs();
1790 EXPECT_TRUE(channel_->SetSendParameters(parameters));
Peter Boström67c9df72015-05-11 14:34:58 +02001791 recv_stream = fake_call_->GetVideoReceiveStreams()[0];
1792 EXPECT_GT(recv_stream->GetConfig().rtp.nack.rtp_history_ms, 0);
1793 send_stream = fake_call_->GetVideoSendStreams()[0];
1794 EXPECT_GT(send_stream->GetConfig().rtp.nack.rtp_history_ms, 0);
pbos@webrtc.orgf99c2f22014-06-13 12:27:38 +00001795}
1796
Peter Boströme7ba0862016-03-12 00:02:28 +01001797// This test verifies that new frame sizes reconfigures encoders even though not
1798// (yet) sending. The purpose of this is to permit encoding as quickly as
1799// possible once we start sending. Likely the frames being input are from the
1800// same source that will be sent later, which just means that we're ready
1801// earlier.
eladalonf1841382017-06-12 01:16:46 -07001802TEST_F(WebRtcVideoChannelTest, ReconfiguresEncodersWhenNotSending) {
Peter Boströme7ba0862016-03-12 00:02:28 +01001803 cricket::VideoSendParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08001804 parameters.codecs.push_back(GetEngineCodec("VP8"));
Peter Boströme7ba0862016-03-12 00:02:28 +01001805 ASSERT_TRUE(channel_->SetSendParameters(parameters));
1806 channel_->SetSend(false);
1807
1808 FakeVideoSendStream* stream = AddSendStream();
1809
perkjfa10b552016-10-02 23:45:26 -07001810 // No frames entered.
Peter Boströme7ba0862016-03-12 00:02:28 +01001811 std::vector<webrtc::VideoStream> streams = stream->GetVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07001812 EXPECT_EQ(0u, streams[0].width);
1813 EXPECT_EQ(0u, streams[0].height);
Peter Boströme7ba0862016-03-12 00:02:28 +01001814
1815 cricket::FakeVideoCapturer capturer;
deadbeef5a4a75a2016-06-02 16:23:38 -07001816 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, &capturer));
perkj26752742016-10-24 01:21:16 -07001817 VideoFormat capture_format = capturer.GetSupportedFormats()->front();
1818 EXPECT_EQ(cricket::CS_RUNNING, capturer.Start(capture_format));
Peter Boströme7ba0862016-03-12 00:02:28 +01001819 EXPECT_TRUE(capturer.CaptureFrame());
1820
1821 // Frame entered, should be reconfigured to new dimensions.
1822 streams = stream->GetVideoStreams();
perkj26752742016-10-24 01:21:16 -07001823 EXPECT_EQ(capture_format.width, streams[0].width);
1824 EXPECT_EQ(capture_format.height, streams[0].height);
Peter Boströme7ba0862016-03-12 00:02:28 +01001825
deadbeef5a4a75a2016-06-02 16:23:38 -07001826 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, nullptr));
Peter Boströme7ba0862016-03-12 00:02:28 +01001827}
1828
eladalonf1841382017-06-12 01:16:46 -07001829TEST_F(WebRtcVideoChannelTest, UsesCorrectSettingsForScreencast) {
pbos@webrtc.orgefc82c22014-10-27 13:58:00 +00001830 static const int kScreenshareMinBitrateKbps = 800;
magjed509e4fe2016-11-18 01:34:11 -08001831 cricket::VideoCodec codec = GetEngineCodec("VP8");
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001832 cricket::VideoSendParameters parameters;
1833 parameters.codecs.push_back(codec);
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001834 EXPECT_TRUE(channel_->SetSendParameters(parameters));
pbos@webrtc.orgefc82c22014-10-27 13:58:00 +00001835 AddSendStream();
1836
deadbeef5a4a75a2016-06-02 16:23:38 -07001837 cricket::FakeVideoCapturer capturer;
nisse05103312016-03-16 02:22:50 -07001838 VideoOptions min_bitrate_options;
1839 min_bitrate_options.screencast_min_bitrate_kbps =
1840 rtc::Optional<int>(kScreenshareMinBitrateKbps);
deadbeef5a4a75a2016-06-02 16:23:38 -07001841 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, &min_bitrate_options,
1842 &capturer));
pbos@webrtc.orgefc82c22014-10-27 13:58:00 +00001843 cricket::VideoFormat capture_format_hd =
1844 capturer.GetSupportedFormats()->front();
1845 EXPECT_EQ(1280, capture_format_hd.width);
1846 EXPECT_EQ(720, capture_format_hd.height);
1847 EXPECT_EQ(cricket::CS_RUNNING, capturer.Start(capture_format_hd));
1848
1849 EXPECT_TRUE(channel_->SetSend(true));
1850
1851 EXPECT_TRUE(capturer.CaptureFrame());
1852 ASSERT_EQ(1u, fake_call_->GetVideoSendStreams().size());
1853 FakeVideoSendStream* send_stream = fake_call_->GetVideoSendStreams().front();
1854
1855 EXPECT_EQ(1, send_stream->GetNumberOfSwappedFrames());
1856
1857 // Verify non-screencast settings.
perkj26091b12016-09-01 01:17:40 -07001858 webrtc::VideoEncoderConfig encoder_config =
1859 send_stream->GetEncoderConfig().Copy();
Erik Språng143cec12015-04-28 10:01:41 +02001860 EXPECT_EQ(webrtc::VideoEncoderConfig::ContentType::kRealtimeVideo,
pbos@webrtc.orgefc82c22014-10-27 13:58:00 +00001861 encoder_config.content_type);
perkjfa10b552016-10-02 23:45:26 -07001862 std::vector<webrtc::VideoStream> streams = send_stream->GetVideoStreams();
1863 EXPECT_EQ(capture_format_hd.width, streams.front().width);
1864 EXPECT_EQ(capture_format_hd.height, streams.front().height);
pbos@webrtc.orgefc82c22014-10-27 13:58:00 +00001865 EXPECT_EQ(0, encoder_config.min_transmit_bitrate_bps)
1866 << "Non-screenshare shouldn't use min-transmit bitrate.";
1867
deadbeef5a4a75a2016-06-02 16:23:38 -07001868 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, nullptr));
perkjd533aec2017-01-13 05:57:25 -08001869 EXPECT_EQ(1, send_stream->GetNumberOfSwappedFrames());
nisse05103312016-03-16 02:22:50 -07001870 VideoOptions screencast_options;
1871 screencast_options.is_screencast = rtc::Optional<bool>(true);
deadbeef5a4a75a2016-06-02 16:23:38 -07001872 EXPECT_TRUE(
1873 channel_->SetVideoSend(last_ssrc_, true, &screencast_options, &capturer));
perkj2d5f0912016-02-29 00:04:41 -08001874 EXPECT_TRUE(capturer.CaptureFrame());
sprangf24a0642017-02-28 13:23:26 -08001875 // Send stream recreated after option change.
1876 ASSERT_EQ(2, fake_call_->GetNumCreatedSendStreams());
1877 send_stream = fake_call_->GetVideoSendStreams().front();
1878 EXPECT_EQ(1, send_stream->GetNumberOfSwappedFrames());
pbos@webrtc.orgefc82c22014-10-27 13:58:00 +00001879
1880 // Verify screencast settings.
perkj26091b12016-09-01 01:17:40 -07001881 encoder_config = send_stream->GetEncoderConfig().Copy();
Erik Språng143cec12015-04-28 10:01:41 +02001882 EXPECT_EQ(webrtc::VideoEncoderConfig::ContentType::kScreen,
pbos@webrtc.orgefc82c22014-10-27 13:58:00 +00001883 encoder_config.content_type);
1884 EXPECT_EQ(kScreenshareMinBitrateKbps * 1000,
1885 encoder_config.min_transmit_bitrate_bps);
1886
perkjfa10b552016-10-02 23:45:26 -07001887 streams = send_stream->GetVideoStreams();
1888 EXPECT_EQ(capture_format_hd.width, streams.front().width);
1889 EXPECT_EQ(capture_format_hd.height, streams.front().height);
1890 EXPECT_TRUE(streams[0].temporal_layer_thresholds_bps.empty());
deadbeef5a4a75a2016-06-02 16:23:38 -07001891 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, nullptr));
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001892}
1893
eladalonf1841382017-06-12 01:16:46 -07001894TEST_F(WebRtcVideoChannelTest,
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001895 ConferenceModeScreencastConfiguresTemporalLayer) {
Erik Språng2c4c9142015-06-24 11:24:44 +02001896 static const int kConferenceScreencastTemporalBitrateBps =
1897 ScreenshareLayerConfig::GetDefault().tl0_bitrate_kbps * 1000;
nisse4b4dc862016-02-17 05:25:36 -08001898 send_parameters_.conference_mode = true;
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001899 channel_->SetSendParameters(send_parameters_);
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001900
1901 AddSendStream();
nisse05103312016-03-16 02:22:50 -07001902 VideoOptions options;
1903 options.is_screencast = rtc::Optional<bool>(true);
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001904 cricket::FakeVideoCapturer capturer;
deadbeef5a4a75a2016-06-02 16:23:38 -07001905 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, &options, &capturer));
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001906 cricket::VideoFormat capture_format_hd =
1907 capturer.GetSupportedFormats()->front();
1908 EXPECT_EQ(cricket::CS_RUNNING, capturer.Start(capture_format_hd));
1909
1910 EXPECT_TRUE(channel_->SetSend(true));
1911
1912 EXPECT_TRUE(capturer.CaptureFrame());
1913 ASSERT_EQ(1u, fake_call_->GetVideoSendStreams().size());
1914 FakeVideoSendStream* send_stream = fake_call_->GetVideoSendStreams().front();
1915
perkj26091b12016-09-01 01:17:40 -07001916 webrtc::VideoEncoderConfig encoder_config =
1917 send_stream->GetEncoderConfig().Copy();
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001918
1919 // Verify screencast settings.
perkj26091b12016-09-01 01:17:40 -07001920 encoder_config = send_stream->GetEncoderConfig().Copy();
Erik Språng143cec12015-04-28 10:01:41 +02001921 EXPECT_EQ(webrtc::VideoEncoderConfig::ContentType::kScreen,
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001922 encoder_config.content_type);
perkjfa10b552016-10-02 23:45:26 -07001923
1924 std::vector<webrtc::VideoStream> streams = send_stream->GetVideoStreams();
1925 ASSERT_EQ(1u, streams.size());
1926 ASSERT_EQ(1u, streams[0].temporal_layer_thresholds_bps.size());
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001927 EXPECT_EQ(kConferenceScreencastTemporalBitrateBps,
perkjfa10b552016-10-02 23:45:26 -07001928 streams[0].temporal_layer_thresholds_bps[0]);
pbos@webrtc.orgefc82c22014-10-27 13:58:00 +00001929
deadbeef5a4a75a2016-06-02 16:23:38 -07001930 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, nullptr));
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00001931}
1932
eladalonf1841382017-06-12 01:16:46 -07001933TEST_F(WebRtcVideoChannelTest, SuspendBelowMinBitrateDisabledByDefault) {
pbos@webrtc.org5ff71ab2014-07-23 07:28:56 +00001934 FakeVideoSendStream* stream = AddSendStream();
1935 EXPECT_FALSE(stream->GetConfig().suspend_below_min_bitrate);
1936}
1937
eladalonf1841382017-06-12 01:16:46 -07001938TEST_F(WebRtcVideoChannelTest, SetMediaConfigSuspendBelowMinBitrate) {
kthelgason2bc68642017-02-07 07:02:22 -08001939 MediaConfig media_config = GetMediaConfig();
nisse0db023a2016-03-01 04:29:59 -08001940 media_config.video.suspend_below_min_bitrate = true;
1941
1942 channel_.reset(
1943 engine_.CreateChannel(fake_call_.get(), media_config, VideoOptions()));
Sergey Ulanove2b15012016-11-22 16:08:30 -08001944 channel_->OnReadyToSend(true);
nisse0db023a2016-03-01 04:29:59 -08001945
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001946 channel_->SetSendParameters(send_parameters_);
pbos@webrtc.org5ff71ab2014-07-23 07:28:56 +00001947
1948 FakeVideoSendStream* stream = AddSendStream();
1949 EXPECT_TRUE(stream->GetConfig().suspend_below_min_bitrate);
1950
nisse0db023a2016-03-01 04:29:59 -08001951 media_config.video.suspend_below_min_bitrate = false;
1952 channel_.reset(
1953 engine_.CreateChannel(fake_call_.get(), media_config, VideoOptions()));
Sergey Ulanove2b15012016-11-22 16:08:30 -08001954 channel_->OnReadyToSend(true);
nisse0db023a2016-03-01 04:29:59 -08001955
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001956 channel_->SetSendParameters(send_parameters_);
pbos@webrtc.org5ff71ab2014-07-23 07:28:56 +00001957
nisse0db023a2016-03-01 04:29:59 -08001958 stream = AddSendStream();
pbos@webrtc.org5ff71ab2014-07-23 07:28:56 +00001959 EXPECT_FALSE(stream->GetConfig().suspend_below_min_bitrate);
1960}
1961
eladalonf1841382017-06-12 01:16:46 -07001962TEST_F(WebRtcVideoChannelTest, Vp8DenoisingEnabledByDefault) {
pbos@webrtc.org6f48f1b2014-07-22 16:29:54 +00001963 FakeVideoSendStream* stream = AddSendStream();
1964 webrtc::VideoCodecVP8 vp8_settings;
1965 ASSERT_TRUE(stream->GetVp8Settings(&vp8_settings)) << "No VP8 config set.";
1966 EXPECT_TRUE(vp8_settings.denoisingOn);
1967}
1968
eladalonf1841382017-06-12 01:16:46 -07001969TEST_F(WebRtcVideoChannelTest, VerifyVp8SpecificSettings) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001970 cricket::VideoSendParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08001971 parameters.codecs.push_back(GetEngineCodec("VP8"));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001972 ASSERT_TRUE(channel_->SetSendParameters(parameters));
pbos@webrtc.org6f48f1b2014-07-22 16:29:54 +00001973
Peter Boström2feafdb2015-09-09 14:32:14 +02001974 // Single-stream settings should apply with RTX as well (verifies that we
1975 // check number of regular SSRCs and not StreamParams::ssrcs which contains
1976 // both RTX and regular SSRCs).
1977 FakeVideoSendStream* stream = SetUpSimulcast(false, true);
Erik Språng143cec12015-04-28 10:01:41 +02001978
1979 cricket::FakeVideoCapturer capturer;
Erik Språng143cec12015-04-28 10:01:41 +02001980 EXPECT_EQ(cricket::CS_RUNNING,
1981 capturer.Start(capturer.GetSupportedFormats()->front()));
deadbeef5a4a75a2016-06-02 16:23:38 -07001982 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, &capturer));
Erik Språng143cec12015-04-28 10:01:41 +02001983 channel_->SetSend(true);
1984
1985 EXPECT_TRUE(capturer.CaptureFrame());
1986
pbos4cba4eb2015-10-26 11:18:18 -07001987 webrtc::VideoCodecVP8 vp8_settings;
1988 ASSERT_TRUE(stream->GetVp8Settings(&vp8_settings)) << "No VP8 config set.";
1989 EXPECT_TRUE(vp8_settings.denoisingOn)
1990 << "VP8 denoising should be on by default.";
1991
nisse05103312016-03-16 02:22:50 -07001992 stream = SetDenoisingOption(last_ssrc_, &capturer, false);
Erik Språng143cec12015-04-28 10:01:41 +02001993
pbos@webrtc.org6f48f1b2014-07-22 16:29:54 +00001994 ASSERT_TRUE(stream->GetVp8Settings(&vp8_settings)) << "No VP8 config set.";
1995 EXPECT_FALSE(vp8_settings.denoisingOn);
Erik Språng143cec12015-04-28 10:01:41 +02001996 EXPECT_TRUE(vp8_settings.automaticResizeOn);
1997 EXPECT_TRUE(vp8_settings.frameDroppingOn);
pbos@webrtc.org6f48f1b2014-07-22 16:29:54 +00001998
nisse05103312016-03-16 02:22:50 -07001999 stream = SetDenoisingOption(last_ssrc_, &capturer, true);
pbos@webrtc.org6f48f1b2014-07-22 16:29:54 +00002000
pbos@webrtc.org6f48f1b2014-07-22 16:29:54 +00002001 ASSERT_TRUE(stream->GetVp8Settings(&vp8_settings)) << "No VP8 config set.";
2002 EXPECT_TRUE(vp8_settings.denoisingOn);
Erik Språng143cec12015-04-28 10:01:41 +02002003 EXPECT_TRUE(vp8_settings.automaticResizeOn);
2004 EXPECT_TRUE(vp8_settings.frameDroppingOn);
2005
deadbeef5a4a75a2016-06-02 16:23:38 -07002006 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, nullptr));
Peter Boström2feafdb2015-09-09 14:32:14 +02002007 stream = SetUpSimulcast(true, false);
deadbeef5a4a75a2016-06-02 16:23:38 -07002008 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, &capturer));
Erik Språng143cec12015-04-28 10:01:41 +02002009 channel_->SetSend(true);
2010 EXPECT_TRUE(capturer.CaptureFrame());
2011
2012 EXPECT_EQ(3, stream->GetVideoStreams().size());
2013 ASSERT_TRUE(stream->GetVp8Settings(&vp8_settings)) << "No VP8 config set.";
2014 // Autmatic resize off when using simulcast.
2015 EXPECT_FALSE(vp8_settings.automaticResizeOn);
2016 EXPECT_TRUE(vp8_settings.frameDroppingOn);
2017
2018 // In screen-share mode, denoising is forced off and simulcast disabled.
nisse05103312016-03-16 02:22:50 -07002019 VideoOptions options;
2020 options.is_screencast = rtc::Optional<bool>(true);
deadbeef5a4a75a2016-06-02 16:23:38 -07002021 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, &options, &capturer));
Niels Möller60653ba2016-03-02 11:41:36 +01002022
nisse05103312016-03-16 02:22:50 -07002023 stream = SetDenoisingOption(last_ssrc_, &capturer, false);
Erik Språng143cec12015-04-28 10:01:41 +02002024
2025 EXPECT_EQ(1, stream->GetVideoStreams().size());
2026 ASSERT_TRUE(stream->GetVp8Settings(&vp8_settings)) << "No VP8 config set.";
2027 EXPECT_FALSE(vp8_settings.denoisingOn);
2028 // Resizing and frame dropping always off for screen sharing.
2029 EXPECT_FALSE(vp8_settings.automaticResizeOn);
2030 EXPECT_FALSE(vp8_settings.frameDroppingOn);
2031
nisse05103312016-03-16 02:22:50 -07002032 stream = SetDenoisingOption(last_ssrc_, &capturer, true);
Erik Språng143cec12015-04-28 10:01:41 +02002033
2034 ASSERT_TRUE(stream->GetVp8Settings(&vp8_settings)) << "No VP8 config set.";
2035 EXPECT_FALSE(vp8_settings.denoisingOn);
2036 EXPECT_FALSE(vp8_settings.automaticResizeOn);
2037 EXPECT_FALSE(vp8_settings.frameDroppingOn);
2038
deadbeef5a4a75a2016-06-02 16:23:38 -07002039 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, nullptr));
Erik Språng143cec12015-04-28 10:01:41 +02002040}
2041
deadbeef119760a2016-04-04 11:43:27 -07002042// Test that setting the same options doesn't result in the encoder being
2043// reconfigured.
eladalonf1841382017-06-12 01:16:46 -07002044TEST_F(WebRtcVideoChannelTest, SetIdenticalOptionsDoesntReconfigureEncoder) {
deadbeef119760a2016-04-04 11:43:27 -07002045 VideoOptions options;
2046 cricket::FakeVideoCapturer capturer;
2047
perkjfa10b552016-10-02 23:45:26 -07002048 AddSendStream();
deadbeef119760a2016-04-04 11:43:27 -07002049 EXPECT_EQ(cricket::CS_RUNNING,
2050 capturer.Start(capturer.GetSupportedFormats()->front()));
perkjfa10b552016-10-02 23:45:26 -07002051 cricket::VideoSendParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08002052 parameters.codecs.push_back(GetEngineCodec("VP8"));
perkjfa10b552016-10-02 23:45:26 -07002053 ASSERT_TRUE(channel_->SetSendParameters(parameters));
2054 FakeVideoSendStream* send_stream = fake_call_->GetVideoSendStreams().front();
2055
2056 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, &options, &capturer));
deadbeef5a4a75a2016-06-02 16:23:38 -07002057 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, &options, &capturer));
deadbeef119760a2016-04-04 11:43:27 -07002058 EXPECT_TRUE(capturer.CaptureFrame());
perkjfa10b552016-10-02 23:45:26 -07002059 // Expect 1 reconfigurations at this point from the initial configuration.
2060 EXPECT_EQ(1, send_stream->num_encoder_reconfigurations());
deadbeef119760a2016-04-04 11:43:27 -07002061
2062 // Set the options one more time and expect no additional reconfigurations.
deadbeef5a4a75a2016-06-02 16:23:38 -07002063 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, &options, &capturer));
perkjfa10b552016-10-02 23:45:26 -07002064 EXPECT_EQ(1, send_stream->num_encoder_reconfigurations());
2065
2066 // Change |options| and expect 2 reconfigurations.
sprangf24a0642017-02-28 13:23:26 -08002067 options.video_noise_reduction = rtc::Optional<bool>(true);
perkjfa10b552016-10-02 23:45:26 -07002068 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, &options, &capturer));
deadbeef119760a2016-04-04 11:43:27 -07002069 EXPECT_EQ(2, send_stream->num_encoder_reconfigurations());
2070
deadbeef5a4a75a2016-06-02 16:23:38 -07002071 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, nullptr));
deadbeef119760a2016-04-04 11:43:27 -07002072}
2073
eladalonf1841382017-06-12 01:16:46 -07002074class Vp9SettingsTest : public WebRtcVideoChannelTest {
Erik Språng143cec12015-04-28 10:01:41 +02002075 public:
asaperssonc5dabdd2016-03-21 04:15:50 -07002076 Vp9SettingsTest() : Vp9SettingsTest("") {}
2077 explicit Vp9SettingsTest(const char* field_trials)
eladalonf1841382017-06-12 01:16:46 -07002078 : WebRtcVideoChannelTest(field_trials) {
Magnus Jedvert02e7a192017-09-23 17:21:32 +02002079 encoder_factory_->AddSupportedVideoCodecType("VP9");
Erik Språng143cec12015-04-28 10:01:41 +02002080 }
2081 virtual ~Vp9SettingsTest() {}
2082
2083 protected:
Erik Språng143cec12015-04-28 10:01:41 +02002084 void TearDown() override {
2085 // Remove references to encoder_factory_ since this will be destroyed
2086 // before channel_ and engine_.
Fredrik Solenbergb071a192015-09-17 16:42:56 +02002087 ASSERT_TRUE(channel_->SetSendParameters(send_parameters_));
Erik Språng143cec12015-04-28 10:01:41 +02002088 }
Erik Språng143cec12015-04-28 10:01:41 +02002089};
2090
2091TEST_F(Vp9SettingsTest, VerifyVp9SpecificSettings) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02002092 cricket::VideoSendParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08002093 parameters.codecs.push_back(GetEngineCodec("VP9"));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02002094 ASSERT_TRUE(channel_->SetSendParameters(parameters));
Erik Språng143cec12015-04-28 10:01:41 +02002095
Peter Boström2feafdb2015-09-09 14:32:14 +02002096 FakeVideoSendStream* stream = SetUpSimulcast(false, false);
Erik Språng143cec12015-04-28 10:01:41 +02002097
2098 cricket::FakeVideoCapturer capturer;
Erik Språng143cec12015-04-28 10:01:41 +02002099 EXPECT_EQ(cricket::CS_RUNNING,
2100 capturer.Start(capturer.GetSupportedFormats()->front()));
deadbeef5a4a75a2016-06-02 16:23:38 -07002101 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, &capturer));
Erik Språng143cec12015-04-28 10:01:41 +02002102 channel_->SetSend(true);
2103
2104 EXPECT_TRUE(capturer.CaptureFrame());
2105
pbos4cba4eb2015-10-26 11:18:18 -07002106 webrtc::VideoCodecVP9 vp9_settings;
2107 ASSERT_TRUE(stream->GetVp9Settings(&vp9_settings)) << "No VP9 config set.";
jianja5e8aa62017-03-27 10:09:00 -07002108 EXPECT_TRUE(vp9_settings.denoisingOn)
2109 << "VP9 denoising should be on by default.";
pbos4cba4eb2015-10-26 11:18:18 -07002110
nisse05103312016-03-16 02:22:50 -07002111 stream = SetDenoisingOption(last_ssrc_, &capturer, false);
Erik Språng143cec12015-04-28 10:01:41 +02002112
Erik Språng143cec12015-04-28 10:01:41 +02002113 ASSERT_TRUE(stream->GetVp9Settings(&vp9_settings)) << "No VP9 config set.";
2114 EXPECT_FALSE(vp9_settings.denoisingOn);
2115 // Frame dropping always on for real time video.
2116 EXPECT_TRUE(vp9_settings.frameDroppingOn);
2117
nisse05103312016-03-16 02:22:50 -07002118 stream = SetDenoisingOption(last_ssrc_, &capturer, true);
Erik Språng143cec12015-04-28 10:01:41 +02002119
2120 ASSERT_TRUE(stream->GetVp9Settings(&vp9_settings)) << "No VP9 config set.";
2121 EXPECT_TRUE(vp9_settings.denoisingOn);
2122 EXPECT_TRUE(vp9_settings.frameDroppingOn);
2123
2124 // In screen-share mode, denoising is forced off.
nisse05103312016-03-16 02:22:50 -07002125 VideoOptions options;
2126 options.is_screencast = rtc::Optional<bool>(true);
deadbeef5a4a75a2016-06-02 16:23:38 -07002127 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, &options, &capturer));
perkj2d5f0912016-02-29 00:04:41 -08002128
nisse05103312016-03-16 02:22:50 -07002129 stream = SetDenoisingOption(last_ssrc_, &capturer, false);
Erik Språng143cec12015-04-28 10:01:41 +02002130
2131 ASSERT_TRUE(stream->GetVp9Settings(&vp9_settings)) << "No VP9 config set.";
2132 EXPECT_FALSE(vp9_settings.denoisingOn);
2133 // Frame dropping always off for screen sharing.
2134 EXPECT_FALSE(vp9_settings.frameDroppingOn);
2135
nisse05103312016-03-16 02:22:50 -07002136 stream = SetDenoisingOption(last_ssrc_, &capturer, false);
Erik Språng143cec12015-04-28 10:01:41 +02002137
2138 ASSERT_TRUE(stream->GetVp9Settings(&vp9_settings)) << "No VP9 config set.";
2139 EXPECT_FALSE(vp9_settings.denoisingOn);
2140 EXPECT_FALSE(vp9_settings.frameDroppingOn);
2141
deadbeef5a4a75a2016-06-02 16:23:38 -07002142 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, nullptr));
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00002143}
2144
asaperssonc5dabdd2016-03-21 04:15:50 -07002145class Vp9SettingsTestWithFieldTrial : public Vp9SettingsTest {
2146 public:
brandtr468da7c2016-11-22 02:16:47 -08002147 explicit Vp9SettingsTestWithFieldTrial(const char* field_trials)
asaperssonc5dabdd2016-03-21 04:15:50 -07002148 : Vp9SettingsTest(field_trials) {}
2149
2150 protected:
2151 void VerifySettings(int num_spatial_layers, int num_temporal_layers) {
2152 cricket::VideoSendParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08002153 parameters.codecs.push_back(GetEngineCodec("VP9"));
asaperssonc5dabdd2016-03-21 04:15:50 -07002154 ASSERT_TRUE(channel_->SetSendParameters(parameters));
2155
2156 FakeVideoSendStream* stream = SetUpSimulcast(false, false);
2157
2158 cricket::FakeVideoCapturer capturer;
2159 EXPECT_EQ(cricket::CS_RUNNING,
2160 capturer.Start(capturer.GetSupportedFormats()->front()));
deadbeef5a4a75a2016-06-02 16:23:38 -07002161 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, &capturer));
asaperssonc5dabdd2016-03-21 04:15:50 -07002162 channel_->SetSend(true);
2163
2164 EXPECT_TRUE(capturer.CaptureFrame());
2165
2166 webrtc::VideoCodecVP9 vp9_settings;
2167 ASSERT_TRUE(stream->GetVp9Settings(&vp9_settings)) << "No VP9 config set.";
2168 EXPECT_EQ(num_spatial_layers, vp9_settings.numberOfSpatialLayers);
2169 EXPECT_EQ(num_temporal_layers, vp9_settings.numberOfTemporalLayers);
2170
deadbeef5a4a75a2016-06-02 16:23:38 -07002171 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, nullptr));
asaperssonc5dabdd2016-03-21 04:15:50 -07002172 }
2173};
2174
2175class Vp9SettingsTestWithNoFlag : public Vp9SettingsTestWithFieldTrial {
2176 public:
2177 Vp9SettingsTestWithNoFlag() : Vp9SettingsTestWithFieldTrial("") {}
2178};
2179
2180TEST_F(Vp9SettingsTestWithNoFlag, VerifySettings) {
2181 const int kNumSpatialLayers = 1;
2182 const int kNumTemporalLayers = 1;
2183 VerifySettings(kNumSpatialLayers, kNumTemporalLayers);
2184}
2185
2186class Vp9SettingsTestWithInvalidFlag : public Vp9SettingsTestWithFieldTrial {
2187 public:
2188 Vp9SettingsTestWithInvalidFlag()
2189 : Vp9SettingsTestWithFieldTrial("WebRTC-SupportVP9SVC/Default/") {}
2190};
2191
2192TEST_F(Vp9SettingsTestWithInvalidFlag, VerifySettings) {
2193 const int kNumSpatialLayers = 1;
2194 const int kNumTemporalLayers = 1;
2195 VerifySettings(kNumSpatialLayers, kNumTemporalLayers);
2196}
2197
2198class Vp9SettingsTestWith2SL3TLFlag : public Vp9SettingsTestWithFieldTrial {
2199 public:
2200 Vp9SettingsTestWith2SL3TLFlag()
2201 : Vp9SettingsTestWithFieldTrial(
2202 "WebRTC-SupportVP9SVC/EnabledByFlag_2SL3TL/") {}
2203};
2204
2205TEST_F(Vp9SettingsTestWith2SL3TLFlag, VerifySettings) {
2206 const int kNumSpatialLayers = 2;
2207 const int kNumTemporalLayers = 3;
2208 VerifySettings(kNumSpatialLayers, kNumTemporalLayers);
2209}
2210
asapersson3c81a1a2017-06-14 05:52:21 -07002211TEST_F(WebRtcVideoChannelTest,
2212 BalancedDegradationPreferenceNotSupportedWithoutFieldtrial) {
2213 webrtc::test::ScopedFieldTrials override_field_trials_(
2214 "WebRTC-Video-BalancedDegradation/Disabled/");
2215 const bool kResolutionScalingEnabled = true;
2216 const bool kFpsScalingEnabled = false;
2217 TestDegradationPreference(kResolutionScalingEnabled, kFpsScalingEnabled);
2218}
2219
2220TEST_F(WebRtcVideoChannelTest,
2221 BalancedDegradationPreferenceSupportedBehindFieldtrial) {
2222 webrtc::test::ScopedFieldTrials override_field_trials_(
2223 "WebRTC-Video-BalancedDegradation/Enabled/");
2224 const bool kResolutionScalingEnabled = true;
2225 const bool kFpsScalingEnabled = true;
2226 TestDegradationPreference(kResolutionScalingEnabled, kFpsScalingEnabled);
2227}
2228
eladalonf1841382017-06-12 01:16:46 -07002229TEST_F(WebRtcVideoChannelTest, AdaptsOnOveruse) {
Erik Språngefbde372015-04-29 16:21:28 +02002230 TestCpuAdaptation(true, false);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00002231}
2232
eladalonf1841382017-06-12 01:16:46 -07002233TEST_F(WebRtcVideoChannelTest, DoesNotAdaptOnOveruseWhenDisabled) {
Erik Språngefbde372015-04-29 16:21:28 +02002234 TestCpuAdaptation(false, false);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00002235}
2236
eladalonf1841382017-06-12 01:16:46 -07002237TEST_F(WebRtcVideoChannelTest, DoesNotAdaptOnOveruseWhenScreensharing) {
Erik Språngefbde372015-04-29 16:21:28 +02002238 TestCpuAdaptation(true, true);
2239}
2240
eladalonf1841382017-06-12 01:16:46 -07002241TEST_F(WebRtcVideoChannelTest, AdaptsOnOveruseAndChangeResolution) {
magjed509e4fe2016-11-18 01:34:11 -08002242 cricket::VideoCodec codec = GetEngineCodec("VP8");
perkj2d5f0912016-02-29 00:04:41 -08002243 cricket::VideoSendParameters parameters;
2244 parameters.codecs.push_back(codec);
2245
kthelgason2bc68642017-02-07 07:02:22 -08002246 MediaConfig media_config = GetMediaConfig();
perkj2d5f0912016-02-29 00:04:41 -08002247 channel_.reset(
2248 engine_.CreateChannel(fake_call_.get(), media_config, VideoOptions()));
Sergey Ulanove2b15012016-11-22 16:08:30 -08002249 channel_->OnReadyToSend(true);
perkj2d5f0912016-02-29 00:04:41 -08002250 ASSERT_TRUE(channel_->SetSendParameters(parameters));
2251
2252 AddSendStream();
2253
2254 cricket::FakeVideoCapturer capturer;
deadbeef5a4a75a2016-06-02 16:23:38 -07002255 ASSERT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, &capturer));
perkj2d5f0912016-02-29 00:04:41 -08002256 ASSERT_EQ(cricket::CS_RUNNING,
2257 capturer.Start(capturer.GetSupportedFormats()->front()));
2258 ASSERT_TRUE(channel_->SetSend(true));
2259
2260 ASSERT_EQ(1u, fake_call_->GetVideoSendStreams().size());
2261 FakeVideoSendStream* send_stream = fake_call_->GetVideoSendStreams().front();
perkj2d5f0912016-02-29 00:04:41 -08002262
2263 EXPECT_TRUE(capturer.CaptureCustomFrame(1280, 720, cricket::FOURCC_I420));
2264 EXPECT_EQ(1, send_stream->GetNumberOfSwappedFrames());
2265 EXPECT_EQ(1280, send_stream->GetLastWidth());
2266 EXPECT_EQ(720, send_stream->GetLastHeight());
2267
2268 // Trigger overuse.
perkj803d97f2016-11-01 11:45:46 -07002269 rtc::VideoSinkWants wants;
sprangc5d62e22017-04-02 23:53:04 -07002270 wants.max_pixel_count =
2271 send_stream->GetLastWidth() * send_stream->GetLastHeight() - 1;
perkj803d97f2016-11-01 11:45:46 -07002272 send_stream->InjectVideoSinkWants(wants);
perkj2d5f0912016-02-29 00:04:41 -08002273 EXPECT_TRUE(capturer.CaptureCustomFrame(1280, 720, cricket::FOURCC_I420));
2274 EXPECT_EQ(2, send_stream->GetNumberOfSwappedFrames());
2275 EXPECT_EQ(1280 * 3 / 4, send_stream->GetLastWidth());
2276 EXPECT_EQ(720 * 3 / 4, send_stream->GetLastHeight());
2277
2278 // Trigger overuse again.
sprangc5d62e22017-04-02 23:53:04 -07002279 wants.max_pixel_count =
2280 send_stream->GetLastWidth() * send_stream->GetLastHeight() - 1;
perkj803d97f2016-11-01 11:45:46 -07002281 send_stream->InjectVideoSinkWants(wants);
perkj2d5f0912016-02-29 00:04:41 -08002282 EXPECT_TRUE(capturer.CaptureCustomFrame(1280, 720, cricket::FOURCC_I420));
2283 EXPECT_EQ(3, send_stream->GetNumberOfSwappedFrames());
2284 EXPECT_EQ(1280 * 2 / 4, send_stream->GetLastWidth());
2285 EXPECT_EQ(720 * 2 / 4, send_stream->GetLastHeight());
2286
2287 // Change input resolution.
2288 EXPECT_TRUE(capturer.CaptureCustomFrame(1284, 724, cricket::FOURCC_I420));
perkj803d97f2016-11-01 11:45:46 -07002289 EXPECT_EQ(4, send_stream->GetNumberOfSwappedFrames());
perkj2d5f0912016-02-29 00:04:41 -08002290 EXPECT_EQ(1284 / 2, send_stream->GetLastWidth());
2291 EXPECT_EQ(724 / 2, send_stream->GetLastHeight());
2292
2293 // Trigger underuse which should go back up in resolution.
sprang84a37592017-02-10 07:04:27 -08002294 int current_pixel_count =
2295 send_stream->GetLastWidth() * send_stream->GetLastHeight();
2296 // Cap the max to 4x the pixel count (assuming max 1/2 x 1/2 scale downs)
2297 // of the current stream, so we don't take too large steps.
sprangc5d62e22017-04-02 23:53:04 -07002298 wants.max_pixel_count = current_pixel_count * 4;
sprang84a37592017-02-10 07:04:27 -08002299 // Default step down is 3/5 pixel count, so go up by 5/3.
2300 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(5, send_stream->GetNumberOfSwappedFrames());
perkj2d5f0912016-02-29 00:04:41 -08002304 EXPECT_EQ(1284 * 3 / 4, send_stream->GetLastWidth());
2305 EXPECT_EQ(724 * 3 / 4, send_stream->GetLastHeight());
2306
sprang84a37592017-02-10 07:04:27 -08002307 // Trigger underuse again, should go back up to full resolution.
2308 current_pixel_count =
2309 send_stream->GetLastWidth() * send_stream->GetLastHeight();
sprangc5d62e22017-04-02 23:53:04 -07002310 wants.max_pixel_count = current_pixel_count * 4;
sprang84a37592017-02-10 07:04:27 -08002311 wants.target_pixel_count = rtc::Optional<int>((current_pixel_count * 5) / 3);
perkj803d97f2016-11-01 11:45:46 -07002312 send_stream->InjectVideoSinkWants(wants);
perkj2d5f0912016-02-29 00:04:41 -08002313 EXPECT_TRUE(capturer.CaptureCustomFrame(1284, 724, cricket::FOURCC_I420));
perkj803d97f2016-11-01 11:45:46 -07002314 EXPECT_EQ(6, send_stream->GetNumberOfSwappedFrames());
perkj2d5f0912016-02-29 00:04:41 -08002315 EXPECT_EQ(1284, send_stream->GetLastWidth());
2316 EXPECT_EQ(724, send_stream->GetLastHeight());
2317
deadbeef5a4a75a2016-06-02 16:23:38 -07002318 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, nullptr));
perkj2d5f0912016-02-29 00:04:41 -08002319}
2320
eladalonf1841382017-06-12 01:16:46 -07002321TEST_F(WebRtcVideoChannelTest, PreviousAdaptationDoesNotApplyToScreenshare) {
magjed509e4fe2016-11-18 01:34:11 -08002322 cricket::VideoCodec codec = GetEngineCodec("VP8");
Per766ad3b2016-04-05 15:23:49 +02002323 cricket::VideoSendParameters parameters;
2324 parameters.codecs.push_back(codec);
2325
kthelgason2bc68642017-02-07 07:02:22 -08002326 MediaConfig media_config = GetMediaConfig();
2327 media_config.video.enable_cpu_overuse_detection = true;
Per766ad3b2016-04-05 15:23:49 +02002328 channel_.reset(
2329 engine_.CreateChannel(fake_call_.get(), media_config, VideoOptions()));
Sergey Ulanove2b15012016-11-22 16:08:30 -08002330 channel_->OnReadyToSend(true);
Per766ad3b2016-04-05 15:23:49 +02002331 ASSERT_TRUE(channel_->SetSendParameters(parameters));
2332
2333 AddSendStream();
2334
2335 cricket::FakeVideoCapturer capturer;
Per766ad3b2016-04-05 15:23:49 +02002336 ASSERT_EQ(cricket::CS_RUNNING,
2337 capturer.Start(capturer.GetSupportedFormats()->front()));
2338 ASSERT_TRUE(channel_->SetSend(true));
2339 cricket::VideoOptions camera_options;
perkj803d97f2016-11-01 11:45:46 -07002340 camera_options.is_screencast = rtc::Optional<bool>(false);
deadbeef5a4a75a2016-06-02 16:23:38 -07002341 channel_->SetVideoSend(last_ssrc_, true /* enable */, &camera_options,
2342 &capturer);
Per766ad3b2016-04-05 15:23:49 +02002343
2344 ASSERT_EQ(1u, fake_call_->GetVideoSendStreams().size());
2345 FakeVideoSendStream* send_stream = fake_call_->GetVideoSendStreams().front();
Per766ad3b2016-04-05 15:23:49 +02002346
2347 EXPECT_TRUE(capturer.CaptureCustomFrame(1280, 720, cricket::FOURCC_I420));
2348 EXPECT_EQ(1, send_stream->GetNumberOfSwappedFrames());
2349 EXPECT_EQ(1280, send_stream->GetLastWidth());
2350 EXPECT_EQ(720, send_stream->GetLastHeight());
2351
2352 // Trigger overuse.
perkj803d97f2016-11-01 11:45:46 -07002353 rtc::VideoSinkWants wants;
sprangc5d62e22017-04-02 23:53:04 -07002354 wants.max_pixel_count =
2355 send_stream->GetLastWidth() * send_stream->GetLastHeight() - 1;
perkj803d97f2016-11-01 11:45:46 -07002356 send_stream->InjectVideoSinkWants(wants);
Per766ad3b2016-04-05 15:23:49 +02002357 EXPECT_TRUE(capturer.CaptureCustomFrame(1280, 720, cricket::FOURCC_I420));
2358 EXPECT_EQ(2, send_stream->GetNumberOfSwappedFrames());
2359 EXPECT_EQ(1280 * 3 / 4, send_stream->GetLastWidth());
2360 EXPECT_EQ(720 * 3 / 4, send_stream->GetLastHeight());
2361
2362 // Switch to screen share. Expect no CPU adaptation.
2363 cricket::FakeVideoCapturer screen_share(true);
2364 ASSERT_EQ(cricket::CS_RUNNING,
2365 screen_share.Start(screen_share.GetSupportedFormats()->front()));
Per766ad3b2016-04-05 15:23:49 +02002366 cricket::VideoOptions screenshare_options;
2367 screenshare_options.is_screencast = rtc::Optional<bool>(true);
deadbeef5a4a75a2016-06-02 16:23:38 -07002368 channel_->SetVideoSend(last_ssrc_, true /* enable */, &screenshare_options,
2369 &screen_share);
Per766ad3b2016-04-05 15:23:49 +02002370 EXPECT_TRUE(screen_share.CaptureCustomFrame(1284, 724, cricket::FOURCC_I420));
sprangf24a0642017-02-28 13:23:26 -08002371 ASSERT_EQ(2, fake_call_->GetNumCreatedSendStreams());
2372 send_stream = fake_call_->GetVideoSendStreams().front();
2373 EXPECT_EQ(1, send_stream->GetNumberOfSwappedFrames());
Per766ad3b2016-04-05 15:23:49 +02002374 EXPECT_EQ(1284, send_stream->GetLastWidth());
2375 EXPECT_EQ(724, send_stream->GetLastHeight());
2376
2377 // Switch back to the normal capturer. Expect the frame to be CPU adapted.
deadbeef5a4a75a2016-06-02 16:23:38 -07002378 channel_->SetVideoSend(last_ssrc_, true /* enable */, &camera_options,
2379 &capturer);
sprangf24a0642017-02-28 13:23:26 -08002380 send_stream = fake_call_->GetVideoSendStreams().front();
2381 // We have a new fake send stream, so it doesn't remember the old sink wants.
2382 // In practice, it will be populated from
mflodmancc3d4422017-08-03 08:27:51 -07002383 // VideoStreamEncoder::VideoSourceProxy::SetSource(), so simulate that here.
sprangf24a0642017-02-28 13:23:26 -08002384 send_stream->InjectVideoSinkWants(wants);
Per766ad3b2016-04-05 15:23:49 +02002385 EXPECT_TRUE(capturer.CaptureCustomFrame(1280, 720, cricket::FOURCC_I420));
sprangf24a0642017-02-28 13:23:26 -08002386 ASSERT_EQ(3, fake_call_->GetNumCreatedSendStreams());
2387 send_stream = fake_call_->GetVideoSendStreams().front();
2388 EXPECT_EQ(1, send_stream->GetNumberOfSwappedFrames());
Per766ad3b2016-04-05 15:23:49 +02002389 EXPECT_EQ(1280 * 3 / 4, send_stream->GetLastWidth());
2390 EXPECT_EQ(720 * 3 / 4, send_stream->GetLastHeight());
2391
deadbeef5a4a75a2016-06-02 16:23:38 -07002392 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, nullptr));
Per766ad3b2016-04-05 15:23:49 +02002393}
2394
asapersson3c81a1a2017-06-14 05:52:21 -07002395// TODO(asapersson): Remove this test when the balanced field trial is removed.
2396void WebRtcVideoChannelTest::TestDegradationPreference(
2397 bool resolution_scaling_enabled,
2398 bool fps_scaling_enabled) {
2399 cricket::VideoCodec codec = GetEngineCodec("VP8");
2400 cricket::VideoSendParameters parameters;
2401 parameters.codecs.push_back(codec);
2402
2403 MediaConfig media_config = GetMediaConfig();
2404 media_config.video.enable_cpu_overuse_detection = true;
2405 channel_.reset(
2406 engine_.CreateChannel(fake_call_.get(), media_config, VideoOptions()));
2407 channel_->OnReadyToSend(true);
2408
2409 EXPECT_TRUE(channel_->SetSendParameters(parameters));
2410
2411 AddSendStream();
2412
2413 cricket::FakeVideoCapturer capturer;
2414 VideoOptions options;
2415 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, &options, &capturer));
2416 cricket::VideoFormat capture_format = capturer.GetSupportedFormats()->front();
2417 EXPECT_EQ(cricket::CS_RUNNING, capturer.Start(capture_format));
2418
2419 EXPECT_TRUE(channel_->SetSend(true));
2420
2421 FakeVideoSendStream* send_stream = fake_call_->GetVideoSendStreams().front();
2422 EXPECT_EQ(resolution_scaling_enabled,
2423 send_stream->resolution_scaling_enabled());
2424 EXPECT_EQ(fps_scaling_enabled, send_stream->framerate_scaling_enabled());
2425
2426 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, nullptr));
2427}
2428
eladalonf1841382017-06-12 01:16:46 -07002429void WebRtcVideoChannelTest::TestCpuAdaptation(bool enable_overuse,
2430 bool is_screenshare) {
sprangc5d62e22017-04-02 23:53:04 -07002431 const int kDefaultFps = 30;
magjed509e4fe2016-11-18 01:34:11 -08002432 cricket::VideoCodec codec = GetEngineCodec("VP8");
Fredrik Solenbergb071a192015-09-17 16:42:56 +02002433 cricket::VideoSendParameters parameters;
2434 parameters.codecs.push_back(codec);
nisse51542be2016-02-12 02:27:06 -08002435
kthelgason2bc68642017-02-07 07:02:22 -08002436 MediaConfig media_config = GetMediaConfig();
2437 if (enable_overuse) {
2438 media_config.video.enable_cpu_overuse_detection = true;
pbos@webrtc.org42684be2014-10-03 11:25:45 +00002439 }
nisse51542be2016-02-12 02:27:06 -08002440 channel_.reset(
2441 engine_.CreateChannel(fake_call_.get(), media_config, VideoOptions()));
Sergey Ulanove2b15012016-11-22 16:08:30 -08002442 channel_->OnReadyToSend(true);
nisse51542be2016-02-12 02:27:06 -08002443
Fredrik Solenbergb071a192015-09-17 16:42:56 +02002444 EXPECT_TRUE(channel_->SetSendParameters(parameters));
pbos@webrtc.org42684be2014-10-03 11:25:45 +00002445
2446 AddSendStream();
2447
deadbeef5a4a75a2016-06-02 16:23:38 -07002448 cricket::FakeVideoCapturer capturer;
nisse05103312016-03-16 02:22:50 -07002449 VideoOptions options;
2450 options.is_screencast = rtc::Optional<bool>(is_screenshare);
deadbeef5a4a75a2016-06-02 16:23:38 -07002451 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, &options, &capturer));
perkj26752742016-10-24 01:21:16 -07002452 cricket::VideoFormat capture_format = capturer.GetSupportedFormats()->front();
sprangc5d62e22017-04-02 23:53:04 -07002453 capture_format.interval = rtc::kNumNanosecsPerSec / kDefaultFps;
perkj26752742016-10-24 01:21:16 -07002454 EXPECT_EQ(cricket::CS_RUNNING, capturer.Start(capture_format));
pbos@webrtc.org42684be2014-10-03 11:25:45 +00002455
2456 EXPECT_TRUE(channel_->SetSend(true));
2457
solenberge5269742015-09-08 05:13:22 -07002458 FakeVideoSendStream* send_stream = fake_call_->GetVideoSendStreams().front();
perkj2d5f0912016-02-29 00:04:41 -08002459
sprangc5d62e22017-04-02 23:53:04 -07002460 if (!enable_overuse) {
perkj803d97f2016-11-01 11:45:46 -07002461 EXPECT_FALSE(send_stream->resolution_scaling_enabled());
sprangc5d62e22017-04-02 23:53:04 -07002462 EXPECT_FALSE(send_stream->framerate_scaling_enabled());
2463 EXPECT_EQ(is_screenshare, send_stream->framerate_scaling_enabled());
perkj2d5f0912016-02-29 00:04:41 -08002464
2465 EXPECT_TRUE(capturer.CaptureFrame());
2466 EXPECT_EQ(1, send_stream->GetNumberOfSwappedFrames());
2467
perkj26752742016-10-24 01:21:16 -07002468 EXPECT_EQ(capture_format.width, send_stream->GetLastWidth());
2469 EXPECT_EQ(capture_format.height, send_stream->GetLastHeight());
perkj2d5f0912016-02-29 00:04:41 -08002470
deadbeef5a4a75a2016-06-02 16:23:38 -07002471 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, nullptr));
perkj2d5f0912016-02-29 00:04:41 -08002472 return;
2473 }
2474
sprangc5d62e22017-04-02 23:53:04 -07002475 if (is_screenshare) {
2476 EXPECT_FALSE(send_stream->resolution_scaling_enabled());
2477 EXPECT_TRUE(send_stream->framerate_scaling_enabled());
2478 } else {
2479 EXPECT_TRUE(send_stream->resolution_scaling_enabled());
2480 EXPECT_FALSE(send_stream->framerate_scaling_enabled());
2481 }
2482
perkj803d97f2016-11-01 11:45:46 -07002483 // Trigger overuse.
2484 ASSERT_EQ(1u, fake_call_->GetVideoSendStreams().size());
2485
2486 rtc::VideoSinkWants wants;
sprangc5d62e22017-04-02 23:53:04 -07002487 if (is_screenshare) {
2488 wants.max_framerate_fps = (kDefaultFps * 2) / 3;
2489 } else {
2490 wants.max_pixel_count = capture_format.width * capture_format.height - 1;
2491 }
perkj803d97f2016-11-01 11:45:46 -07002492 send_stream->InjectVideoSinkWants(wants);
2493
sprangc5d62e22017-04-02 23:53:04 -07002494 for (int i = 0; i < kDefaultFps; ++i)
2495 EXPECT_TRUE(capturer.CaptureFrame());
pbos@webrtc.org42684be2014-10-03 11:25:45 +00002496
sprangc5d62e22017-04-02 23:53:04 -07002497 if (is_screenshare) {
2498 // Drops every third frame.
2499 EXPECT_EQ(kDefaultFps * 2 / 3, send_stream->GetNumberOfSwappedFrames());
2500 EXPECT_EQ(send_stream->GetLastWidth(), capture_format.width);
2501 EXPECT_EQ(send_stream->GetLastHeight(), capture_format.height);
2502 } else {
2503 EXPECT_EQ(kDefaultFps, send_stream->GetNumberOfSwappedFrames());
2504 EXPECT_LT(send_stream->GetLastWidth(), capture_format.width);
2505 EXPECT_LT(send_stream->GetLastHeight(), capture_format.height);
2506 }
pbos@webrtc.org42684be2014-10-03 11:25:45 +00002507
2508 // Trigger underuse which should go back to normal resolution.
sprang84a37592017-02-10 07:04:27 -08002509 int last_pixel_count =
2510 send_stream->GetLastWidth() * send_stream->GetLastHeight();
sprangc5d62e22017-04-02 23:53:04 -07002511 if (is_screenshare) {
2512 wants.max_framerate_fps = kDefaultFps;
2513 } else {
2514 wants.max_pixel_count = last_pixel_count * 4;
2515 wants.target_pixel_count.emplace((last_pixel_count * 5) / 3);
2516 }
perkj803d97f2016-11-01 11:45:46 -07002517 send_stream->InjectVideoSinkWants(wants);
2518
sprangc5d62e22017-04-02 23:53:04 -07002519 for (int i = 0; i < kDefaultFps; ++i)
2520 EXPECT_TRUE(capturer.CaptureFrame());
2521
2522 if (is_screenshare) {
2523 EXPECT_EQ(kDefaultFps + (kDefaultFps * 2 / 3),
2524 send_stream->GetNumberOfSwappedFrames());
2525 } else {
2526 EXPECT_EQ(kDefaultFps * 2, send_stream->GetNumberOfSwappedFrames());
2527 }
pbos@webrtc.org42684be2014-10-03 11:25:45 +00002528
perkj26752742016-10-24 01:21:16 -07002529 EXPECT_EQ(capture_format.width, send_stream->GetLastWidth());
2530 EXPECT_EQ(capture_format.height, send_stream->GetLastHeight());
pbos@webrtc.org42684be2014-10-03 11:25:45 +00002531
deadbeef5a4a75a2016-06-02 16:23:38 -07002532 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, nullptr));
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00002533}
2534
eladalonf1841382017-06-12 01:16:46 -07002535TEST_F(WebRtcVideoChannelTest, EstimatesNtpStartTimeCorrectly) {
magjed@webrtc.orgfc5ad952015-01-27 09:57:01 +00002536 // Start at last timestamp to verify that wraparounds are estimated correctly.
2537 static const uint32_t kInitialTimestamp = 0xFFFFFFFFu;
2538 static const int64_t kInitialNtpTimeMs = 1247891230;
2539 static const int kFrameOffsetMs = 20;
Fredrik Solenbergb071a192015-09-17 16:42:56 +02002540 EXPECT_TRUE(channel_->SetRecvParameters(recv_parameters_));
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00002541
magjed@webrtc.orgfc5ad952015-01-27 09:57:01 +00002542 FakeVideoReceiveStream* stream = AddRecvStream();
2543 cricket::FakeVideoRenderer renderer;
nisse08582ff2016-02-04 01:24:52 -08002544 EXPECT_TRUE(channel_->SetSink(last_ssrc_, &renderer));
magjed@webrtc.orgfc5ad952015-01-27 09:57:01 +00002545
nisse64ec8f82016-09-27 00:17:25 -07002546 webrtc::VideoFrame video_frame(CreateBlackFrameBuffer(4, 4),
2547 kInitialTimestamp, 0,
2548 webrtc::kVideoRotation_0);
magjed@webrtc.orgfc5ad952015-01-27 09:57:01 +00002549 // Initial NTP time is not available on the first frame, but should still be
2550 // able to be estimated.
nisseeb83a1a2016-03-21 01:27:56 -07002551 stream->InjectFrame(video_frame);
magjed@webrtc.orgfc5ad952015-01-27 09:57:01 +00002552
2553 EXPECT_EQ(1, renderer.num_rendered_frames());
magjed@webrtc.orgfc5ad952015-01-27 09:57:01 +00002554
2555 // This timestamp is kInitialTimestamp (-1) + kFrameOffsetMs * 90, which
2556 // triggers a constant-overflow warning, hence we're calculating it explicitly
2557 // here.
2558 video_frame.set_timestamp(kFrameOffsetMs * 90 - 1);
2559 video_frame.set_ntp_time_ms(kInitialNtpTimeMs + kFrameOffsetMs);
nisseeb83a1a2016-03-21 01:27:56 -07002560 stream->InjectFrame(video_frame);
magjed@webrtc.orgfc5ad952015-01-27 09:57:01 +00002561
2562 EXPECT_EQ(2, renderer.num_rendered_frames());
magjed@webrtc.orgfc5ad952015-01-27 09:57:01 +00002563
2564 // Verify that NTP time has been correctly deduced.
2565 cricket::VideoMediaInfo info;
pbos@webrtc.org058b1f12015-03-04 08:54:32 +00002566 ASSERT_TRUE(channel_->GetStats(&info));
magjed@webrtc.orgfc5ad952015-01-27 09:57:01 +00002567 ASSERT_EQ(1u, info.receivers.size());
2568 EXPECT_EQ(kInitialNtpTimeMs, info.receivers[0].capture_start_ntp_time_ms);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00002569}
2570
eladalonf1841382017-06-12 01:16:46 -07002571TEST_F(WebRtcVideoChannelTest, SetDefaultSendCodecs) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02002572 ASSERT_TRUE(channel_->SetSendParameters(send_parameters_));
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00002573
2574 VideoCodec codec;
2575 EXPECT_TRUE(channel_->GetSendCodec(&codec));
pbos@webrtc.org9fbb7172014-06-13 09:34:13 +00002576 EXPECT_TRUE(codec.Matches(engine_.codecs()[0]));
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00002577
2578 // Using a RTX setup to verify that the default RTX payload type is good.
Peter Boström0c4e06b2015-10-07 12:23:21 +02002579 const std::vector<uint32_t> ssrcs = MAKE_VECTOR(kSsrcs1);
2580 const std::vector<uint32_t> rtx_ssrcs = MAKE_VECTOR(kRtxSsrcs1);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00002581 FakeVideoSendStream* stream = AddSendStream(
2582 cricket::CreateSimWithRtxStreamParams("cname", ssrcs, rtx_ssrcs));
perkj26091b12016-09-01 01:17:40 -07002583 webrtc::VideoSendStream::Config config = stream->GetConfig().Copy();
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00002584
2585 // Make sure NACK and FEC are enabled on the correct payload types.
2586 EXPECT_EQ(1000, config.rtp.nack.rtp_history_ms);
magjed509e4fe2016-11-18 01:34:11 -08002587 EXPECT_EQ(GetEngineCodec("ulpfec").id, config.rtp.ulpfec.ulpfec_payload_type);
2588 EXPECT_EQ(GetEngineCodec("red").id, config.rtp.ulpfec.red_payload_type);
pbos@webrtc.org269605c2014-06-26 08:49:03 +00002589
2590 EXPECT_EQ(1u, config.rtp.rtx.ssrcs.size());
2591 EXPECT_EQ(kRtxSsrcs1[0], config.rtp.rtx.ssrcs[0]);
Shao Changbine62202f2015-04-21 20:24:50 +08002592 VerifySendStreamHasRtxTypes(config, default_apt_rtx_types_);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00002593 // TODO(juberti): Check RTCP, PLI, TMMBR.
2594}
2595
brandtr31bd2242017-05-19 05:47:46 -07002596// The following four tests ensures that FlexFEC is not activated by default
2597// when the field trials are not enabled.
2598// TODO(brandtr): Remove or update these tests when FlexFEC _is_ enabled by
2599// default.
eladalonf1841382017-06-12 01:16:46 -07002600TEST_F(WebRtcVideoChannelTest,
brandtr31bd2242017-05-19 05:47:46 -07002601 FlexfecSendCodecWithoutSsrcNotExposedByDefault) {
brandtr468da7c2016-11-22 02:16:47 -08002602 FakeVideoSendStream* stream = AddSendStream();
2603 webrtc::VideoSendStream::Config config = stream->GetConfig().Copy();
2604
brandtr3d200bd2017-01-16 06:59:19 -08002605 EXPECT_EQ(-1, config.rtp.flexfec.payload_type);
brandtr31bd2242017-05-19 05:47:46 -07002606 EXPECT_EQ(0U, config.rtp.flexfec.ssrc);
2607 EXPECT_TRUE(config.rtp.flexfec.protected_media_ssrcs.empty());
brandtr468da7c2016-11-22 02:16:47 -08002608}
2609
eladalonf1841382017-06-12 01:16:46 -07002610TEST_F(WebRtcVideoChannelTest, FlexfecSendCodecWithSsrcNotExposedByDefault) {
brandtr468da7c2016-11-22 02:16:47 -08002611 FakeVideoSendStream* stream = AddSendStream(
2612 CreatePrimaryWithFecFrStreamParams("cname", kSsrcs1[0], kFlexfecSsrc));
2613 webrtc::VideoSendStream::Config config = stream->GetConfig().Copy();
2614
brandtr3d200bd2017-01-16 06:59:19 -08002615 EXPECT_EQ(-1, config.rtp.flexfec.payload_type);
brandtr31bd2242017-05-19 05:47:46 -07002616 EXPECT_EQ(0U, config.rtp.flexfec.ssrc);
2617 EXPECT_TRUE(config.rtp.flexfec.protected_media_ssrcs.empty());
2618}
2619
eladalonf1841382017-06-12 01:16:46 -07002620TEST_F(WebRtcVideoChannelTest,
brandtr31bd2242017-05-19 05:47:46 -07002621 FlexfecRecvCodecWithoutSsrcNotExposedByDefault) {
2622 AddRecvStream();
2623
2624 const std::vector<FakeFlexfecReceiveStream*>& streams =
2625 fake_call_->GetFlexfecReceiveStreams();
2626 EXPECT_TRUE(streams.empty());
2627}
2628
eladalonf1841382017-06-12 01:16:46 -07002629TEST_F(WebRtcVideoChannelTest, FlexfecRecvCodecWithSsrcNotExposedByDefault) {
brandtr31bd2242017-05-19 05:47:46 -07002630 AddRecvStream(
2631 CreatePrimaryWithFecFrStreamParams("cname", kSsrcs1[0], kFlexfecSsrc));
2632
2633 const std::vector<FakeFlexfecReceiveStream*>& streams =
2634 fake_call_->GetFlexfecReceiveStreams();
2635 EXPECT_TRUE(streams.empty());
brandtr468da7c2016-11-22 02:16:47 -08002636}
2637
2638// TODO(brandtr): When FlexFEC is no longer behind a field trial, merge all
2639// tests that use this test fixture into the corresponding "non-field trial"
2640// tests.
eladalonf1841382017-06-12 01:16:46 -07002641class WebRtcVideoChannelFlexfecRecvTest : public WebRtcVideoChannelTest {
brandtr468da7c2016-11-22 02:16:47 -08002642 public:
eladalonf1841382017-06-12 01:16:46 -07002643 WebRtcVideoChannelFlexfecRecvTest()
2644 : WebRtcVideoChannelTest("WebRTC-FlexFEC-03-Advertised/Enabled/") {}
brandtr468da7c2016-11-22 02:16:47 -08002645};
2646
eladalonf1841382017-06-12 01:16:46 -07002647TEST_F(WebRtcVideoChannelFlexfecRecvTest,
brandtr36e7d702017-01-13 07:15:54 -08002648 DefaultFlexfecCodecHasTransportCcAndRembFeedbackParam) {
2649 EXPECT_TRUE(cricket::HasTransportCc(GetEngineCodec("flexfec-03")));
2650 EXPECT_TRUE(cricket::HasRemb(GetEngineCodec("flexfec-03")));
2651}
2652
eladalonf1841382017-06-12 01:16:46 -07002653TEST_F(WebRtcVideoChannelFlexfecRecvTest, SetDefaultRecvCodecsWithoutSsrc) {
brandtr31bd2242017-05-19 05:47:46 -07002654 AddRecvStream();
2655
2656 const std::vector<FakeFlexfecReceiveStream*>& streams =
2657 fake_call_->GetFlexfecReceiveStreams();
2658 EXPECT_TRUE(streams.empty());
2659}
2660
eladalonf1841382017-06-12 01:16:46 -07002661TEST_F(WebRtcVideoChannelFlexfecRecvTest, SetDefaultRecvCodecsWithSsrc) {
brandtr31bd2242017-05-19 05:47:46 -07002662 AddRecvStream(
2663 CreatePrimaryWithFecFrStreamParams("cname", kSsrcs1[0], kFlexfecSsrc));
2664
2665 const std::vector<FakeFlexfecReceiveStream*>& streams =
2666 fake_call_->GetFlexfecReceiveStreams();
2667 ASSERT_EQ(1U, streams.size());
2668 const FakeFlexfecReceiveStream* stream = streams.front();
2669 const webrtc::FlexfecReceiveStream::Config& config = stream->GetConfig();
2670 EXPECT_EQ(GetEngineCodec("flexfec-03").id, config.payload_type);
2671 EXPECT_EQ(kFlexfecSsrc, config.remote_ssrc);
2672 ASSERT_EQ(1U, config.protected_media_ssrcs.size());
2673 EXPECT_EQ(kSsrcs1[0], config.protected_media_ssrcs[0]);
brandtr7cd28b92017-09-22 00:26:25 -07002674
2675 const std::vector<FakeVideoReceiveStream*>& video_streams =
2676 fake_call_->GetVideoReceiveStreams();
2677 ASSERT_EQ(1U, video_streams.size());
2678 const webrtc::VideoReceiveStream::Config& video_config =
2679 video_streams.front()->GetConfig();
2680 EXPECT_TRUE(video_config.rtp.protected_by_flexfec);
brandtr31bd2242017-05-19 05:47:46 -07002681}
2682
eladalonf1841382017-06-12 01:16:46 -07002683TEST_F(WebRtcVideoChannelFlexfecRecvTest,
brandtr11fb4722017-05-30 01:31:37 -07002684 EnablingFlexfecDoesNotRecreateVideoReceiveStream) {
2685 cricket::VideoRecvParameters recv_parameters;
2686 recv_parameters.codecs.push_back(GetEngineCodec("VP8"));
2687 ASSERT_TRUE(channel_->SetRecvParameters(recv_parameters));
2688
2689 AddRecvStream(
2690 CreatePrimaryWithFecFrStreamParams("cname", kSsrcs1[0], kFlexfecSsrc));
2691 EXPECT_EQ(1, fake_call_->GetNumCreatedReceiveStreams());
2692 EXPECT_EQ(1U, fake_call_->GetVideoReceiveStreams().size());
2693
2694 // Enable FlexFEC.
2695 recv_parameters.codecs.push_back(GetEngineCodec("flexfec-03"));
2696 ASSERT_TRUE(channel_->SetRecvParameters(recv_parameters));
2697 EXPECT_EQ(2, fake_call_->GetNumCreatedReceiveStreams())
2698 << "Enabling FlexFEC should create FlexfecReceiveStream.";
2699 EXPECT_EQ(1U, fake_call_->GetVideoReceiveStreams().size())
2700 << "Enabling FlexFEC should not create VideoReceiveStream.";
2701 EXPECT_EQ(1U, fake_call_->GetFlexfecReceiveStreams().size())
2702 << "Enabling FlexFEC should create a single FlexfecReceiveStream.";
2703}
2704
eladalonf1841382017-06-12 01:16:46 -07002705TEST_F(WebRtcVideoChannelFlexfecRecvTest,
brandtr11fb4722017-05-30 01:31:37 -07002706 DisablingFlexfecDoesNotRecreateVideoReceiveStream) {
2707 cricket::VideoRecvParameters recv_parameters;
2708 recv_parameters.codecs.push_back(GetEngineCodec("VP8"));
2709 recv_parameters.codecs.push_back(GetEngineCodec("flexfec-03"));
2710 ASSERT_TRUE(channel_->SetRecvParameters(recv_parameters));
2711
2712 AddRecvStream(
2713 CreatePrimaryWithFecFrStreamParams("cname", kSsrcs1[0], kFlexfecSsrc));
2714 EXPECT_EQ(2, fake_call_->GetNumCreatedReceiveStreams());
2715 EXPECT_EQ(1U, fake_call_->GetVideoReceiveStreams().size());
2716 EXPECT_EQ(1U, fake_call_->GetFlexfecReceiveStreams().size());
2717
2718 // Disable FlexFEC.
2719 recv_parameters.codecs.clear();
2720 recv_parameters.codecs.push_back(GetEngineCodec("VP8"));
2721 ASSERT_TRUE(channel_->SetRecvParameters(recv_parameters));
2722 EXPECT_EQ(2, fake_call_->GetNumCreatedReceiveStreams())
2723 << "Disabling FlexFEC should not recreate VideoReceiveStream.";
2724 EXPECT_EQ(1U, fake_call_->GetVideoReceiveStreams().size())
2725 << "Disabling FlexFEC should not destroy VideoReceiveStream.";
2726 EXPECT_TRUE(fake_call_->GetFlexfecReceiveStreams().empty())
2727 << "Disabling FlexFEC should destroy FlexfecReceiveStream.";
2728}
2729
brandtr31bd2242017-05-19 05:47:46 -07002730// TODO(brandtr): When FlexFEC is no longer behind a field trial, merge all
2731// tests that use this test fixture into the corresponding "non-field trial"
2732// tests.
eladalonf1841382017-06-12 01:16:46 -07002733class WebRtcVideoChannelFlexfecSendRecvTest : public WebRtcVideoChannelTest {
brandtr31bd2242017-05-19 05:47:46 -07002734 public:
eladalonf1841382017-06-12 01:16:46 -07002735 WebRtcVideoChannelFlexfecSendRecvTest()
2736 : WebRtcVideoChannelTest(
brandtr31bd2242017-05-19 05:47:46 -07002737 "WebRTC-FlexFEC-03-Advertised/Enabled/WebRTC-FlexFEC-03/Enabled/") {
2738 }
2739};
2740
eladalonf1841382017-06-12 01:16:46 -07002741TEST_F(WebRtcVideoChannelFlexfecSendRecvTest,
brandtr31bd2242017-05-19 05:47:46 -07002742 SetDefaultSendCodecsWithoutSsrc) {
brandtr468da7c2016-11-22 02:16:47 -08002743 FakeVideoSendStream* stream = AddSendStream();
2744 webrtc::VideoSendStream::Config config = stream->GetConfig().Copy();
2745
brandtr3d200bd2017-01-16 06:59:19 -08002746 EXPECT_EQ(GetEngineCodec("flexfec-03").id, config.rtp.flexfec.payload_type);
2747 EXPECT_EQ(0U, config.rtp.flexfec.ssrc);
2748 EXPECT_TRUE(config.rtp.flexfec.protected_media_ssrcs.empty());
brandtr468da7c2016-11-22 02:16:47 -08002749}
2750
eladalonf1841382017-06-12 01:16:46 -07002751TEST_F(WebRtcVideoChannelFlexfecSendRecvTest, SetDefaultSendCodecsWithSsrc) {
brandtr468da7c2016-11-22 02:16:47 -08002752 FakeVideoSendStream* stream = AddSendStream(
2753 CreatePrimaryWithFecFrStreamParams("cname", kSsrcs1[0], kFlexfecSsrc));
2754 webrtc::VideoSendStream::Config config = stream->GetConfig().Copy();
2755
brandtr3d200bd2017-01-16 06:59:19 -08002756 EXPECT_EQ(GetEngineCodec("flexfec-03").id, config.rtp.flexfec.payload_type);
2757 EXPECT_EQ(kFlexfecSsrc, config.rtp.flexfec.ssrc);
2758 ASSERT_EQ(1U, config.rtp.flexfec.protected_media_ssrcs.size());
2759 EXPECT_EQ(kSsrcs1[0], config.rtp.flexfec.protected_media_ssrcs[0]);
brandtr468da7c2016-11-22 02:16:47 -08002760}
2761
eladalonf1841382017-06-12 01:16:46 -07002762TEST_F(WebRtcVideoChannelTest, SetSendCodecsWithoutFec) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02002763 cricket::VideoSendParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08002764 parameters.codecs.push_back(GetEngineCodec("VP8"));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02002765 ASSERT_TRUE(channel_->SetSendParameters(parameters));
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00002766
2767 FakeVideoSendStream* stream = AddSendStream();
perkj26091b12016-09-01 01:17:40 -07002768 webrtc::VideoSendStream::Config config = stream->GetConfig().Copy();
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00002769
brandtrb5f2c3f2016-10-04 23:28:39 -07002770 EXPECT_EQ(-1, config.rtp.ulpfec.ulpfec_payload_type);
2771 EXPECT_EQ(-1, config.rtp.ulpfec.red_payload_type);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00002772}
2773
eladalonf1841382017-06-12 01:16:46 -07002774TEST_F(WebRtcVideoChannelFlexfecSendRecvTest, SetSendCodecsWithoutFec) {
brandtr468da7c2016-11-22 02:16:47 -08002775 cricket::VideoSendParameters parameters;
2776 parameters.codecs.push_back(GetEngineCodec("VP8"));
2777 ASSERT_TRUE(channel_->SetSendParameters(parameters));
2778
2779 FakeVideoSendStream* stream = AddSendStream();
2780 webrtc::VideoSendStream::Config config = stream->GetConfig().Copy();
2781
brandtr3d200bd2017-01-16 06:59:19 -08002782 EXPECT_EQ(-1, config.rtp.flexfec.payload_type);
brandtr468da7c2016-11-22 02:16:47 -08002783}
2784
eladalonf1841382017-06-12 01:16:46 -07002785TEST_F(WebRtcVideoChannelFlexfecRecvTest, SetRecvCodecsWithFec) {
brandtr9c3d4c42017-01-23 06:59:13 -08002786 AddRecvStream(
2787 CreatePrimaryWithFecFrStreamParams("cname", kSsrcs1[0], kFlexfecSsrc));
brandtr9c3d4c42017-01-23 06:59:13 -08002788
2789 cricket::VideoRecvParameters recv_parameters;
2790 recv_parameters.codecs.push_back(GetEngineCodec("VP8"));
2791 recv_parameters.codecs.push_back(GetEngineCodec("flexfec-03"));
2792 ASSERT_TRUE(channel_->SetRecvParameters(recv_parameters));
brandtr9d58d942017-02-03 04:43:41 -08002793
2794 const std::vector<FakeFlexfecReceiveStream*>& flexfec_streams =
2795 fake_call_->GetFlexfecReceiveStreams();
2796 ASSERT_EQ(1U, flexfec_streams.size());
2797 const FakeFlexfecReceiveStream* flexfec_stream = flexfec_streams.front();
2798 const webrtc::FlexfecReceiveStream::Config& flexfec_stream_config =
2799 flexfec_stream->GetConfig();
brandtr9c3d4c42017-01-23 06:59:13 -08002800 EXPECT_EQ(GetEngineCodec("flexfec-03").id,
brandtr9d58d942017-02-03 04:43:41 -08002801 flexfec_stream_config.payload_type);
2802 EXPECT_EQ(kFlexfecSsrc, flexfec_stream_config.remote_ssrc);
2803 ASSERT_EQ(1U, flexfec_stream_config.protected_media_ssrcs.size());
2804 EXPECT_EQ(kSsrcs1[0], flexfec_stream_config.protected_media_ssrcs[0]);
2805 const std::vector<FakeVideoReceiveStream*>& video_streams =
2806 fake_call_->GetVideoReceiveStreams();
2807 const FakeVideoReceiveStream* video_stream = video_streams.front();
2808 const webrtc::VideoReceiveStream::Config& video_stream_config =
2809 video_stream->GetConfig();
2810 EXPECT_EQ(video_stream_config.rtp.local_ssrc,
2811 flexfec_stream_config.local_ssrc);
2812 EXPECT_EQ(video_stream_config.rtp.rtcp_mode, flexfec_stream_config.rtcp_mode);
2813 EXPECT_EQ(video_stream_config.rtcp_send_transport,
2814 flexfec_stream_config.rtcp_send_transport);
2815 // TODO(brandtr): Update this EXPECT when we set |transport_cc| in a
2816 // spec-compliant way.
2817 EXPECT_EQ(video_stream_config.rtp.transport_cc,
2818 flexfec_stream_config.transport_cc);
2819 EXPECT_EQ(video_stream_config.rtp.rtcp_mode, flexfec_stream_config.rtcp_mode);
2820 EXPECT_EQ(video_stream_config.rtp.extensions,
2821 flexfec_stream_config.rtp_header_extensions);
brandtr9c3d4c42017-01-23 06:59:13 -08002822}
2823
brandtr31bd2242017-05-19 05:47:46 -07002824// We should not send FlexFEC, even if we advertise it, unless the right
2825// field trial is set.
2826// TODO(brandtr): Remove when FlexFEC is enabled by default.
eladalonf1841382017-06-12 01:16:46 -07002827TEST_F(WebRtcVideoChannelFlexfecRecvTest,
brandtr31bd2242017-05-19 05:47:46 -07002828 SetSendCodecsWithoutSsrcWithFecDoesNotEnableFec) {
2829 cricket::VideoSendParameters parameters;
2830 parameters.codecs.push_back(GetEngineCodec("VP8"));
2831 parameters.codecs.push_back(GetEngineCodec("flexfec-03"));
2832 ASSERT_TRUE(channel_->SetSendParameters(parameters));
2833
2834 FakeVideoSendStream* stream = AddSendStream();
2835 webrtc::VideoSendStream::Config config = stream->GetConfig().Copy();
2836
2837 EXPECT_EQ(-1, config.rtp.flexfec.payload_type);
2838 EXPECT_EQ(0, config.rtp.flexfec.ssrc);
2839 EXPECT_TRUE(config.rtp.flexfec.protected_media_ssrcs.empty());
2840}
2841
eladalonf1841382017-06-12 01:16:46 -07002842TEST_F(WebRtcVideoChannelFlexfecRecvTest,
brandtr31bd2242017-05-19 05:47:46 -07002843 SetSendCodecsWithSsrcWithFecDoesNotEnableFec) {
2844 cricket::VideoSendParameters parameters;
2845 parameters.codecs.push_back(GetEngineCodec("VP8"));
2846 parameters.codecs.push_back(GetEngineCodec("flexfec-03"));
2847 ASSERT_TRUE(channel_->SetSendParameters(parameters));
2848
2849 FakeVideoSendStream* stream = AddSendStream(
2850 CreatePrimaryWithFecFrStreamParams("cname", kSsrcs1[0], kFlexfecSsrc));
2851 webrtc::VideoSendStream::Config config = stream->GetConfig().Copy();
2852
2853 EXPECT_EQ(-1, config.rtp.flexfec.payload_type);
2854 EXPECT_EQ(0, config.rtp.flexfec.ssrc);
2855 EXPECT_TRUE(config.rtp.flexfec.protected_media_ssrcs.empty());
2856}
2857
eladalonf1841382017-06-12 01:16:46 -07002858TEST_F(WebRtcVideoChannelTest,
pbos@webrtc.org269605c2014-06-26 08:49:03 +00002859 SetSendCodecRejectsRtxWithoutAssociatedPayloadType) {
magjed509e4fe2016-11-18 01:34:11 -08002860 const int kUnusedPayloadType = 127;
2861 EXPECT_FALSE(FindCodecById(engine_.codecs(), kUnusedPayloadType));
2862
Fredrik Solenbergb071a192015-09-17 16:42:56 +02002863 cricket::VideoSendParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08002864 cricket::VideoCodec rtx_codec(kUnusedPayloadType, "rtx");
Fredrik Solenbergb071a192015-09-17 16:42:56 +02002865 parameters.codecs.push_back(rtx_codec);
2866 EXPECT_FALSE(channel_->SetSendParameters(parameters))
pbos@webrtc.org269605c2014-06-26 08:49:03 +00002867 << "RTX codec without associated payload type should be rejected.";
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00002868}
2869
eladalonf1841382017-06-12 01:16:46 -07002870TEST_F(WebRtcVideoChannelTest,
pbos@webrtc.org269605c2014-06-26 08:49:03 +00002871 SetSendCodecRejectsRtxWithoutMatchingVideoCodec) {
magjed509e4fe2016-11-18 01:34:11 -08002872 const int kUnusedPayloadType1 = 126;
2873 const int kUnusedPayloadType2 = 127;
2874 EXPECT_FALSE(FindCodecById(engine_.codecs(), kUnusedPayloadType1));
2875 EXPECT_FALSE(FindCodecById(engine_.codecs(), kUnusedPayloadType2));
2876 {
2877 cricket::VideoCodec rtx_codec = cricket::VideoCodec::CreateRtxCodec(
2878 kUnusedPayloadType1, GetEngineCodec("VP8").id);
2879 cricket::VideoSendParameters parameters;
2880 parameters.codecs.push_back(GetEngineCodec("VP8"));
2881 parameters.codecs.push_back(rtx_codec);
2882 ASSERT_TRUE(channel_->SetSendParameters(parameters));
2883 }
2884 {
2885 cricket::VideoCodec rtx_codec = cricket::VideoCodec::CreateRtxCodec(
2886 kUnusedPayloadType1, kUnusedPayloadType2);
2887 cricket::VideoSendParameters parameters;
2888 parameters.codecs.push_back(GetEngineCodec("VP8"));
2889 parameters.codecs.push_back(rtx_codec);
2890 EXPECT_FALSE(channel_->SetSendParameters(parameters))
2891 << "RTX without matching video codec should be rejected.";
2892 }
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00002893}
2894
eladalonf1841382017-06-12 01:16:46 -07002895TEST_F(WebRtcVideoChannelTest, SetSendCodecsWithChangedRtxPayloadType) {
brandtr14742122017-01-27 04:53:07 -08002896 const int kUnusedPayloadType1 = 126;
2897 const int kUnusedPayloadType2 = 127;
2898 EXPECT_FALSE(FindCodecById(engine_.codecs(), kUnusedPayloadType1));
2899 EXPECT_FALSE(FindCodecById(engine_.codecs(), kUnusedPayloadType2));
2900
2901 // SSRCs for RTX.
2902 cricket::StreamParams params =
2903 cricket::StreamParams::CreateLegacy(kSsrcs1[0]);
2904 params.AddFidSsrc(kSsrcs1[0], kRtxSsrcs1[0]);
2905 AddSendStream(params);
2906
2907 // Original payload type for RTX.
2908 cricket::VideoSendParameters parameters;
2909 parameters.codecs.push_back(GetEngineCodec("VP8"));
2910 cricket::VideoCodec rtx_codec(kUnusedPayloadType1, "rtx");
2911 rtx_codec.SetParam("apt", GetEngineCodec("VP8").id);
2912 parameters.codecs.push_back(rtx_codec);
2913 EXPECT_TRUE(channel_->SetSendParameters(parameters));
2914 ASSERT_EQ(1U, fake_call_->GetVideoSendStreams().size());
2915 const webrtc::VideoSendStream::Config& config_before =
2916 fake_call_->GetVideoSendStreams()[0]->GetConfig();
2917 EXPECT_EQ(kUnusedPayloadType1, config_before.rtp.rtx.payload_type);
2918 ASSERT_EQ(1U, config_before.rtp.rtx.ssrcs.size());
2919 EXPECT_EQ(kRtxSsrcs1[0], config_before.rtp.rtx.ssrcs[0]);
2920
2921 // Change payload type for RTX.
2922 parameters.codecs[1].id = kUnusedPayloadType2;
2923 EXPECT_TRUE(channel_->SetSendParameters(parameters));
2924 ASSERT_EQ(1U, fake_call_->GetVideoSendStreams().size());
2925 const webrtc::VideoSendStream::Config& config_after =
2926 fake_call_->GetVideoSendStreams()[0]->GetConfig();
2927 EXPECT_EQ(kUnusedPayloadType2, config_after.rtp.rtx.payload_type);
2928 ASSERT_EQ(1U, config_after.rtp.rtx.ssrcs.size());
2929 EXPECT_EQ(kRtxSsrcs1[0], config_after.rtp.rtx.ssrcs[0]);
2930}
2931
eladalonf1841382017-06-12 01:16:46 -07002932TEST_F(WebRtcVideoChannelTest, SetSendCodecsWithoutFecDisablesFec) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02002933 cricket::VideoSendParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08002934 parameters.codecs.push_back(GetEngineCodec("VP8"));
2935 parameters.codecs.push_back(GetEngineCodec("ulpfec"));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02002936 ASSERT_TRUE(channel_->SetSendParameters(parameters));
pbos@webrtc.org269605c2014-06-26 08:49:03 +00002937
2938 FakeVideoSendStream* stream = AddSendStream();
perkj26091b12016-09-01 01:17:40 -07002939 webrtc::VideoSendStream::Config config = stream->GetConfig().Copy();
pbos@webrtc.org269605c2014-06-26 08:49:03 +00002940
magjed509e4fe2016-11-18 01:34:11 -08002941 EXPECT_EQ(GetEngineCodec("ulpfec").id, config.rtp.ulpfec.ulpfec_payload_type);
pbos@webrtc.org269605c2014-06-26 08:49:03 +00002942
Fredrik Solenbergb071a192015-09-17 16:42:56 +02002943 parameters.codecs.pop_back();
2944 ASSERT_TRUE(channel_->SetSendParameters(parameters));
pbos@webrtc.org42684be2014-10-03 11:25:45 +00002945 stream = fake_call_->GetVideoSendStreams()[0];
brandtr468da7c2016-11-22 02:16:47 -08002946 ASSERT_TRUE(stream != nullptr);
perkj26091b12016-09-01 01:17:40 -07002947 config = stream->GetConfig().Copy();
brandtrb5f2c3f2016-10-04 23:28:39 -07002948 EXPECT_EQ(-1, config.rtp.ulpfec.ulpfec_payload_type)
brandtr468da7c2016-11-22 02:16:47 -08002949 << "SetSendCodec without ULPFEC should disable current ULPFEC.";
2950}
2951
eladalonf1841382017-06-12 01:16:46 -07002952TEST_F(WebRtcVideoChannelFlexfecSendRecvTest,
brandtr31bd2242017-05-19 05:47:46 -07002953 SetSendCodecsWithoutFecDisablesFec) {
brandtr468da7c2016-11-22 02:16:47 -08002954 cricket::VideoSendParameters parameters;
2955 parameters.codecs.push_back(GetEngineCodec("VP8"));
2956 parameters.codecs.push_back(GetEngineCodec("flexfec-03"));
2957 ASSERT_TRUE(channel_->SetSendParameters(parameters));
2958
2959 FakeVideoSendStream* stream = AddSendStream(
2960 CreatePrimaryWithFecFrStreamParams("cname", kSsrcs1[0], kFlexfecSsrc));
2961 webrtc::VideoSendStream::Config config = stream->GetConfig().Copy();
2962
brandtr3d200bd2017-01-16 06:59:19 -08002963 EXPECT_EQ(GetEngineCodec("flexfec-03").id, config.rtp.flexfec.payload_type);
2964 EXPECT_EQ(kFlexfecSsrc, config.rtp.flexfec.ssrc);
brandtr468da7c2016-11-22 02:16:47 -08002965 ASSERT_EQ(1U, config.rtp.flexfec.protected_media_ssrcs.size());
2966 EXPECT_EQ(kSsrcs1[0], config.rtp.flexfec.protected_media_ssrcs[0]);
2967
2968 parameters.codecs.pop_back();
2969 ASSERT_TRUE(channel_->SetSendParameters(parameters));
2970 stream = fake_call_->GetVideoSendStreams()[0];
2971 ASSERT_TRUE(stream != nullptr);
2972 config = stream->GetConfig().Copy();
brandtr3d200bd2017-01-16 06:59:19 -08002973 EXPECT_EQ(-1, config.rtp.flexfec.payload_type)
brandtr468da7c2016-11-22 02:16:47 -08002974 << "SetSendCodec without FlexFEC should disable current FlexFEC.";
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00002975}
2976
eladalonf1841382017-06-12 01:16:46 -07002977TEST_F(WebRtcVideoChannelTest, SetSendCodecsChangesExistingStreams) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02002978 cricket::VideoSendParameters parameters;
perkj26752742016-10-24 01:21:16 -07002979 cricket::VideoCodec codec(100, "VP8");
2980 codec.SetParam(kCodecParamMaxQuantization, kDefaultQpMax);
2981 parameters.codecs.push_back(codec);
perkjfa10b552016-10-02 23:45:26 -07002982
Fredrik Solenbergb071a192015-09-17 16:42:56 +02002983 ASSERT_TRUE(channel_->SetSendParameters(parameters));
pbos@webrtc.org86196c42015-02-16 21:02:00 +00002984 channel_->SetSend(true);
pbos@webrtc.org38ce7d02014-07-16 08:01:38 +00002985
pbos@webrtc.org86196c42015-02-16 21:02:00 +00002986 FakeVideoSendStream* stream = AddSendStream();
pbos@webrtc.org86196c42015-02-16 21:02:00 +00002987 cricket::FakeVideoCapturer capturer;
deadbeef5a4a75a2016-06-02 16:23:38 -07002988 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, &capturer));
pbos@webrtc.org86196c42015-02-16 21:02:00 +00002989
2990 std::vector<webrtc::VideoStream> streams = stream->GetVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07002991 EXPECT_EQ(kDefaultQpMax, streams[0].max_qp);
pbos@webrtc.org38ce7d02014-07-16 08:01:38 +00002992
Fredrik Solenbergb071a192015-09-17 16:42:56 +02002993 parameters.codecs.clear();
perkj26752742016-10-24 01:21:16 -07002994 codec.SetParam(kCodecParamMaxQuantization, kDefaultQpMax + 1);
2995 parameters.codecs.push_back(codec);
Fredrik Solenbergb071a192015-09-17 16:42:56 +02002996 ASSERT_TRUE(channel_->SetSendParameters(parameters));
pbos@webrtc.org42684be2014-10-03 11:25:45 +00002997 streams = fake_call_->GetVideoSendStreams()[0]->GetVideoStreams();
perkjfa10b552016-10-02 23:45:26 -07002998 EXPECT_EQ(kDefaultQpMax + 1, streams[0].max_qp);
deadbeef5a4a75a2016-06-02 16:23:38 -07002999 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, nullptr));
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00003000}
3001
eladalonf1841382017-06-12 01:16:46 -07003002TEST_F(WebRtcVideoChannelTest, SetSendCodecsWithBitrates) {
pbos@webrtc.org00873182014-11-25 14:03:34 +00003003 SetSendCodecsShouldWorkForBitrates("100", 100000, "150", 150000, "200",
3004 200000);
3005}
3006
eladalonf1841382017-06-12 01:16:46 -07003007TEST_F(WebRtcVideoChannelTest, SetSendCodecsWithHighMaxBitrate) {
pbos@webrtc.orga5f6fb52015-03-23 22:29:39 +00003008 SetSendCodecsShouldWorkForBitrates("", 0, "", -1, "10000", 10000000);
3009 std::vector<webrtc::VideoStream> streams = AddSendStream()->GetVideoStreams();
3010 ASSERT_EQ(1u, streams.size());
3011 EXPECT_EQ(10000000, streams[0].max_bitrate_bps);
3012}
3013
eladalonf1841382017-06-12 01:16:46 -07003014TEST_F(WebRtcVideoChannelTest,
pbos@webrtc.org00873182014-11-25 14:03:34 +00003015 SetSendCodecsWithoutBitratesUsesCorrectDefaults) {
3016 SetSendCodecsShouldWorkForBitrates(
3017 "", 0, "", -1, "", -1);
3018}
3019
eladalonf1841382017-06-12 01:16:46 -07003020TEST_F(WebRtcVideoChannelTest, SetSendCodecsCapsMinAndStartBitrate) {
pbos@webrtc.org00873182014-11-25 14:03:34 +00003021 SetSendCodecsShouldWorkForBitrates("-1", 0, "-100", -1, "", -1);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00003022}
3023
eladalonf1841382017-06-12 01:16:46 -07003024TEST_F(WebRtcVideoChannelTest, SetSendCodecsRejectsMaxLessThanMinBitrate) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003025 send_parameters_.codecs[0].params[kCodecParamMinBitrate] = "300";
3026 send_parameters_.codecs[0].params[kCodecParamMaxBitrate] = "200";
3027 EXPECT_FALSE(channel_->SetSendParameters(send_parameters_));
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00003028}
3029
Taylor Brandstetter58f2bd92016-04-26 17:15:23 -07003030// Test that when both the codec-specific bitrate params and max_bandwidth_bps
3031// are present in the same send parameters, the settings are combined correctly.
eladalonf1841382017-06-12 01:16:46 -07003032TEST_F(WebRtcVideoChannelTest, SetSendCodecsWithBitratesAndMaxSendBandwidth) {
Taylor Brandstetter58f2bd92016-04-26 17:15:23 -07003033 send_parameters_.codecs[0].params[kCodecParamMinBitrate] = "100";
3034 send_parameters_.codecs[0].params[kCodecParamStartBitrate] = "200";
3035 send_parameters_.codecs[0].params[kCodecParamMaxBitrate] = "300";
3036 send_parameters_.max_bandwidth_bps = 400000;
3037 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
3038 EXPECT_EQ(100000, fake_call_->GetConfig().bitrate_config.min_bitrate_bps);
3039 EXPECT_EQ(200000, fake_call_->GetConfig().bitrate_config.start_bitrate_bps);
3040 // We expect max_bandwidth_bps to take priority, if set.
3041 EXPECT_EQ(400000, fake_call_->GetConfig().bitrate_config.max_bitrate_bps);
3042
3043 // Decrease max_bandwidth_bps.
3044 send_parameters_.max_bandwidth_bps = 350000;
3045 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
3046 EXPECT_EQ(100000, fake_call_->GetConfig().bitrate_config.min_bitrate_bps);
3047 // Since the codec isn't changing, start_bitrate_bps should be -1.
3048 EXPECT_EQ(-1, fake_call_->GetConfig().bitrate_config.start_bitrate_bps);
3049 EXPECT_EQ(350000, fake_call_->GetConfig().bitrate_config.max_bitrate_bps);
3050
3051 // Now try again with the values flipped around.
3052 send_parameters_.codecs[0].params[kCodecParamMaxBitrate] = "400";
3053 send_parameters_.max_bandwidth_bps = 300000;
3054 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
3055 EXPECT_EQ(100000, fake_call_->GetConfig().bitrate_config.min_bitrate_bps);
3056 EXPECT_EQ(200000, fake_call_->GetConfig().bitrate_config.start_bitrate_bps);
3057 EXPECT_EQ(300000, fake_call_->GetConfig().bitrate_config.max_bitrate_bps);
3058
3059 // If we change the codec max, max_bandwidth_bps should still apply.
3060 send_parameters_.codecs[0].params[kCodecParamMaxBitrate] = "350";
3061 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
3062 EXPECT_EQ(100000, fake_call_->GetConfig().bitrate_config.min_bitrate_bps);
3063 EXPECT_EQ(200000, fake_call_->GetConfig().bitrate_config.start_bitrate_bps);
3064 EXPECT_EQ(300000, fake_call_->GetConfig().bitrate_config.max_bitrate_bps);
3065}
3066
eladalonf1841382017-06-12 01:16:46 -07003067TEST_F(WebRtcVideoChannelTest,
pbos@webrtc.org00873182014-11-25 14:03:34 +00003068 SetMaxSendBandwidthShouldPreserveOtherBitrates) {
3069 SetSendCodecsShouldWorkForBitrates("100", 100000, "150", 150000, "200",
3070 200000);
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003071 send_parameters_.max_bandwidth_bps = 300000;
3072 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
Stefan Holmere5904162015-03-26 11:11:06 +01003073 EXPECT_EQ(100000, fake_call_->GetConfig().bitrate_config.min_bitrate_bps)
pbos@webrtc.org00873182014-11-25 14:03:34 +00003074 << "Setting max bitrate should keep previous min bitrate.";
Stefan Holmere5904162015-03-26 11:11:06 +01003075 EXPECT_EQ(-1, fake_call_->GetConfig().bitrate_config.start_bitrate_bps)
pbos@webrtc.org00873182014-11-25 14:03:34 +00003076 << "Setting max bitrate should not reset start bitrate.";
Stefan Holmere5904162015-03-26 11:11:06 +01003077 EXPECT_EQ(300000, fake_call_->GetConfig().bitrate_config.max_bitrate_bps);
pbos@webrtc.org00873182014-11-25 14:03:34 +00003078}
3079
eladalonf1841382017-06-12 01:16:46 -07003080TEST_F(WebRtcVideoChannelTest, SetMaxSendBandwidthShouldBeRemovable) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003081 send_parameters_.max_bandwidth_bps = 300000;
3082 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
Stefan Holmere5904162015-03-26 11:11:06 +01003083 EXPECT_EQ(300000, fake_call_->GetConfig().bitrate_config.max_bitrate_bps);
pbos5c7760a2017-03-10 11:23:12 -08003084 // -1 means to disable max bitrate (set infinite).
3085 send_parameters_.max_bandwidth_bps = -1;
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003086 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
Stefan Holmere5904162015-03-26 11:11:06 +01003087 EXPECT_EQ(-1, fake_call_->GetConfig().bitrate_config.max_bitrate_bps)
pbos@webrtc.org00873182014-11-25 14:03:34 +00003088 << "Setting zero max bitrate did not reset start bitrate.";
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00003089}
3090
eladalonf1841382017-06-12 01:16:46 -07003091TEST_F(WebRtcVideoChannelTest, SetMaxSendBandwidthAndAddSendStream) {
perkjfa10b552016-10-02 23:45:26 -07003092 send_parameters_.max_bandwidth_bps = 99999;
3093 FakeVideoSendStream* stream = AddSendStream();
3094 ASSERT_TRUE(channel_->SetSendParameters(send_parameters_));
3095 EXPECT_EQ(send_parameters_.max_bandwidth_bps,
3096 fake_call_->GetConfig().bitrate_config.max_bitrate_bps);
3097 ASSERT_EQ(1u, stream->GetVideoStreams().size());
3098 EXPECT_EQ(send_parameters_.max_bandwidth_bps,
3099 stream->GetVideoStreams()[0].max_bitrate_bps);
3100
3101 send_parameters_.max_bandwidth_bps = 77777;
3102 ASSERT_TRUE(channel_->SetSendParameters(send_parameters_));
3103 EXPECT_EQ(send_parameters_.max_bandwidth_bps,
3104 fake_call_->GetConfig().bitrate_config.max_bitrate_bps);
3105 EXPECT_EQ(send_parameters_.max_bandwidth_bps,
3106 stream->GetVideoStreams()[0].max_bitrate_bps);
3107}
3108
eladalonf1841382017-06-12 01:16:46 -07003109TEST_F(WebRtcVideoChannelTest, SetMaxSendBitrateCanIncreaseSenderBitrate) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003110 cricket::VideoSendParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08003111 parameters.codecs.push_back(GetEngineCodec("VP8"));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003112 ASSERT_TRUE(channel_->SetSendParameters(parameters));
Peter Boströmdfd53fe2015-03-27 15:58:11 +01003113 channel_->SetSend(true);
3114
3115 FakeVideoSendStream* stream = AddSendStream();
3116
Peter Boström3afc8c42016-01-27 16:45:21 +01003117 cricket::FakeVideoCapturer capturer;
deadbeef5a4a75a2016-06-02 16:23:38 -07003118 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, &capturer));
Peter Boström3afc8c42016-01-27 16:45:21 +01003119 EXPECT_EQ(cricket::CS_RUNNING,
3120 capturer.Start(capturer.GetSupportedFormats()->front()));
3121
Peter Boströmdfd53fe2015-03-27 15:58:11 +01003122 std::vector<webrtc::VideoStream> streams = stream->GetVideoStreams();
3123 int initial_max_bitrate_bps = streams[0].max_bitrate_bps;
3124 EXPECT_GT(initial_max_bitrate_bps, 0);
3125
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003126 parameters.max_bandwidth_bps = initial_max_bitrate_bps * 2;
3127 EXPECT_TRUE(channel_->SetSendParameters(parameters));
Peter Boström3afc8c42016-01-27 16:45:21 +01003128 // Insert a frame to update the encoder config.
3129 EXPECT_TRUE(capturer.CaptureFrame());
Peter Boströmdfd53fe2015-03-27 15:58:11 +01003130 streams = stream->GetVideoStreams();
3131 EXPECT_EQ(initial_max_bitrate_bps * 2, streams[0].max_bitrate_bps);
deadbeef5a4a75a2016-06-02 16:23:38 -07003132 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, nullptr));
Peter Boströmdfd53fe2015-03-27 15:58:11 +01003133}
3134
eladalonf1841382017-06-12 01:16:46 -07003135TEST_F(WebRtcVideoChannelTest,
Peter Boströmdfd53fe2015-03-27 15:58:11 +01003136 SetMaxSendBitrateCanIncreaseSimulcastSenderBitrate) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003137 cricket::VideoSendParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08003138 parameters.codecs.push_back(GetEngineCodec("VP8"));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003139 ASSERT_TRUE(channel_->SetSendParameters(parameters));
Peter Boströmdfd53fe2015-03-27 15:58:11 +01003140 channel_->SetSend(true);
3141
3142 FakeVideoSendStream* stream = AddSendStream(
3143 cricket::CreateSimStreamParams("cname", MAKE_VECTOR(kSsrcs3)));
3144
3145 // Send a frame to make sure this scales up to >1 stream (simulcast).
3146 cricket::FakeVideoCapturer capturer;
deadbeef5a4a75a2016-06-02 16:23:38 -07003147 EXPECT_TRUE(channel_->SetVideoSend(kSsrcs3[0], true, nullptr, &capturer));
Peter Boströmdfd53fe2015-03-27 15:58:11 +01003148 EXPECT_EQ(cricket::CS_RUNNING,
3149 capturer.Start(capturer.GetSupportedFormats()->front()));
3150 EXPECT_TRUE(capturer.CaptureFrame());
3151
3152 std::vector<webrtc::VideoStream> streams = stream->GetVideoStreams();
3153 ASSERT_GT(streams.size(), 1u)
3154 << "Without simulcast this test doesn't make sense.";
pbosbe16f792015-10-16 12:49:39 -07003155 int initial_max_bitrate_bps = GetTotalMaxBitrateBps(streams);
Peter Boströmdfd53fe2015-03-27 15:58:11 +01003156 EXPECT_GT(initial_max_bitrate_bps, 0);
3157
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003158 parameters.max_bandwidth_bps = initial_max_bitrate_bps * 2;
3159 EXPECT_TRUE(channel_->SetSendParameters(parameters));
Peter Boström3afc8c42016-01-27 16:45:21 +01003160 // Insert a frame to update the encoder config.
3161 EXPECT_TRUE(capturer.CaptureFrame());
Peter Boströmdfd53fe2015-03-27 15:58:11 +01003162 streams = stream->GetVideoStreams();
pbosbe16f792015-10-16 12:49:39 -07003163 int increased_max_bitrate_bps = GetTotalMaxBitrateBps(streams);
Peter Boströmdfd53fe2015-03-27 15:58:11 +01003164 EXPECT_EQ(initial_max_bitrate_bps * 2, increased_max_bitrate_bps);
3165
deadbeef5a4a75a2016-06-02 16:23:38 -07003166 EXPECT_TRUE(channel_->SetVideoSend(kSsrcs3[0], true, nullptr, nullptr));
Peter Boströmdfd53fe2015-03-27 15:58:11 +01003167}
3168
eladalonf1841382017-06-12 01:16:46 -07003169TEST_F(WebRtcVideoChannelTest, SetSendCodecsWithMaxQuantization) {
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00003170 static const char* kMaxQuantization = "21";
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003171 cricket::VideoSendParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08003172 parameters.codecs.push_back(GetEngineCodec("VP8"));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003173 parameters.codecs[0].params[kCodecParamMaxQuantization] = kMaxQuantization;
3174 EXPECT_TRUE(channel_->SetSendParameters(parameters));
pbos@webrtc.org6ae48c62014-06-06 10:49:19 +00003175 EXPECT_EQ(static_cast<unsigned int>(atoi(kMaxQuantization)),
3176 AddSendStream()->GetVideoStreams().back().max_qp);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00003177
3178 VideoCodec codec;
3179 EXPECT_TRUE(channel_->GetSendCodec(&codec));
3180 EXPECT_EQ(kMaxQuantization, codec.params[kCodecParamMaxQuantization]);
3181}
3182
eladalonf1841382017-06-12 01:16:46 -07003183TEST_F(WebRtcVideoChannelTest, SetSendCodecsRejectBadPayloadTypes) {
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00003184 // TODO(pbos): Should we only allow the dynamic range?
pkasting@chromium.orge7a4a122015-01-28 21:36:55 +00003185 static const int kIncorrectPayloads[] = {-2, -1, 128, 129};
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003186 cricket::VideoSendParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08003187 parameters.codecs.push_back(GetEngineCodec("VP8"));
pkasting@chromium.orge7a4a122015-01-28 21:36:55 +00003188 for (size_t i = 0; i < arraysize(kIncorrectPayloads); ++i) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003189 parameters.codecs[0].id = kIncorrectPayloads[i];
3190 EXPECT_FALSE(channel_->SetSendParameters(parameters))
pkasting@chromium.orgd3245462015-02-23 21:28:22 +00003191 << "Bad payload type '" << kIncorrectPayloads[i] << "' accepted.";
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00003192 }
3193}
3194
eladalonf1841382017-06-12 01:16:46 -07003195TEST_F(WebRtcVideoChannelTest, SetSendCodecsAcceptAllValidPayloadTypes) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003196 cricket::VideoSendParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08003197 parameters.codecs.push_back(GetEngineCodec("VP8"));
magjedf823ede2016-11-12 09:53:04 -08003198 for (int payload_type = 96; payload_type <= 127; ++payload_type) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003199 parameters.codecs[0].id = payload_type;
3200 EXPECT_TRUE(channel_->SetSendParameters(parameters))
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00003201 << "Payload type '" << payload_type << "' rejected.";
3202 }
3203}
3204
deadbeef67cf2c12016-04-13 10:07:16 -07003205// Test that setting the a different set of codecs but with an identical front
3206// codec doesn't result in the stream being recreated.
3207// This may happen when a subsequent negotiation includes fewer codecs, as a
3208// result of one of the codecs being rejected.
eladalonf1841382017-06-12 01:16:46 -07003209TEST_F(WebRtcVideoChannelTest,
deadbeef67cf2c12016-04-13 10:07:16 -07003210 SetSendCodecsIdenticalFirstCodecDoesntRecreateStream) {
3211 cricket::VideoSendParameters parameters1;
magjed509e4fe2016-11-18 01:34:11 -08003212 parameters1.codecs.push_back(GetEngineCodec("VP8"));
3213 parameters1.codecs.push_back(GetEngineCodec("VP9"));
deadbeef67cf2c12016-04-13 10:07:16 -07003214 EXPECT_TRUE(channel_->SetSendParameters(parameters1));
3215
3216 AddSendStream();
3217 EXPECT_EQ(1, fake_call_->GetNumCreatedSendStreams());
3218
3219 cricket::VideoSendParameters parameters2;
magjed509e4fe2016-11-18 01:34:11 -08003220 parameters2.codecs.push_back(GetEngineCodec("VP8"));
deadbeef67cf2c12016-04-13 10:07:16 -07003221 EXPECT_TRUE(channel_->SetSendParameters(parameters2));
3222 EXPECT_EQ(1, fake_call_->GetNumCreatedSendStreams());
3223}
3224
eladalonf1841382017-06-12 01:16:46 -07003225TEST_F(WebRtcVideoChannelTest, SetRecvCodecsWithOnlyVp8) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003226 cricket::VideoRecvParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08003227 parameters.codecs.push_back(GetEngineCodec("VP8"));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003228 EXPECT_TRUE(channel_->SetRecvParameters(parameters));
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00003229}
3230
pbos@webrtc.orge322a172014-06-13 11:47:28 +00003231// Test that we set our inbound RTX codecs properly.
eladalonf1841382017-06-12 01:16:46 -07003232TEST_F(WebRtcVideoChannelTest, SetRecvCodecsWithRtx) {
magjed509e4fe2016-11-18 01:34:11 -08003233 const int kUnusedPayloadType1 = 126;
3234 const int kUnusedPayloadType2 = 127;
3235 EXPECT_FALSE(FindCodecById(engine_.codecs(), kUnusedPayloadType1));
3236 EXPECT_FALSE(FindCodecById(engine_.codecs(), kUnusedPayloadType2));
3237
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003238 cricket::VideoRecvParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08003239 parameters.codecs.push_back(GetEngineCodec("VP8"));
3240 cricket::VideoCodec rtx_codec(kUnusedPayloadType1, "rtx");
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003241 parameters.codecs.push_back(rtx_codec);
3242 EXPECT_FALSE(channel_->SetRecvParameters(parameters))
pbos@webrtc.orge322a172014-06-13 11:47:28 +00003243 << "RTX codec without associated payload should be rejected.";
3244
magjed509e4fe2016-11-18 01:34:11 -08003245 parameters.codecs[1].SetParam("apt", kUnusedPayloadType2);
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003246 EXPECT_FALSE(channel_->SetRecvParameters(parameters))
pbos@webrtc.orge322a172014-06-13 11:47:28 +00003247 << "RTX codec with invalid associated payload type should be rejected.";
3248
magjed509e4fe2016-11-18 01:34:11 -08003249 parameters.codecs[1].SetParam("apt", GetEngineCodec("VP8").id);
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003250 EXPECT_TRUE(channel_->SetRecvParameters(parameters));
pbos@webrtc.orge322a172014-06-13 11:47:28 +00003251
magjed509e4fe2016-11-18 01:34:11 -08003252 cricket::VideoCodec rtx_codec2(kUnusedPayloadType2, "rtx");
pbos@webrtc.orge322a172014-06-13 11:47:28 +00003253 rtx_codec2.SetParam("apt", rtx_codec.id);
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003254 parameters.codecs.push_back(rtx_codec2);
pbos@webrtc.orge322a172014-06-13 11:47:28 +00003255
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003256 EXPECT_FALSE(channel_->SetRecvParameters(parameters)) <<
3257 "RTX codec with another RTX as associated payload type should be "
3258 "rejected.";
pbos@webrtc.orge322a172014-06-13 11:47:28 +00003259}
3260
eladalonf1841382017-06-12 01:16:46 -07003261TEST_F(WebRtcVideoChannelTest, SetRecvCodecsWithChangedRtxPayloadType) {
brandtr14742122017-01-27 04:53:07 -08003262 const int kUnusedPayloadType1 = 126;
3263 const int kUnusedPayloadType2 = 127;
3264 EXPECT_FALSE(FindCodecById(engine_.codecs(), kUnusedPayloadType1));
3265 EXPECT_FALSE(FindCodecById(engine_.codecs(), kUnusedPayloadType2));
3266
3267 // SSRCs for RTX.
3268 cricket::StreamParams params =
3269 cricket::StreamParams::CreateLegacy(kSsrcs1[0]);
3270 params.AddFidSsrc(kSsrcs1[0], kRtxSsrcs1[0]);
3271 AddRecvStream(params);
3272
3273 // Original payload type for RTX.
3274 cricket::VideoRecvParameters parameters;
3275 parameters.codecs.push_back(GetEngineCodec("VP8"));
3276 cricket::VideoCodec rtx_codec(kUnusedPayloadType1, "rtx");
3277 rtx_codec.SetParam("apt", GetEngineCodec("VP8").id);
3278 parameters.codecs.push_back(rtx_codec);
3279 EXPECT_TRUE(channel_->SetRecvParameters(parameters));
3280 ASSERT_EQ(1U, fake_call_->GetVideoReceiveStreams().size());
3281 const webrtc::VideoReceiveStream::Config& config_before =
3282 fake_call_->GetVideoReceiveStreams()[0]->GetConfig();
nisse26e3abb2017-08-25 04:44:25 -07003283 EXPECT_EQ(1U, config_before.rtp.rtx_associated_payload_types.size());
3284 const int* payload_type_before = FindKeyByValue(
3285 config_before.rtp.rtx_associated_payload_types, GetEngineCodec("VP8").id);
3286 ASSERT_NE(payload_type_before, nullptr);
3287 EXPECT_EQ(kUnusedPayloadType1, *payload_type_before);
brandtr14742122017-01-27 04:53:07 -08003288 EXPECT_EQ(kRtxSsrcs1[0], config_before.rtp.rtx_ssrc);
3289
3290 // Change payload type for RTX.
3291 parameters.codecs[1].id = kUnusedPayloadType2;
3292 EXPECT_TRUE(channel_->SetRecvParameters(parameters));
3293 ASSERT_EQ(1U, fake_call_->GetVideoReceiveStreams().size());
3294 const webrtc::VideoReceiveStream::Config& config_after =
3295 fake_call_->GetVideoReceiveStreams()[0]->GetConfig();
nisse26e3abb2017-08-25 04:44:25 -07003296 EXPECT_EQ(1U, config_after.rtp.rtx_associated_payload_types.size());
3297 const int* payload_type_after = FindKeyByValue(
3298 config_after.rtp.rtx_associated_payload_types, GetEngineCodec("VP8").id);
3299 ASSERT_NE(payload_type_after, nullptr);
3300 EXPECT_EQ(kUnusedPayloadType2, *payload_type_after);
brandtr14742122017-01-27 04:53:07 -08003301 EXPECT_EQ(kRtxSsrcs1[0], config_after.rtp.rtx_ssrc);
3302}
3303
eladalonf1841382017-06-12 01:16:46 -07003304TEST_F(WebRtcVideoChannelTest, SetRecvCodecsDifferentPayloadType) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003305 cricket::VideoRecvParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08003306 parameters.codecs.push_back(GetEngineCodec("VP8"));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003307 parameters.codecs[0].id = 99;
3308 EXPECT_TRUE(channel_->SetRecvParameters(parameters));
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00003309}
3310
eladalonf1841382017-06-12 01:16:46 -07003311TEST_F(WebRtcVideoChannelTest, SetRecvCodecsAcceptDefaultCodecs) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003312 cricket::VideoRecvParameters parameters;
3313 parameters.codecs = engine_.codecs();
3314 EXPECT_TRUE(channel_->SetRecvParameters(parameters));
pbos@webrtc.orgccbed3b2014-07-11 13:02:54 +00003315
3316 FakeVideoReceiveStream* stream = AddRecvStream();
Tommi733b5472016-06-10 17:58:01 +02003317 const webrtc::VideoReceiveStream::Config& config = stream->GetConfig();
pbos@webrtc.org776e6f22014-10-29 15:28:39 +00003318 EXPECT_EQ(engine_.codecs()[0].name, config.decoders[0].payload_name);
3319 EXPECT_EQ(engine_.codecs()[0].id, config.decoders[0].payload_type);
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00003320}
3321
eladalonf1841382017-06-12 01:16:46 -07003322TEST_F(WebRtcVideoChannelTest, SetRecvCodecsRejectUnsupportedCodec) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003323 cricket::VideoRecvParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08003324 parameters.codecs.push_back(GetEngineCodec("VP8"));
perkj26752742016-10-24 01:21:16 -07003325 parameters.codecs.push_back(VideoCodec(101, "WTF3"));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003326 EXPECT_FALSE(channel_->SetRecvParameters(parameters));
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00003327}
3328
eladalonf1841382017-06-12 01:16:46 -07003329TEST_F(WebRtcVideoChannelTest, SetRecvCodecsAcceptsMultipleVideoCodecs) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003330 cricket::VideoRecvParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08003331 parameters.codecs.push_back(GetEngineCodec("VP8"));
3332 parameters.codecs.push_back(GetEngineCodec("VP9"));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003333 EXPECT_TRUE(channel_->SetRecvParameters(parameters));
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00003334}
3335
eladalonf1841382017-06-12 01:16:46 -07003336TEST_F(WebRtcVideoChannelTest, SetRecvCodecsWithoutFecDisablesFec) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003337 cricket::VideoSendParameters send_parameters;
magjed509e4fe2016-11-18 01:34:11 -08003338 send_parameters.codecs.push_back(GetEngineCodec("VP8"));
3339 send_parameters.codecs.push_back(GetEngineCodec("red"));
3340 send_parameters.codecs.push_back(GetEngineCodec("ulpfec"));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003341 ASSERT_TRUE(channel_->SetSendParameters(send_parameters));
pbos@webrtc.orgd1ea06b2014-07-18 09:35:58 +00003342
3343 FakeVideoReceiveStream* stream = AddRecvStream();
pbos@webrtc.orgd1ea06b2014-07-18 09:35:58 +00003344
magjed509e4fe2016-11-18 01:34:11 -08003345 EXPECT_EQ(GetEngineCodec("ulpfec").id,
nisse3b3622f2017-09-26 02:49:21 -07003346 stream->GetConfig().rtp.ulpfec_payload_type);
pbos@webrtc.orgd1ea06b2014-07-18 09:35:58 +00003347
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003348 cricket::VideoRecvParameters recv_parameters;
magjed509e4fe2016-11-18 01:34:11 -08003349 recv_parameters.codecs.push_back(GetEngineCodec("VP8"));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003350 ASSERT_TRUE(channel_->SetRecvParameters(recv_parameters));
pbos@webrtc.org42684be2014-10-03 11:25:45 +00003351 stream = fake_call_->GetVideoReceiveStreams()[0];
brandtr468da7c2016-11-22 02:16:47 -08003352 ASSERT_TRUE(stream != nullptr);
nisse3b3622f2017-09-26 02:49:21 -07003353 EXPECT_EQ(-1, stream->GetConfig().rtp.ulpfec_payload_type)
brandtr468da7c2016-11-22 02:16:47 -08003354 << "SetSendCodec without ULPFEC should disable current ULPFEC.";
3355}
3356
eladalonf1841382017-06-12 01:16:46 -07003357TEST_F(WebRtcVideoChannelFlexfecRecvTest, SetRecvParamsWithoutFecDisablesFec) {
brandtr468da7c2016-11-22 02:16:47 -08003358 AddRecvStream(
3359 CreatePrimaryWithFecFrStreamParams("cname", kSsrcs1[0], kFlexfecSsrc));
brandtr9c3d4c42017-01-23 06:59:13 -08003360 const std::vector<FakeFlexfecReceiveStream*>& streams =
brandtr468da7c2016-11-22 02:16:47 -08003361 fake_call_->GetFlexfecReceiveStreams();
3362
3363 ASSERT_EQ(1U, streams.size());
brandtr9c3d4c42017-01-23 06:59:13 -08003364 const FakeFlexfecReceiveStream* stream = streams.front();
3365 EXPECT_EQ(GetEngineCodec("flexfec-03").id, stream->GetConfig().payload_type);
3366 EXPECT_EQ(kFlexfecSsrc, stream->GetConfig().remote_ssrc);
3367 ASSERT_EQ(1U, stream->GetConfig().protected_media_ssrcs.size());
3368 EXPECT_EQ(kSsrcs1[0], stream->GetConfig().protected_media_ssrcs[0]);
brandtr468da7c2016-11-22 02:16:47 -08003369
3370 cricket::VideoRecvParameters recv_parameters;
3371 recv_parameters.codecs.push_back(GetEngineCodec("VP8"));
3372 ASSERT_TRUE(channel_->SetRecvParameters(recv_parameters));
3373 EXPECT_TRUE(streams.empty())
3374 << "SetSendCodec without FlexFEC should disable current FlexFEC.";
pbos@webrtc.org269605c2014-06-26 08:49:03 +00003375}
3376
eladalonf1841382017-06-12 01:16:46 -07003377TEST_F(WebRtcVideoChannelTest, SetSendParamsWithFecEnablesFec) {
Stefan Holmer2b1f6512016-05-17 16:33:30 +02003378 FakeVideoReceiveStream* stream = AddRecvStream();
magjed509e4fe2016-11-18 01:34:11 -08003379 EXPECT_EQ(GetEngineCodec("ulpfec").id,
nisse3b3622f2017-09-26 02:49:21 -07003380 stream->GetConfig().rtp.ulpfec_payload_type);
Stefan Holmer2b1f6512016-05-17 16:33:30 +02003381
3382 cricket::VideoRecvParameters recv_parameters;
magjed509e4fe2016-11-18 01:34:11 -08003383 recv_parameters.codecs.push_back(GetEngineCodec("VP8"));
3384 recv_parameters.codecs.push_back(GetEngineCodec("red"));
3385 recv_parameters.codecs.push_back(GetEngineCodec("ulpfec"));
Stefan Holmer2b1f6512016-05-17 16:33:30 +02003386 ASSERT_TRUE(channel_->SetRecvParameters(recv_parameters));
3387 stream = fake_call_->GetVideoReceiveStreams()[0];
brandtr468da7c2016-11-22 02:16:47 -08003388 ASSERT_TRUE(stream != nullptr);
magjed509e4fe2016-11-18 01:34:11 -08003389 EXPECT_EQ(GetEngineCodec("ulpfec").id,
nisse3b3622f2017-09-26 02:49:21 -07003390 stream->GetConfig().rtp.ulpfec_payload_type)
brandtr468da7c2016-11-22 02:16:47 -08003391 << "ULPFEC should be enabled on the receive stream.";
Stefan Holmer2b1f6512016-05-17 16:33:30 +02003392
3393 cricket::VideoSendParameters send_parameters;
magjed509e4fe2016-11-18 01:34:11 -08003394 send_parameters.codecs.push_back(GetEngineCodec("VP8"));
3395 send_parameters.codecs.push_back(GetEngineCodec("red"));
3396 send_parameters.codecs.push_back(GetEngineCodec("ulpfec"));
Stefan Holmer2b1f6512016-05-17 16:33:30 +02003397 ASSERT_TRUE(channel_->SetSendParameters(send_parameters));
3398 stream = fake_call_->GetVideoReceiveStreams()[0];
magjed509e4fe2016-11-18 01:34:11 -08003399 EXPECT_EQ(GetEngineCodec("ulpfec").id,
nisse3b3622f2017-09-26 02:49:21 -07003400 stream->GetConfig().rtp.ulpfec_payload_type)
brandtr468da7c2016-11-22 02:16:47 -08003401 << "ULPFEC should be enabled on the receive stream.";
3402}
3403
eladalonf1841382017-06-12 01:16:46 -07003404TEST_F(WebRtcVideoChannelFlexfecSendRecvTest,
brandtr31bd2242017-05-19 05:47:46 -07003405 SetSendRecvParamsWithFecEnablesFec) {
brandtr468da7c2016-11-22 02:16:47 -08003406 AddRecvStream(
3407 CreatePrimaryWithFecFrStreamParams("cname", kSsrcs1[0], kFlexfecSsrc));
brandtr9c3d4c42017-01-23 06:59:13 -08003408 const std::vector<FakeFlexfecReceiveStream*>& streams =
brandtr468da7c2016-11-22 02:16:47 -08003409 fake_call_->GetFlexfecReceiveStreams();
3410
3411 cricket::VideoRecvParameters recv_parameters;
3412 recv_parameters.codecs.push_back(GetEngineCodec("VP8"));
3413 recv_parameters.codecs.push_back(GetEngineCodec("flexfec-03"));
3414 ASSERT_TRUE(channel_->SetRecvParameters(recv_parameters));
3415 ASSERT_EQ(1U, streams.size());
brandtr9c3d4c42017-01-23 06:59:13 -08003416 const FakeFlexfecReceiveStream* stream_with_recv_params = streams.front();
brandtr468da7c2016-11-22 02:16:47 -08003417 EXPECT_EQ(GetEngineCodec("flexfec-03").id,
brandtr9c3d4c42017-01-23 06:59:13 -08003418 stream_with_recv_params->GetConfig().payload_type);
3419 EXPECT_EQ(kFlexfecSsrc, stream_with_recv_params->GetConfig().remote_ssrc);
brandtr468da7c2016-11-22 02:16:47 -08003420 EXPECT_EQ(1U,
brandtr9c3d4c42017-01-23 06:59:13 -08003421 stream_with_recv_params->GetConfig().protected_media_ssrcs.size());
brandtr468da7c2016-11-22 02:16:47 -08003422 EXPECT_EQ(kSsrcs1[0],
brandtr9c3d4c42017-01-23 06:59:13 -08003423 stream_with_recv_params->GetConfig().protected_media_ssrcs[0]);
brandtr468da7c2016-11-22 02:16:47 -08003424
3425 cricket::VideoSendParameters send_parameters;
3426 send_parameters.codecs.push_back(GetEngineCodec("VP8"));
3427 send_parameters.codecs.push_back(GetEngineCodec("flexfec-03"));
3428 ASSERT_TRUE(channel_->SetSendParameters(send_parameters));
3429 ASSERT_EQ(1U, streams.size());
brandtr9c3d4c42017-01-23 06:59:13 -08003430 const FakeFlexfecReceiveStream* stream_with_send_params = streams.front();
brandtr468da7c2016-11-22 02:16:47 -08003431 EXPECT_EQ(GetEngineCodec("flexfec-03").id,
brandtr9c3d4c42017-01-23 06:59:13 -08003432 stream_with_send_params->GetConfig().payload_type);
3433 EXPECT_EQ(kFlexfecSsrc, stream_with_send_params->GetConfig().remote_ssrc);
brandtr468da7c2016-11-22 02:16:47 -08003434 EXPECT_EQ(1U,
brandtr9c3d4c42017-01-23 06:59:13 -08003435 stream_with_send_params->GetConfig().protected_media_ssrcs.size());
brandtr468da7c2016-11-22 02:16:47 -08003436 EXPECT_EQ(kSsrcs1[0],
brandtr9c3d4c42017-01-23 06:59:13 -08003437 stream_with_send_params->GetConfig().protected_media_ssrcs[0]);
Stefan Holmer2b1f6512016-05-17 16:33:30 +02003438}
3439
eladalonf1841382017-06-12 01:16:46 -07003440TEST_F(WebRtcVideoChannelTest, SetRecvCodecsRejectDuplicateFecPayloads) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003441 cricket::VideoRecvParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08003442 parameters.codecs.push_back(GetEngineCodec("VP8"));
3443 parameters.codecs.push_back(GetEngineCodec("red"));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003444 parameters.codecs[1].id = parameters.codecs[0].id;
3445 EXPECT_FALSE(channel_->SetRecvParameters(parameters));
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00003446}
3447
eladalonf1841382017-06-12 01:16:46 -07003448TEST_F(WebRtcVideoChannelFlexfecRecvTest,
brandtr31bd2242017-05-19 05:47:46 -07003449 SetRecvCodecsRejectDuplicateFecPayloads) {
brandtr468da7c2016-11-22 02:16:47 -08003450 cricket::VideoRecvParameters parameters;
3451 parameters.codecs.push_back(GetEngineCodec("VP8"));
3452 parameters.codecs.push_back(GetEngineCodec("flexfec-03"));
3453 parameters.codecs[1].id = parameters.codecs[0].id;
3454 EXPECT_FALSE(channel_->SetRecvParameters(parameters));
3455}
3456
eladalonf1841382017-06-12 01:16:46 -07003457TEST_F(WebRtcVideoChannelTest, SetRecvCodecsRejectDuplicateCodecPayloads) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003458 cricket::VideoRecvParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08003459 parameters.codecs.push_back(GetEngineCodec("VP8"));
3460 parameters.codecs.push_back(GetEngineCodec("VP9"));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003461 parameters.codecs[1].id = parameters.codecs[0].id;
3462 EXPECT_FALSE(channel_->SetRecvParameters(parameters));
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00003463}
3464
eladalonf1841382017-06-12 01:16:46 -07003465TEST_F(WebRtcVideoChannelTest,
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00003466 SetRecvCodecsAcceptSameCodecOnMultiplePayloadTypes) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003467 cricket::VideoRecvParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08003468 parameters.codecs.push_back(GetEngineCodec("VP8"));
3469 parameters.codecs.push_back(GetEngineCodec("VP8"));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003470 parameters.codecs[1].id += 1;
3471 EXPECT_TRUE(channel_->SetRecvParameters(parameters));
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00003472}
3473
deadbeef67cf2c12016-04-13 10:07:16 -07003474// Test that setting the same codecs but with a different order
deadbeef874ca3a2015-08-20 17:19:20 -07003475// doesn't result in the stream being recreated.
eladalonf1841382017-06-12 01:16:46 -07003476TEST_F(WebRtcVideoChannelTest,
deadbeef67cf2c12016-04-13 10:07:16 -07003477 SetRecvCodecsDifferentOrderDoesntRecreateStream) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003478 cricket::VideoRecvParameters parameters1;
magjed509e4fe2016-11-18 01:34:11 -08003479 parameters1.codecs.push_back(GetEngineCodec("VP8"));
3480 parameters1.codecs.push_back(GetEngineCodec("red"));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003481 EXPECT_TRUE(channel_->SetRecvParameters(parameters1));
deadbeef874ca3a2015-08-20 17:19:20 -07003482
3483 AddRecvStream(cricket::StreamParams::CreateLegacy(123));
3484 EXPECT_EQ(1, fake_call_->GetNumCreatedReceiveStreams());
3485
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003486 cricket::VideoRecvParameters parameters2;
magjed509e4fe2016-11-18 01:34:11 -08003487 parameters2.codecs.push_back(GetEngineCodec("red"));
3488 parameters2.codecs.push_back(GetEngineCodec("VP8"));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003489 EXPECT_TRUE(channel_->SetRecvParameters(parameters2));
deadbeef874ca3a2015-08-20 17:19:20 -07003490 EXPECT_EQ(1, fake_call_->GetNumCreatedReceiveStreams());
3491}
3492
eladalonf1841382017-06-12 01:16:46 -07003493TEST_F(WebRtcVideoChannelTest, SendStreamNotSendingByDefault) {
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00003494 EXPECT_FALSE(AddSendStream()->IsSending());
3495}
3496
eladalonf1841382017-06-12 01:16:46 -07003497TEST_F(WebRtcVideoChannelTest, ReceiveStreamReceivingByDefault) {
pbos@webrtc.org85f42942014-07-22 09:14:58 +00003498 EXPECT_TRUE(AddRecvStream()->IsReceiving());
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00003499}
3500
eladalonf1841382017-06-12 01:16:46 -07003501TEST_F(WebRtcVideoChannelTest, SetSend) {
pbos@webrtc.org5301b0f2014-07-17 08:51:46 +00003502 FakeVideoSendStream* stream = AddSendStream();
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00003503 EXPECT_FALSE(stream->IsSending());
3504
3505 // false->true
3506 EXPECT_TRUE(channel_->SetSend(true));
3507 EXPECT_TRUE(stream->IsSending());
3508 // true->true
3509 EXPECT_TRUE(channel_->SetSend(true));
3510 EXPECT_TRUE(stream->IsSending());
3511 // true->false
3512 EXPECT_TRUE(channel_->SetSend(false));
3513 EXPECT_FALSE(stream->IsSending());
3514 // false->false
3515 EXPECT_TRUE(channel_->SetSend(false));
3516 EXPECT_FALSE(stream->IsSending());
3517
3518 EXPECT_TRUE(channel_->SetSend(true));
3519 FakeVideoSendStream* new_stream = AddSendStream();
3520 EXPECT_TRUE(new_stream->IsSending())
3521 << "Send stream created after SetSend(true) not sending initially.";
3522}
3523
pbos@webrtc.orgd8198032014-11-10 14:41:43 +00003524// This test verifies DSCP settings are properly applied on video media channel.
eladalonf1841382017-06-12 01:16:46 -07003525TEST_F(WebRtcVideoChannelTest, TestSetDscpOptions) {
kwiberg686a8ef2016-02-26 03:00:35 -08003526 std::unique_ptr<cricket::FakeNetworkInterface> network_interface(
pbos@webrtc.orgd8198032014-11-10 14:41:43 +00003527 new cricket::FakeNetworkInterface);
nisse51542be2016-02-12 02:27:06 -08003528 MediaConfig config;
kwiberg686a8ef2016-02-26 03:00:35 -08003529 std::unique_ptr<VideoMediaChannel> channel;
nisse51542be2016-02-12 02:27:06 -08003530
3531 channel.reset(engine_.CreateChannel(call_.get(), config, VideoOptions()));
3532 channel->SetInterface(network_interface.get());
3533 // Default value when DSCP is disabled should be DSCP_DEFAULT.
pbos@webrtc.orgd8198032014-11-10 14:41:43 +00003534 EXPECT_EQ(rtc::DSCP_DEFAULT, network_interface->dscp());
nisse51542be2016-02-12 02:27:06 -08003535
3536 config.enable_dscp = true;
3537 channel.reset(engine_.CreateChannel(call_.get(), config, VideoOptions()));
3538 channel->SetInterface(network_interface.get());
3539 EXPECT_EQ(rtc::DSCP_AF41, network_interface->dscp());
3540
3541 // Verify that setting the option to false resets the
3542 // DiffServCodePoint.
3543 config.enable_dscp = false;
3544 channel.reset(engine_.CreateChannel(call_.get(), config, VideoOptions()));
3545 channel->SetInterface(network_interface.get());
3546 EXPECT_EQ(rtc::DSCP_DEFAULT, network_interface->dscp());
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00003547}
3548
deadbeef13871492015-12-09 12:37:51 -08003549// This test verifies that the RTCP reduced size mode is properly applied to
3550// send video streams.
eladalonf1841382017-06-12 01:16:46 -07003551TEST_F(WebRtcVideoChannelTest, TestSetSendRtcpReducedSize) {
deadbeef13871492015-12-09 12:37:51 -08003552 // Create stream, expecting that default mode is "compound".
3553 FakeVideoSendStream* stream1 = AddSendStream();
3554 EXPECT_EQ(webrtc::RtcpMode::kCompound, stream1->GetConfig().rtp.rtcp_mode);
3555
3556 // Now enable reduced size mode.
3557 send_parameters_.rtcp.reduced_size = true;
3558 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
3559 stream1 = fake_call_->GetVideoSendStreams()[0];
3560 EXPECT_EQ(webrtc::RtcpMode::kReducedSize, stream1->GetConfig().rtp.rtcp_mode);
3561
3562 // Create a new stream and ensure it picks up the reduced size mode.
3563 FakeVideoSendStream* stream2 = AddSendStream();
3564 EXPECT_EQ(webrtc::RtcpMode::kReducedSize, stream2->GetConfig().rtp.rtcp_mode);
3565}
3566
3567// This test verifies that the RTCP reduced size mode is properly applied to
3568// receive video streams.
eladalonf1841382017-06-12 01:16:46 -07003569TEST_F(WebRtcVideoChannelTest, TestSetRecvRtcpReducedSize) {
deadbeef13871492015-12-09 12:37:51 -08003570 // Create stream, expecting that default mode is "compound".
3571 FakeVideoReceiveStream* stream1 = AddRecvStream();
3572 EXPECT_EQ(webrtc::RtcpMode::kCompound, stream1->GetConfig().rtp.rtcp_mode);
3573
3574 // Now enable reduced size mode.
Taylor Brandstetter5f0b83b2016-03-18 15:02:07 -07003575 // TODO(deadbeef): Once "recv_parameters" becomes "receiver_parameters",
3576 // the reduced_size flag should come from that.
3577 send_parameters_.rtcp.reduced_size = true;
3578 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
deadbeef13871492015-12-09 12:37:51 -08003579 stream1 = fake_call_->GetVideoReceiveStreams()[0];
3580 EXPECT_EQ(webrtc::RtcpMode::kReducedSize, stream1->GetConfig().rtp.rtcp_mode);
3581
3582 // Create a new stream and ensure it picks up the reduced size mode.
3583 FakeVideoReceiveStream* stream2 = AddRecvStream();
3584 EXPECT_EQ(webrtc::RtcpMode::kReducedSize, stream2->GetConfig().rtp.rtcp_mode);
3585}
3586
eladalonf1841382017-06-12 01:16:46 -07003587TEST_F(WebRtcVideoChannelTest, OnReadyToSendSignalsNetworkState) {
skvlad7a43d252016-03-22 15:32:27 -07003588 EXPECT_EQ(webrtc::kNetworkUp,
3589 fake_call_->GetNetworkState(webrtc::MediaType::VIDEO));
3590 EXPECT_EQ(webrtc::kNetworkUp,
3591 fake_call_->GetNetworkState(webrtc::MediaType::AUDIO));
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003592
3593 channel_->OnReadyToSend(false);
skvlad7a43d252016-03-22 15:32:27 -07003594 EXPECT_EQ(webrtc::kNetworkDown,
3595 fake_call_->GetNetworkState(webrtc::MediaType::VIDEO));
3596 EXPECT_EQ(webrtc::kNetworkUp,
3597 fake_call_->GetNetworkState(webrtc::MediaType::AUDIO));
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00003598
3599 channel_->OnReadyToSend(true);
skvlad7a43d252016-03-22 15:32:27 -07003600 EXPECT_EQ(webrtc::kNetworkUp,
3601 fake_call_->GetNetworkState(webrtc::MediaType::VIDEO));
3602 EXPECT_EQ(webrtc::kNetworkUp,
3603 fake_call_->GetNetworkState(webrtc::MediaType::AUDIO));
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00003604}
3605
eladalonf1841382017-06-12 01:16:46 -07003606TEST_F(WebRtcVideoChannelTest, GetStatsReportsSentCodecName) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003607 cricket::VideoSendParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08003608 parameters.codecs.push_back(GetEngineCodec("VP8"));
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003609 EXPECT_TRUE(channel_->SetSendParameters(parameters));
Peter Boström74d9ed72015-03-26 16:28:31 +01003610
3611 AddSendStream();
3612
3613 cricket::VideoMediaInfo info;
3614 ASSERT_TRUE(channel_->GetStats(&info));
magjed509e4fe2016-11-18 01:34:11 -08003615 EXPECT_EQ("VP8", info.senders[0].codec_name);
Peter Boström74d9ed72015-03-26 16:28:31 +01003616}
3617
eladalonf1841382017-06-12 01:16:46 -07003618TEST_F(WebRtcVideoChannelTest, GetStatsReportsEncoderImplementationName) {
Peter Boströmb7d9a972015-12-18 16:01:11 +01003619 FakeVideoSendStream* stream = AddSendStream();
3620 webrtc::VideoSendStream::Stats stats;
3621 stats.encoder_implementation_name = "encoder_implementation_name";
3622 stream->SetStats(stats);
3623
3624 cricket::VideoMediaInfo info;
3625 ASSERT_TRUE(channel_->GetStats(&info));
3626 EXPECT_EQ(stats.encoder_implementation_name,
3627 info.senders[0].encoder_implementation_name);
3628}
3629
eladalonf1841382017-06-12 01:16:46 -07003630TEST_F(WebRtcVideoChannelTest, GetStatsReportsCpuOveruseMetrics) {
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00003631 FakeVideoSendStream* stream = AddSendStream();
3632 webrtc::VideoSendStream::Stats stats;
3633 stats.avg_encode_time_ms = 13;
3634 stats.encode_usage_percent = 42;
3635 stream->SetStats(stats);
3636
3637 cricket::VideoMediaInfo info;
pbos@webrtc.org058b1f12015-03-04 08:54:32 +00003638 ASSERT_TRUE(channel_->GetStats(&info));
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00003639 EXPECT_EQ(stats.avg_encode_time_ms, info.senders[0].avg_encode_ms);
3640 EXPECT_EQ(stats.encode_usage_percent, info.senders[0].encode_usage_percent);
3641}
3642
eladalonf1841382017-06-12 01:16:46 -07003643TEST_F(WebRtcVideoChannelTest, GetStatsReportsFramesEncoded) {
sakal43536c32016-10-24 01:46:43 -07003644 FakeVideoSendStream* stream = AddSendStream();
3645 webrtc::VideoSendStream::Stats stats;
3646 stats.frames_encoded = 13;
3647 stream->SetStats(stats);
3648
3649 cricket::VideoMediaInfo info;
3650 ASSERT_TRUE(channel_->GetStats(&info));
3651 EXPECT_EQ(stats.frames_encoded, info.senders[0].frames_encoded);
3652}
3653
eladalonf1841382017-06-12 01:16:46 -07003654TEST_F(WebRtcVideoChannelTest, GetStatsReportsQpSum) {
sakal87da4042016-10-31 06:53:47 -07003655 FakeVideoSendStream* stream = AddSendStream();
3656 webrtc::VideoSendStream::Stats stats;
3657 stats.qp_sum = rtc::Optional<uint64_t>(13);
3658 stream->SetStats(stats);
3659
3660 cricket::VideoMediaInfo info;
3661 ASSERT_TRUE(channel_->GetStats(&info));
3662 EXPECT_EQ(stats.qp_sum, info.senders[0].qp_sum);
3663}
3664
eladalonf1841382017-06-12 01:16:46 -07003665TEST_F(WebRtcVideoChannelTest, GetStatsReportsUpperResolution) {
pbos@webrtc.org273a4142014-12-01 15:23:21 +00003666 FakeVideoSendStream* stream = AddSendStream();
3667 webrtc::VideoSendStream::Stats stats;
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00003668 stats.substreams[17].width = 123;
3669 stats.substreams[17].height = 40;
3670 stats.substreams[42].width = 80;
3671 stats.substreams[42].height = 31;
3672 stats.substreams[11].width = 20;
3673 stats.substreams[11].height = 90;
pbos@webrtc.org273a4142014-12-01 15:23:21 +00003674 stream->SetStats(stats);
3675
3676 cricket::VideoMediaInfo info;
pbos@webrtc.org058b1f12015-03-04 08:54:32 +00003677 ASSERT_TRUE(channel_->GetStats(&info));
pbos@webrtc.org273a4142014-12-01 15:23:21 +00003678 ASSERT_EQ(1u, info.senders.size());
3679 EXPECT_EQ(123, info.senders[0].send_frame_width);
3680 EXPECT_EQ(90, info.senders[0].send_frame_height);
3681}
3682
eladalonf1841382017-06-12 01:16:46 -07003683TEST_F(WebRtcVideoChannelTest, GetStatsReportsPreferredBitrate) {
Pera48ddb72016-09-29 11:48:50 +02003684 FakeVideoSendStream* stream = AddSendStream();
3685 webrtc::VideoSendStream::Stats stats;
3686 stats.preferred_media_bitrate_bps = 5;
3687 stream->SetStats(stats);
3688
3689 cricket::VideoMediaInfo info;
3690 ASSERT_TRUE(channel_->GetStats(&info));
3691 ASSERT_EQ(1u, info.senders.size());
3692 EXPECT_EQ(5, info.senders[0].preferred_bitrate);
3693}
3694
eladalonf1841382017-06-12 01:16:46 -07003695TEST_F(WebRtcVideoChannelTest, GetStatsReportsCpuAdaptationStats) {
perkj803d97f2016-11-01 11:45:46 -07003696 FakeVideoSendStream* stream = AddSendStream();
3697 webrtc::VideoSendStream::Stats stats;
3698 stats.number_of_cpu_adapt_changes = 2;
3699 stats.cpu_limited_resolution = true;
3700 stream->SetStats(stats);
pbos@webrtc.org9a4410e2015-02-26 10:03:39 +00003701
pbos@webrtc.org9a4410e2015-02-26 10:03:39 +00003702 cricket::VideoMediaInfo info;
pbos@webrtc.org058b1f12015-03-04 08:54:32 +00003703 EXPECT_TRUE(channel_->GetStats(&info));
pbos@webrtc.org9a4410e2015-02-26 10:03:39 +00003704 ASSERT_EQ(1U, info.senders.size());
eladalonf1841382017-06-12 01:16:46 -07003705 EXPECT_EQ(WebRtcVideoChannel::ADAPTREASON_CPU, info.senders[0].adapt_reason);
perkj803d97f2016-11-01 11:45:46 -07003706 EXPECT_EQ(stats.number_of_cpu_adapt_changes, info.senders[0].adapt_changes);
pbos@webrtc.org9a4410e2015-02-26 10:03:39 +00003707}
3708
eladalonf1841382017-06-12 01:16:46 -07003709TEST_F(WebRtcVideoChannelTest, GetStatsReportsAdaptationAndBandwidthStats) {
perkj803d97f2016-11-01 11:45:46 -07003710 FakeVideoSendStream* stream = AddSendStream();
asapersson17821db2015-12-14 02:08:12 -08003711 webrtc::VideoSendStream::Stats stats;
perkj803d97f2016-11-01 11:45:46 -07003712 stats.number_of_cpu_adapt_changes = 2;
3713 stats.cpu_limited_resolution = true;
asapersson17821db2015-12-14 02:08:12 -08003714 stats.bw_limited_resolution = true;
perkj803d97f2016-11-01 11:45:46 -07003715 stream->SetStats(stats);
3716
3717 cricket::VideoMediaInfo info;
asapersson17821db2015-12-14 02:08:12 -08003718 EXPECT_TRUE(channel_->GetStats(&info));
3719 ASSERT_EQ(1U, info.senders.size());
eladalonf1841382017-06-12 01:16:46 -07003720 EXPECT_EQ(WebRtcVideoChannel::ADAPTREASON_CPU |
3721 WebRtcVideoChannel::ADAPTREASON_BANDWIDTH,
asapersson17821db2015-12-14 02:08:12 -08003722 info.senders[0].adapt_reason);
perkj803d97f2016-11-01 11:45:46 -07003723 EXPECT_EQ(stats.number_of_cpu_adapt_changes, info.senders[0].adapt_changes);
asapersson17821db2015-12-14 02:08:12 -08003724}
3725
eladalonf1841382017-06-12 01:16:46 -07003726TEST_F(WebRtcVideoChannelTest,
asapersson17821db2015-12-14 02:08:12 -08003727 GetStatsTranslatesBandwidthLimitedResolutionCorrectly) {
3728 FakeVideoSendStream* stream = AddSendStream();
3729 webrtc::VideoSendStream::Stats stats;
3730 stats.bw_limited_resolution = true;
3731 stream->SetStats(stats);
3732
3733 cricket::VideoMediaInfo info;
3734 EXPECT_TRUE(channel_->GetStats(&info));
3735 ASSERT_EQ(1U, info.senders.size());
eladalonf1841382017-06-12 01:16:46 -07003736 EXPECT_EQ(WebRtcVideoChannel::ADAPTREASON_BANDWIDTH,
asapersson17821db2015-12-14 02:08:12 -08003737 info.senders[0].adapt_reason);
3738}
3739
eladalonf1841382017-06-12 01:16:46 -07003740TEST_F(WebRtcVideoChannelTest,
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003741 GetStatsTranslatesSendRtcpPacketTypesCorrectly) {
3742 FakeVideoSendStream* stream = AddSendStream();
3743 webrtc::VideoSendStream::Stats stats;
3744 stats.substreams[17].rtcp_packet_type_counts.fir_packets = 2;
3745 stats.substreams[17].rtcp_packet_type_counts.nack_packets = 3;
3746 stats.substreams[17].rtcp_packet_type_counts.pli_packets = 4;
3747
3748 stats.substreams[42].rtcp_packet_type_counts.fir_packets = 5;
3749 stats.substreams[42].rtcp_packet_type_counts.nack_packets = 7;
3750 stats.substreams[42].rtcp_packet_type_counts.pli_packets = 9;
3751
3752 stream->SetStats(stats);
3753
3754 cricket::VideoMediaInfo info;
pbos@webrtc.org058b1f12015-03-04 08:54:32 +00003755 ASSERT_TRUE(channel_->GetStats(&info));
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003756 EXPECT_EQ(7, info.senders[0].firs_rcvd);
3757 EXPECT_EQ(10, info.senders[0].nacks_rcvd);
3758 EXPECT_EQ(13, info.senders[0].plis_rcvd);
3759}
3760
eladalonf1841382017-06-12 01:16:46 -07003761TEST_F(WebRtcVideoChannelTest,
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003762 GetStatsTranslatesReceiveRtcpPacketTypesCorrectly) {
3763 FakeVideoReceiveStream* stream = AddRecvStream();
3764 webrtc::VideoReceiveStream::Stats stats;
3765 stats.rtcp_packet_type_counts.fir_packets = 2;
3766 stats.rtcp_packet_type_counts.nack_packets = 3;
3767 stats.rtcp_packet_type_counts.pli_packets = 4;
3768 stream->SetStats(stats);
3769
3770 cricket::VideoMediaInfo info;
pbos@webrtc.org058b1f12015-03-04 08:54:32 +00003771 ASSERT_TRUE(channel_->GetStats(&info));
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00003772 EXPECT_EQ(stats.rtcp_packet_type_counts.fir_packets,
3773 info.receivers[0].firs_sent);
3774 EXPECT_EQ(stats.rtcp_packet_type_counts.nack_packets,
3775 info.receivers[0].nacks_sent);
3776 EXPECT_EQ(stats.rtcp_packet_type_counts.pli_packets,
3777 info.receivers[0].plis_sent);
3778}
3779
eladalonf1841382017-06-12 01:16:46 -07003780TEST_F(WebRtcVideoChannelTest, GetStatsTranslatesDecodeStatsCorrectly) {
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00003781 FakeVideoReceiveStream* stream = AddRecvStream();
3782 webrtc::VideoReceiveStream::Stats stats;
Peter Boströmb7d9a972015-12-18 16:01:11 +01003783 stats.decoder_implementation_name = "decoder_implementation_name";
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00003784 stats.decode_ms = 2;
3785 stats.max_decode_ms = 3;
3786 stats.current_delay_ms = 4;
3787 stats.target_delay_ms = 5;
3788 stats.jitter_buffer_ms = 6;
3789 stats.min_playout_delay_ms = 7;
3790 stats.render_delay_ms = 8;
asapersson26dd92b2016-08-30 00:45:45 -07003791 stats.width = 9;
3792 stats.height = 10;
hbos42f6d2f2017-01-20 03:56:50 -08003793 stats.frame_counts.key_frames = 11;
3794 stats.frame_counts.delta_frames = 12;
hbos50cfe1f2017-01-23 07:21:55 -08003795 stats.frames_rendered = 13;
3796 stats.frames_decoded = 14;
sakalcc452e12017-02-09 04:53:45 -08003797 stats.qp_sum = rtc::Optional<uint64_t>(15);
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00003798 stream->SetStats(stats);
3799
3800 cricket::VideoMediaInfo info;
pbos@webrtc.org058b1f12015-03-04 08:54:32 +00003801 ASSERT_TRUE(channel_->GetStats(&info));
Peter Boströmb7d9a972015-12-18 16:01:11 +01003802 EXPECT_EQ(stats.decoder_implementation_name,
3803 info.receivers[0].decoder_implementation_name);
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00003804 EXPECT_EQ(stats.decode_ms, info.receivers[0].decode_ms);
3805 EXPECT_EQ(stats.max_decode_ms, info.receivers[0].max_decode_ms);
3806 EXPECT_EQ(stats.current_delay_ms, info.receivers[0].current_delay_ms);
3807 EXPECT_EQ(stats.target_delay_ms, info.receivers[0].target_delay_ms);
3808 EXPECT_EQ(stats.jitter_buffer_ms, info.receivers[0].jitter_buffer_ms);
3809 EXPECT_EQ(stats.min_playout_delay_ms, info.receivers[0].min_playout_delay_ms);
3810 EXPECT_EQ(stats.render_delay_ms, info.receivers[0].render_delay_ms);
asapersson26dd92b2016-08-30 00:45:45 -07003811 EXPECT_EQ(stats.width, info.receivers[0].frame_width);
3812 EXPECT_EQ(stats.height, info.receivers[0].frame_height);
hbos42f6d2f2017-01-20 03:56:50 -08003813 EXPECT_EQ(stats.frame_counts.key_frames + stats.frame_counts.delta_frames,
3814 info.receivers[0].frames_received);
hbos50cfe1f2017-01-23 07:21:55 -08003815 EXPECT_EQ(stats.frames_rendered, info.receivers[0].frames_rendered);
sakale5ba44e2016-10-26 07:09:24 -07003816 EXPECT_EQ(stats.frames_decoded, info.receivers[0].frames_decoded);
sakalcc452e12017-02-09 04:53:45 -08003817 EXPECT_EQ(stats.qp_sum, info.receivers[0].qp_sum);
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00003818}
3819
eladalonf1841382017-06-12 01:16:46 -07003820TEST_F(WebRtcVideoChannelTest, GetStatsTranslatesReceivePacketStatsCorrectly) {
Peter Boström393347f2015-04-22 14:52:45 +02003821 FakeVideoReceiveStream* stream = AddRecvStream();
3822 webrtc::VideoReceiveStream::Stats stats;
3823 stats.rtp_stats.transmitted.payload_bytes = 2;
3824 stats.rtp_stats.transmitted.header_bytes = 3;
3825 stats.rtp_stats.transmitted.padding_bytes = 4;
3826 stats.rtp_stats.transmitted.packets = 5;
srte186d9c32017-08-04 05:03:53 -07003827 stats.rtcp_stats.packets_lost = 6;
Peter Boström393347f2015-04-22 14:52:45 +02003828 stats.rtcp_stats.fraction_lost = 7;
3829 stream->SetStats(stats);
3830
3831 cricket::VideoMediaInfo info;
3832 ASSERT_TRUE(channel_->GetStats(&info));
3833 EXPECT_EQ(stats.rtp_stats.transmitted.payload_bytes +
3834 stats.rtp_stats.transmitted.header_bytes +
3835 stats.rtp_stats.transmitted.padding_bytes,
3836 info.receivers[0].bytes_rcvd);
3837 EXPECT_EQ(stats.rtp_stats.transmitted.packets,
3838 info.receivers[0].packets_rcvd);
srte186d9c32017-08-04 05:03:53 -07003839 EXPECT_EQ(stats.rtcp_stats.packets_lost, info.receivers[0].packets_lost);
Peter Boström393347f2015-04-22 14:52:45 +02003840 EXPECT_EQ(static_cast<float>(stats.rtcp_stats.fraction_lost) / (1 << 8),
3841 info.receivers[0].fraction_lost);
3842}
3843
eladalonf1841382017-06-12 01:16:46 -07003844TEST_F(WebRtcVideoChannelTest, TranslatesCallStatsCorrectly) {
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003845 AddSendStream();
3846 AddSendStream();
3847 webrtc::Call::Stats stats;
3848 stats.rtt_ms = 123;
3849 fake_call_->SetStats(stats);
3850
3851 cricket::VideoMediaInfo info;
pbos@webrtc.org058b1f12015-03-04 08:54:32 +00003852 ASSERT_TRUE(channel_->GetStats(&info));
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00003853 ASSERT_EQ(2u, info.senders.size());
3854 EXPECT_EQ(stats.rtt_ms, info.senders[0].rtt_ms);
3855 EXPECT_EQ(stats.rtt_ms, info.senders[1].rtt_ms);
3856}
3857
eladalonf1841382017-06-12 01:16:46 -07003858TEST_F(WebRtcVideoChannelTest, TranslatesSenderBitrateStatsCorrectly) {
pbos@webrtc.org77e11bb2015-02-23 16:39:07 +00003859 FakeVideoSendStream* stream = AddSendStream();
3860 webrtc::VideoSendStream::Stats stats;
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003861 stats.target_media_bitrate_bps = 156;
pbos@webrtc.org77e11bb2015-02-23 16:39:07 +00003862 stats.media_bitrate_bps = 123;
3863 stats.substreams[17].total_bitrate_bps = 1;
3864 stats.substreams[17].retransmit_bitrate_bps = 2;
3865 stats.substreams[42].total_bitrate_bps = 3;
3866 stats.substreams[42].retransmit_bitrate_bps = 4;
3867 stream->SetStats(stats);
3868
3869 FakeVideoSendStream* stream2 = AddSendStream();
3870 webrtc::VideoSendStream::Stats stats2;
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003871 stats2.target_media_bitrate_bps = 200;
pbos@webrtc.org77e11bb2015-02-23 16:39:07 +00003872 stats2.media_bitrate_bps = 321;
3873 stats2.substreams[13].total_bitrate_bps = 5;
3874 stats2.substreams[13].retransmit_bitrate_bps = 6;
3875 stats2.substreams[21].total_bitrate_bps = 7;
3876 stats2.substreams[21].retransmit_bitrate_bps = 8;
3877 stream2->SetStats(stats2);
3878
3879 cricket::VideoMediaInfo info;
pbos@webrtc.org058b1f12015-03-04 08:54:32 +00003880 ASSERT_TRUE(channel_->GetStats(&info));
pbos@webrtc.org77e11bb2015-02-23 16:39:07 +00003881 ASSERT_EQ(2u, info.senders.size());
stefanf79ade12017-06-02 06:44:03 -07003882 BandwidthEstimationInfo bwe_info;
3883 channel_->FillBitrateInfo(&bwe_info);
pbos@webrtc.org77e11bb2015-02-23 16:39:07 +00003884 // Assuming stream and stream2 corresponds to senders[0] and [1] respectively
3885 // is OK as std::maps are sorted and AddSendStream() gives increasing SSRCs.
3886 EXPECT_EQ(stats.media_bitrate_bps, info.senders[0].nominal_bitrate);
3887 EXPECT_EQ(stats2.media_bitrate_bps, info.senders[1].nominal_bitrate);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00003888 EXPECT_EQ(stats.target_media_bitrate_bps + stats2.target_media_bitrate_bps,
stefanf79ade12017-06-02 06:44:03 -07003889 bwe_info.target_enc_bitrate);
pbos@webrtc.org77e11bb2015-02-23 16:39:07 +00003890 EXPECT_EQ(stats.media_bitrate_bps + stats2.media_bitrate_bps,
stefanf79ade12017-06-02 06:44:03 -07003891 bwe_info.actual_enc_bitrate);
3892 EXPECT_EQ(1 + 3 + 5 + 7, bwe_info.transmit_bitrate)
pbos@webrtc.org77e11bb2015-02-23 16:39:07 +00003893 << "Bandwidth stats should take all streams into account.";
stefanf79ade12017-06-02 06:44:03 -07003894 EXPECT_EQ(2 + 4 + 6 + 8, bwe_info.retransmit_bitrate)
pbos@webrtc.org77e11bb2015-02-23 16:39:07 +00003895 << "Bandwidth stats should take all streams into account.";
3896}
3897
eladalonf1841382017-06-12 01:16:46 -07003898TEST_F(WebRtcVideoChannelTest, DefaultReceiveStreamReconfiguresToUseRtx) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003899 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
pbos@webrtc.orga2a6fe62015-03-06 15:35:19 +00003900
Peter Boström0c4e06b2015-10-07 12:23:21 +02003901 const std::vector<uint32_t> ssrcs = MAKE_VECTOR(kSsrcs1);
3902 const std::vector<uint32_t> rtx_ssrcs = MAKE_VECTOR(kRtxSsrcs1);
pbos@webrtc.orga2a6fe62015-03-06 15:35:19 +00003903
3904 ASSERT_EQ(0u, fake_call_->GetVideoReceiveStreams().size());
3905 const size_t kDataLength = 12;
3906 uint8_t data[kDataLength];
3907 memset(data, 0, sizeof(data));
3908 rtc::SetBE32(&data[8], ssrcs[0]);
jbaucheec21bd2016-03-20 06:15:43 -07003909 rtc::CopyOnWriteBuffer packet(data, kDataLength);
pbos@webrtc.orga2a6fe62015-03-06 15:35:19 +00003910 rtc::PacketTime packet_time;
3911 channel_->OnPacketReceived(&packet, packet_time);
3912
3913 ASSERT_EQ(1u, fake_call_->GetVideoReceiveStreams().size())
3914 << "No default receive stream created.";
3915 FakeVideoReceiveStream* recv_stream = fake_call_->GetVideoReceiveStreams()[0];
brandtr14742122017-01-27 04:53:07 -08003916 EXPECT_EQ(0u, recv_stream->GetConfig().rtp.rtx_ssrc)
pbos@webrtc.orga2a6fe62015-03-06 15:35:19 +00003917 << "Default receive stream should not have configured RTX";
3918
3919 EXPECT_TRUE(channel_->AddRecvStream(
3920 cricket::CreateSimWithRtxStreamParams("cname", ssrcs, rtx_ssrcs)));
3921 ASSERT_EQ(1u, fake_call_->GetVideoReceiveStreams().size())
brandtr14742122017-01-27 04:53:07 -08003922 << "AddRecvStream should have reconfigured, not added a new receiver.";
pbos@webrtc.orga2a6fe62015-03-06 15:35:19 +00003923 recv_stream = fake_call_->GetVideoReceiveStreams()[0];
nisse26e3abb2017-08-25 04:44:25 -07003924 EXPECT_FALSE(
3925 recv_stream->GetConfig().rtp.rtx_associated_payload_types.empty());
nisseca5706d2017-09-11 02:32:16 -07003926 EXPECT_TRUE(VerifyRtxReceiveAssociations(recv_stream->GetConfig()))
Peter Boströmd8b01092016-05-12 16:44:36 +02003927 << "RTX should be mapped for all decoders/payload types.";
nisseca5706d2017-09-11 02:32:16 -07003928 EXPECT_TRUE(HasRtxReceiveAssociation(recv_stream->GetConfig(),
3929 GetEngineCodec("red").id))
3930 << "RTX should be mapped also for the RED payload type";
brandtr14742122017-01-27 04:53:07 -08003931 EXPECT_EQ(rtx_ssrcs[0], recv_stream->GetConfig().rtp.rtx_ssrc);
pbos@webrtc.orga2a6fe62015-03-06 15:35:19 +00003932}
3933
eladalonf1841382017-06-12 01:16:46 -07003934TEST_F(WebRtcVideoChannelTest, RejectsAddingStreamsWithMissingSsrcsForRtx) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003935 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
Peter Boströmd4362cd2015-03-25 14:17:23 +01003936
Peter Boström0c4e06b2015-10-07 12:23:21 +02003937 const std::vector<uint32_t> ssrcs = MAKE_VECTOR(kSsrcs1);
3938 const std::vector<uint32_t> rtx_ssrcs = MAKE_VECTOR(kRtxSsrcs1);
Peter Boströmd4362cd2015-03-25 14:17:23 +01003939
3940 StreamParams sp =
3941 cricket::CreateSimWithRtxStreamParams("cname", ssrcs, rtx_ssrcs);
3942 sp.ssrcs = ssrcs; // Without RTXs, this is the important part.
3943
3944 EXPECT_FALSE(channel_->AddSendStream(sp));
3945 EXPECT_FALSE(channel_->AddRecvStream(sp));
3946}
3947
eladalonf1841382017-06-12 01:16:46 -07003948TEST_F(WebRtcVideoChannelTest, RejectsAddingStreamsWithOverlappingRtxSsrcs) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003949 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
Peter Boströmd6f4c252015-03-26 16:23:04 +01003950
Peter Boström0c4e06b2015-10-07 12:23:21 +02003951 const std::vector<uint32_t> ssrcs = MAKE_VECTOR(kSsrcs1);
3952 const std::vector<uint32_t> rtx_ssrcs = MAKE_VECTOR(kRtxSsrcs1);
Peter Boströmd6f4c252015-03-26 16:23:04 +01003953
3954 StreamParams sp =
3955 cricket::CreateSimWithRtxStreamParams("cname", ssrcs, rtx_ssrcs);
3956
3957 EXPECT_TRUE(channel_->AddSendStream(sp));
3958 EXPECT_TRUE(channel_->AddRecvStream(sp));
3959
3960 // The RTX SSRC is already used in previous streams, using it should fail.
3961 sp = cricket::StreamParams::CreateLegacy(rtx_ssrcs[0]);
3962 EXPECT_FALSE(channel_->AddSendStream(sp));
3963 EXPECT_FALSE(channel_->AddRecvStream(sp));
3964
3965 // After removing the original stream this should be fine to add (makes sure
3966 // that RTX ssrcs are not forever taken).
3967 EXPECT_TRUE(channel_->RemoveSendStream(ssrcs[0]));
3968 EXPECT_TRUE(channel_->RemoveRecvStream(ssrcs[0]));
3969 EXPECT_TRUE(channel_->AddSendStream(sp));
3970 EXPECT_TRUE(channel_->AddRecvStream(sp));
3971}
3972
eladalonf1841382017-06-12 01:16:46 -07003973TEST_F(WebRtcVideoChannelTest,
Peter Boströmd6f4c252015-03-26 16:23:04 +01003974 RejectsAddingStreamsWithOverlappingSimulcastSsrcs) {
Peter Boström0c4e06b2015-10-07 12:23:21 +02003975 static const uint32_t kFirstStreamSsrcs[] = {1, 2, 3};
3976 static const uint32_t kOverlappingStreamSsrcs[] = {4, 3, 5};
Fredrik Solenbergb071a192015-09-17 16:42:56 +02003977 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
Peter Boströmd6f4c252015-03-26 16:23:04 +01003978
Peter Boströmd6f4c252015-03-26 16:23:04 +01003979 StreamParams sp =
3980 cricket::CreateSimStreamParams("cname", MAKE_VECTOR(kFirstStreamSsrcs));
3981
3982 EXPECT_TRUE(channel_->AddSendStream(sp));
3983 EXPECT_TRUE(channel_->AddRecvStream(sp));
3984
3985 // One of the SSRCs is already used in previous streams, using it should fail.
3986 sp = cricket::CreateSimStreamParams("cname",
3987 MAKE_VECTOR(kOverlappingStreamSsrcs));
3988 EXPECT_FALSE(channel_->AddSendStream(sp));
3989 EXPECT_FALSE(channel_->AddRecvStream(sp));
3990
3991 // After removing the original stream this should be fine to add (makes sure
3992 // that RTX ssrcs are not forever taken).
Peter Boström3548dd22015-05-22 18:48:36 +02003993 EXPECT_TRUE(channel_->RemoveSendStream(kFirstStreamSsrcs[0]));
3994 EXPECT_TRUE(channel_->RemoveRecvStream(kFirstStreamSsrcs[0]));
Peter Boströmd6f4c252015-03-26 16:23:04 +01003995 EXPECT_TRUE(channel_->AddSendStream(sp));
3996 EXPECT_TRUE(channel_->AddRecvStream(sp));
3997}
3998
eladalonf1841382017-06-12 01:16:46 -07003999TEST_F(WebRtcVideoChannelTest, ReportsSsrcGroupsInStats) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02004000 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
Peter Boström259bd202015-05-28 13:39:50 +02004001
4002 static const uint32_t kSenderSsrcs[] = {4, 7, 10};
4003 static const uint32_t kSenderRtxSsrcs[] = {5, 8, 11};
4004
4005 StreamParams sender_sp = cricket::CreateSimWithRtxStreamParams(
4006 "cname", MAKE_VECTOR(kSenderSsrcs), MAKE_VECTOR(kSenderRtxSsrcs));
4007
4008 EXPECT_TRUE(channel_->AddSendStream(sender_sp));
4009
4010 static const uint32_t kReceiverSsrcs[] = {3};
4011 static const uint32_t kReceiverRtxSsrcs[] = {2};
4012
4013 StreamParams receiver_sp = cricket::CreateSimWithRtxStreamParams(
4014 "cname", MAKE_VECTOR(kReceiverSsrcs), MAKE_VECTOR(kReceiverRtxSsrcs));
4015 EXPECT_TRUE(channel_->AddRecvStream(receiver_sp));
4016
4017 cricket::VideoMediaInfo info;
4018 ASSERT_TRUE(channel_->GetStats(&info));
4019
4020 ASSERT_EQ(1u, info.senders.size());
4021 ASSERT_EQ(1u, info.receivers.size());
4022
4023 EXPECT_NE(sender_sp.ssrc_groups, receiver_sp.ssrc_groups);
4024 EXPECT_EQ(sender_sp.ssrc_groups, info.senders[0].ssrc_groups);
4025 EXPECT_EQ(receiver_sp.ssrc_groups, info.receivers[0].ssrc_groups);
4026}
4027
eladalonf1841382017-06-12 01:16:46 -07004028TEST_F(WebRtcVideoChannelTest, MapsReceivedPayloadTypeToCodecName) {
pbosf42376c2015-08-28 07:35:32 -07004029 FakeVideoReceiveStream* stream = AddRecvStream();
4030 webrtc::VideoReceiveStream::Stats stats;
4031 cricket::VideoMediaInfo info;
4032
4033 // Report no codec name before receiving.
4034 stream->SetStats(stats);
4035 ASSERT_TRUE(channel_->GetStats(&info));
4036 EXPECT_STREQ("", info.receivers[0].codec_name.c_str());
4037
4038 // Report VP8 if we're receiving it.
magjed509e4fe2016-11-18 01:34:11 -08004039 stats.current_payload_type = GetEngineCodec("VP8").id;
pbosf42376c2015-08-28 07:35:32 -07004040 stream->SetStats(stats);
4041 ASSERT_TRUE(channel_->GetStats(&info));
4042 EXPECT_STREQ(kVp8CodecName, info.receivers[0].codec_name.c_str());
4043
4044 // Report no codec name for unknown playload types.
4045 stats.current_payload_type = 3;
4046 stream->SetStats(stats);
4047 ASSERT_TRUE(channel_->GetStats(&info));
4048 EXPECT_STREQ("", info.receivers[0].codec_name.c_str());
4049}
4050
eladalonf1841382017-06-12 01:16:46 -07004051void WebRtcVideoChannelTest::TestReceiveUnsignaledSsrcPacket(
noahricd10a68e2015-07-10 11:27:55 -07004052 uint8_t payload_type,
4053 bool expect_created_receive_stream) {
magjed509e4fe2016-11-18 01:34:11 -08004054 // kRedRtxPayloadType must currently be unused.
4055 EXPECT_FALSE(FindCodecById(engine_.codecs(), kRedRtxPayloadType));
4056
noahricd10a68e2015-07-10 11:27:55 -07004057 // Add a RED RTX codec.
4058 VideoCodec red_rtx_codec =
magjed509e4fe2016-11-18 01:34:11 -08004059 VideoCodec::CreateRtxCodec(kRedRtxPayloadType, GetEngineCodec("red").id);
Fredrik Solenbergb071a192015-09-17 16:42:56 +02004060 recv_parameters_.codecs.push_back(red_rtx_codec);
4061 EXPECT_TRUE(channel_->SetRecvParameters(recv_parameters_));
noahricd10a68e2015-07-10 11:27:55 -07004062
4063 ASSERT_EQ(0u, fake_call_->GetVideoReceiveStreams().size());
4064 const size_t kDataLength = 12;
4065 uint8_t data[kDataLength];
4066 memset(data, 0, sizeof(data));
4067
4068 rtc::Set8(data, 1, payload_type);
4069 rtc::SetBE32(&data[8], kIncomingUnsignalledSsrc);
jbaucheec21bd2016-03-20 06:15:43 -07004070 rtc::CopyOnWriteBuffer packet(data, kDataLength);
noahricd10a68e2015-07-10 11:27:55 -07004071 rtc::PacketTime packet_time;
4072 channel_->OnPacketReceived(&packet, packet_time);
4073
4074 if (expect_created_receive_stream) {
4075 EXPECT_EQ(1u, fake_call_->GetVideoReceiveStreams().size())
4076 << "Should have created a receive stream for payload type: "
4077 << payload_type;
4078 } else {
4079 EXPECT_EQ(0u, fake_call_->GetVideoReceiveStreams().size())
4080 << "Shouldn't have created a receive stream for payload type: "
4081 << payload_type;
4082 }
4083}
4084
eladalonf1841382017-06-12 01:16:46 -07004085TEST_F(WebRtcVideoChannelTest, Vp8PacketCreatesUnsignalledStream) {
magjed509e4fe2016-11-18 01:34:11 -08004086 TestReceiveUnsignaledSsrcPacket(GetEngineCodec("VP8").id,
4087 true /* expect_created_receive_stream */);
noahricd10a68e2015-07-10 11:27:55 -07004088}
4089
eladalonf1841382017-06-12 01:16:46 -07004090TEST_F(WebRtcVideoChannelTest, Vp9PacketCreatesUnsignalledStream) {
magjed509e4fe2016-11-18 01:34:11 -08004091 TestReceiveUnsignaledSsrcPacket(GetEngineCodec("VP9").id,
4092 true /* expect_created_receive_stream */);
noahricd10a68e2015-07-10 11:27:55 -07004093}
4094
eladalonf1841382017-06-12 01:16:46 -07004095TEST_F(WebRtcVideoChannelTest, RtxPacketDoesntCreateUnsignalledStream) {
magjed509e4fe2016-11-18 01:34:11 -08004096 const cricket::VideoCodec vp8 = GetEngineCodec("VP8");
4097 const int rtx_vp8_payload_type = default_apt_rtx_types_[vp8.id];
4098 TestReceiveUnsignaledSsrcPacket(rtx_vp8_payload_type,
4099 false /* expect_created_receive_stream */);
noahricd10a68e2015-07-10 11:27:55 -07004100}
4101
eladalonf1841382017-06-12 01:16:46 -07004102TEST_F(WebRtcVideoChannelTest, UlpfecPacketDoesntCreateUnsignalledStream) {
magjed509e4fe2016-11-18 01:34:11 -08004103 TestReceiveUnsignaledSsrcPacket(GetEngineCodec("ulpfec").id,
4104 false /* expect_created_receive_stream */);
noahricd10a68e2015-07-10 11:27:55 -07004105}
4106
eladalonf1841382017-06-12 01:16:46 -07004107TEST_F(WebRtcVideoChannelFlexfecRecvTest,
brandtr468da7c2016-11-22 02:16:47 -08004108 FlexfecPacketDoesntCreateUnsignalledStream) {
4109 TestReceiveUnsignaledSsrcPacket(GetEngineCodec("flexfec-03").id,
4110 false /* expect_created_receive_stream */);
4111}
4112
eladalonf1841382017-06-12 01:16:46 -07004113TEST_F(WebRtcVideoChannelTest, RedRtxPacketDoesntCreateUnsignalledStream) {
magjed509e4fe2016-11-18 01:34:11 -08004114 TestReceiveUnsignaledSsrcPacket(kRedRtxPayloadType,
4115 false /* expect_created_receive_stream */);
noahricd10a68e2015-07-10 11:27:55 -07004116}
4117
mzanaty8a855d62017-02-17 15:46:43 -08004118// Test that receiving any unsignalled SSRC works even if it changes.
4119// The first unsignalled SSRC received will create a default receive stream.
4120// Any different unsignalled SSRC received will replace the default.
eladalonf1841382017-06-12 01:16:46 -07004121TEST_F(WebRtcVideoChannelTest, ReceiveDifferentUnsignaledSsrc) {
mzanaty8a855d62017-02-17 15:46:43 -08004122 // Allow receiving VP8, VP9, H264 (if enabled).
4123 cricket::VideoRecvParameters parameters;
4124 parameters.codecs.push_back(GetEngineCodec("VP8"));
4125 parameters.codecs.push_back(GetEngineCodec("VP9"));
4126
4127#if defined(WEBRTC_USE_H264)
4128 cricket::VideoCodec H264codec(126, "H264");
4129 parameters.codecs.push_back(H264codec);
4130#endif
4131
4132 EXPECT_TRUE(channel_->SetRecvParameters(parameters));
4133 // No receive streams yet.
4134 ASSERT_EQ(0u, fake_call_->GetVideoReceiveStreams().size());
4135 cricket::FakeVideoRenderer renderer;
4136 EXPECT_TRUE(channel_->SetSink(kDefaultRecvSsrc, &renderer));
4137
4138 // Receive VP8 packet on first SSRC.
4139 uint8_t data[kMinRtpPacketLen];
4140 cricket::RtpHeader rtpHeader;
4141 rtpHeader.payload_type = GetEngineCodec("VP8").id;
4142 rtpHeader.seq_num = rtpHeader.timestamp = 0;
4143 rtpHeader.ssrc = kIncomingUnsignalledSsrc+1;
4144 cricket::SetRtpHeader(data, sizeof(data), rtpHeader);
4145 rtc::CopyOnWriteBuffer packet(data, sizeof(data));
4146 rtc::PacketTime packet_time;
4147 channel_->OnPacketReceived(&packet, packet_time);
4148 // VP8 packet should create default receive stream.
4149 ASSERT_EQ(1u, fake_call_->GetVideoReceiveStreams().size());
4150 FakeVideoReceiveStream* recv_stream =
4151 fake_call_->GetVideoReceiveStreams()[0];
4152 EXPECT_EQ(rtpHeader.ssrc, recv_stream->GetConfig().rtp.remote_ssrc);
4153 // Verify that the receive stream sinks to a renderer.
4154 webrtc::VideoFrame video_frame(CreateBlackFrameBuffer(4, 4), 100, 0,
4155 webrtc::kVideoRotation_0);
4156 recv_stream->InjectFrame(video_frame);
4157 EXPECT_EQ(1, renderer.num_rendered_frames());
4158
4159 // Receive VP9 packet on second SSRC.
4160 rtpHeader.payload_type = GetEngineCodec("VP9").id;
4161 rtpHeader.ssrc = kIncomingUnsignalledSsrc+2;
4162 cricket::SetRtpHeader(data, sizeof(data), rtpHeader);
4163 rtc::CopyOnWriteBuffer packet2(data, sizeof(data));
4164 channel_->OnPacketReceived(&packet2, packet_time);
4165 // VP9 packet should replace the default receive SSRC.
4166 ASSERT_EQ(1u, fake_call_->GetVideoReceiveStreams().size());
4167 recv_stream = fake_call_->GetVideoReceiveStreams()[0];
4168 EXPECT_EQ(rtpHeader.ssrc, recv_stream->GetConfig().rtp.remote_ssrc);
4169 // Verify that the receive stream sinks to a renderer.
4170 webrtc::VideoFrame video_frame2(CreateBlackFrameBuffer(4, 4), 200, 0,
ilnik00d802b2017-04-11 10:34:31 -07004171 webrtc::kVideoRotation_0);
mzanaty8a855d62017-02-17 15:46:43 -08004172 recv_stream->InjectFrame(video_frame2);
4173 EXPECT_EQ(2, renderer.num_rendered_frames());
4174
4175#if defined(WEBRTC_USE_H264)
4176 // Receive H264 packet on third SSRC.
4177 rtpHeader.payload_type = 126;
4178 rtpHeader.ssrc = kIncomingUnsignalledSsrc+3;
4179 cricket::SetRtpHeader(data, sizeof(data), rtpHeader);
4180 rtc::CopyOnWriteBuffer packet3(data, sizeof(data));
4181 channel_->OnPacketReceived(&packet3, packet_time);
4182 // H264 packet should replace the default receive SSRC.
4183 ASSERT_EQ(1u, fake_call_->GetVideoReceiveStreams().size());
4184 recv_stream = fake_call_->GetVideoReceiveStreams()[0];
4185 EXPECT_EQ(rtpHeader.ssrc, recv_stream->GetConfig().rtp.remote_ssrc);
4186 // Verify that the receive stream sinks to a renderer.
4187 webrtc::VideoFrame video_frame3(CreateBlackFrameBuffer(4, 4), 300, 0,
ilnik00d802b2017-04-11 10:34:31 -07004188 webrtc::kVideoRotation_0);
mzanaty8a855d62017-02-17 15:46:43 -08004189 recv_stream->InjectFrame(video_frame3);
4190 EXPECT_EQ(3, renderer.num_rendered_frames());
4191#endif
4192}
4193
brandtr0dc57ea2017-05-29 23:33:31 -07004194// This test verifies that when a new default stream is created for a new
4195// unsignaled SSRC, the new stream does not overwrite any old stream that had
4196// been the default receive stream before being properly signaled.
eladalonf1841382017-06-12 01:16:46 -07004197TEST_F(WebRtcVideoChannelTest,
brandtr0dc57ea2017-05-29 23:33:31 -07004198 NewUnsignaledStreamDoesNotDestroyPreviouslyUnsignaledStream) {
4199 cricket::VideoRecvParameters parameters;
4200 parameters.codecs.push_back(GetEngineCodec("VP8"));
4201 ASSERT_TRUE(channel_->SetRecvParameters(parameters));
4202
4203 // No streams signaled and no packets received, so we should not have any
4204 // stream objects created yet.
4205 EXPECT_EQ(0u, fake_call_->GetVideoReceiveStreams().size());
4206
4207 // Receive packet on an unsignaled SSRC.
4208 uint8_t data[kMinRtpPacketLen];
4209 cricket::RtpHeader rtp_header;
4210 rtp_header.payload_type = GetEngineCodec("VP8").id;
4211 rtp_header.seq_num = rtp_header.timestamp = 0;
4212 rtp_header.ssrc = kSsrcs3[0];
4213 cricket::SetRtpHeader(data, sizeof(data), rtp_header);
4214 rtc::CopyOnWriteBuffer packet(data, sizeof(data));
4215 rtc::PacketTime packet_time;
4216 channel_->OnPacketReceived(&packet, packet_time);
4217 // Default receive stream should be created.
4218 ASSERT_EQ(1u, fake_call_->GetVideoReceiveStreams().size());
4219 FakeVideoReceiveStream* recv_stream0 =
4220 fake_call_->GetVideoReceiveStreams()[0];
4221 EXPECT_EQ(kSsrcs3[0], recv_stream0->GetConfig().rtp.remote_ssrc);
4222
4223 // Signal the SSRC.
4224 EXPECT_TRUE(
4225 channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(kSsrcs3[0])));
4226 ASSERT_EQ(1u, fake_call_->GetVideoReceiveStreams().size());
4227 recv_stream0 = fake_call_->GetVideoReceiveStreams()[0];
4228 EXPECT_EQ(kSsrcs3[0], recv_stream0->GetConfig().rtp.remote_ssrc);
4229
4230 // Receive packet on a different unsignaled SSRC.
4231 rtp_header.ssrc = kSsrcs3[1];
4232 cricket::SetRtpHeader(data, sizeof(data), rtp_header);
4233 packet.SetData(data, sizeof(data));
4234 channel_->OnPacketReceived(&packet, packet_time);
4235 // New default receive stream should be created, but old stream should remain.
4236 ASSERT_EQ(2u, fake_call_->GetVideoReceiveStreams().size());
4237 EXPECT_EQ(recv_stream0, fake_call_->GetVideoReceiveStreams()[0]);
4238 FakeVideoReceiveStream* recv_stream1 =
4239 fake_call_->GetVideoReceiveStreams()[1];
4240 EXPECT_EQ(kSsrcs3[1], recv_stream1->GetConfig().rtp.remote_ssrc);
4241}
4242
eladalonf1841382017-06-12 01:16:46 -07004243TEST_F(WebRtcVideoChannelTest, CanSentMaxBitrateForExistingStream) {
skvladdc1c62c2016-03-16 19:07:43 -07004244 AddSendStream();
4245
4246 cricket::FakeVideoCapturer capturer;
deadbeef5a4a75a2016-06-02 16:23:38 -07004247 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, &capturer));
skvladdc1c62c2016-03-16 19:07:43 -07004248 cricket::VideoFormat capture_format_hd =
4249 capturer.GetSupportedFormats()->front();
4250 EXPECT_EQ(1280, capture_format_hd.width);
4251 EXPECT_EQ(720, capture_format_hd.height);
4252 EXPECT_EQ(cricket::CS_RUNNING, capturer.Start(capture_format_hd));
4253 EXPECT_TRUE(channel_->SetSend(true));
perkjfa10b552016-10-02 23:45:26 -07004254 capturer.CaptureFrame();
skvladdc1c62c2016-03-16 19:07:43 -07004255
perkjfa10b552016-10-02 23:45:26 -07004256 int default_encoder_bitrate = GetMaxEncoderBitrate();
brandtr468da7c2016-11-22 02:16:47 -08004257 EXPECT_GT(default_encoder_bitrate, 1000);
skvladdc1c62c2016-03-16 19:07:43 -07004258
4259 // TODO(skvlad): Resolve the inconsistency between the interpretation
4260 // of the global bitrate limit for audio and video:
4261 // - Audio: max_bandwidth_bps = 0 - fail the operation,
4262 // max_bandwidth_bps = -1 - remove the bandwidth limit
4263 // - Video: max_bandwidth_bps = 0 - remove the bandwidth limit,
pbos5c7760a2017-03-10 11:23:12 -08004264 // max_bandwidth_bps = -1 - remove the bandwidth limit
skvladdc1c62c2016-03-16 19:07:43 -07004265
perkjfa10b552016-10-02 23:45:26 -07004266 SetAndExpectMaxBitrate(1000, 0, 1000);
4267 SetAndExpectMaxBitrate(1000, 800, 800);
4268 SetAndExpectMaxBitrate(600, 800, 600);
4269 SetAndExpectMaxBitrate(0, 800, 800);
4270 SetAndExpectMaxBitrate(0, 0, default_encoder_bitrate);
skvladdc1c62c2016-03-16 19:07:43 -07004271
deadbeef5a4a75a2016-06-02 16:23:38 -07004272 EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, true, nullptr, nullptr));
skvladdc1c62c2016-03-16 19:07:43 -07004273}
4274
eladalonf1841382017-06-12 01:16:46 -07004275TEST_F(WebRtcVideoChannelTest, CannotSetMaxBitrateForNonexistentStream) {
skvladdc1c62c2016-03-16 19:07:43 -07004276 webrtc::RtpParameters nonexistent_parameters =
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07004277 channel_->GetRtpSendParameters(last_ssrc_);
skvladdc1c62c2016-03-16 19:07:43 -07004278 EXPECT_EQ(0, nonexistent_parameters.encodings.size());
4279
4280 nonexistent_parameters.encodings.push_back(webrtc::RtpEncodingParameters());
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07004281 EXPECT_FALSE(
4282 channel_->SetRtpSendParameters(last_ssrc_, nonexistent_parameters));
skvladdc1c62c2016-03-16 19:07:43 -07004283}
4284
eladalonf1841382017-06-12 01:16:46 -07004285TEST_F(WebRtcVideoChannelTest,
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07004286 CannotSetRtpSendParametersWithIncorrectNumberOfEncodings) {
skvladdc1c62c2016-03-16 19:07:43 -07004287 // This test verifies that setting RtpParameters succeeds only if
4288 // the structure contains exactly one encoding.
deadbeefdbe2b872016-03-22 15:42:00 -07004289 // TODO(skvlad): Update this test when we start supporting setting parameters
skvladdc1c62c2016-03-16 19:07:43 -07004290 // for each encoding individually.
4291
4292 AddSendStream();
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07004293 webrtc::RtpParameters parameters = channel_->GetRtpSendParameters(last_ssrc_);
skvladdc1c62c2016-03-16 19:07:43 -07004294 // Two or more encodings should result in failure.
4295 parameters.encodings.push_back(webrtc::RtpEncodingParameters());
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07004296 EXPECT_FALSE(channel_->SetRtpSendParameters(last_ssrc_, parameters));
deadbeeffb2aced2017-01-06 23:05:37 -08004297 // Zero encodings should also fail.
4298 parameters.encodings.clear();
4299 EXPECT_FALSE(channel_->SetRtpSendParameters(last_ssrc_, parameters));
4300}
4301
4302// Changing the SSRC through RtpParameters is not allowed.
eladalonf1841382017-06-12 01:16:46 -07004303TEST_F(WebRtcVideoChannelTest, CannotSetSsrcInRtpSendParameters) {
deadbeeffb2aced2017-01-06 23:05:37 -08004304 AddSendStream();
4305 webrtc::RtpParameters parameters = channel_->GetRtpSendParameters(last_ssrc_);
4306 parameters.encodings[0].ssrc = rtc::Optional<uint32_t>(0xdeadbeef);
4307 EXPECT_FALSE(channel_->SetRtpSendParameters(last_ssrc_, parameters));
skvladdc1c62c2016-03-16 19:07:43 -07004308}
4309
Taylor Brandstetter14b9d792016-09-07 17:16:54 -07004310// Test that a stream will not be sending if its encoding is made inactive
4311// through SetRtpSendParameters.
deadbeefdbe2b872016-03-22 15:42:00 -07004312// TODO(deadbeef): Update this test when we start supporting setting parameters
4313// for each encoding individually.
eladalonf1841382017-06-12 01:16:46 -07004314TEST_F(WebRtcVideoChannelTest, SetRtpSendParametersEncodingsActive) {
deadbeefdbe2b872016-03-22 15:42:00 -07004315 FakeVideoSendStream* stream = AddSendStream();
4316 EXPECT_TRUE(channel_->SetSend(true));
4317 EXPECT_TRUE(stream->IsSending());
4318
4319 // Get current parameters and change "active" to false.
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07004320 webrtc::RtpParameters parameters = channel_->GetRtpSendParameters(last_ssrc_);
deadbeefdbe2b872016-03-22 15:42:00 -07004321 ASSERT_EQ(1u, parameters.encodings.size());
4322 ASSERT_TRUE(parameters.encodings[0].active);
4323 parameters.encodings[0].active = false;
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07004324 EXPECT_TRUE(channel_->SetRtpSendParameters(last_ssrc_, parameters));
deadbeefdbe2b872016-03-22 15:42:00 -07004325 EXPECT_FALSE(stream->IsSending());
4326
4327 // Now change it back to active and verify we resume sending.
4328 parameters.encodings[0].active = true;
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07004329 EXPECT_TRUE(channel_->SetRtpSendParameters(last_ssrc_, parameters));
deadbeefdbe2b872016-03-22 15:42:00 -07004330 EXPECT_TRUE(stream->IsSending());
4331}
4332
Taylor Brandstetter14b9d792016-09-07 17:16:54 -07004333// Test that if a stream is reconfigured (due to a codec change or other
4334// change) while its encoding is still inactive, it doesn't start sending.
eladalonf1841382017-06-12 01:16:46 -07004335TEST_F(WebRtcVideoChannelTest,
Taylor Brandstetter14b9d792016-09-07 17:16:54 -07004336 InactiveStreamDoesntStartSendingWhenReconfigured) {
4337 // Set an initial codec list, which will be modified later.
4338 cricket::VideoSendParameters parameters1;
magjed509e4fe2016-11-18 01:34:11 -08004339 parameters1.codecs.push_back(GetEngineCodec("VP8"));
4340 parameters1.codecs.push_back(GetEngineCodec("VP9"));
Taylor Brandstetter14b9d792016-09-07 17:16:54 -07004341 EXPECT_TRUE(channel_->SetSendParameters(parameters1));
4342
4343 FakeVideoSendStream* stream = AddSendStream();
4344 EXPECT_TRUE(channel_->SetSend(true));
4345 EXPECT_TRUE(stream->IsSending());
4346
4347 // Get current parameters and change "active" to false.
4348 webrtc::RtpParameters parameters = channel_->GetRtpSendParameters(last_ssrc_);
4349 ASSERT_EQ(1u, parameters.encodings.size());
4350 ASSERT_TRUE(parameters.encodings[0].active);
4351 parameters.encodings[0].active = false;
4352 EXPECT_EQ(1u, GetFakeSendStreams().size());
4353 EXPECT_EQ(1, fake_call_->GetNumCreatedSendStreams());
4354 EXPECT_TRUE(channel_->SetRtpSendParameters(last_ssrc_, parameters));
4355 EXPECT_FALSE(stream->IsSending());
4356
4357 // Reorder the codec list, causing the stream to be reconfigured.
4358 cricket::VideoSendParameters parameters2;
magjed509e4fe2016-11-18 01:34:11 -08004359 parameters2.codecs.push_back(GetEngineCodec("VP9"));
4360 parameters2.codecs.push_back(GetEngineCodec("VP8"));
Taylor Brandstetter14b9d792016-09-07 17:16:54 -07004361 EXPECT_TRUE(channel_->SetSendParameters(parameters2));
4362 auto new_streams = GetFakeSendStreams();
4363 // Assert that a new underlying stream was created due to the codec change.
4364 // Otherwise, this test isn't testing what it set out to test.
4365 EXPECT_EQ(1u, GetFakeSendStreams().size());
4366 EXPECT_EQ(2, fake_call_->GetNumCreatedSendStreams());
4367
4368 // Verify that we still are not sending anything, due to the inactive
4369 // encoding.
4370 EXPECT_FALSE(new_streams[0]->IsSending());
4371}
4372
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07004373// Test that GetRtpSendParameters returns the currently configured codecs.
eladalonf1841382017-06-12 01:16:46 -07004374TEST_F(WebRtcVideoChannelTest, GetRtpSendParametersCodecs) {
Taylor Brandstetter0cd086b2016-04-20 16:23:10 -07004375 AddSendStream();
4376 cricket::VideoSendParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08004377 parameters.codecs.push_back(GetEngineCodec("VP8"));
4378 parameters.codecs.push_back(GetEngineCodec("VP9"));
Taylor Brandstetter0cd086b2016-04-20 16:23:10 -07004379 EXPECT_TRUE(channel_->SetSendParameters(parameters));
4380
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07004381 webrtc::RtpParameters rtp_parameters =
4382 channel_->GetRtpSendParameters(last_ssrc_);
Taylor Brandstetter0cd086b2016-04-20 16:23:10 -07004383 ASSERT_EQ(2u, rtp_parameters.codecs.size());
magjed509e4fe2016-11-18 01:34:11 -08004384 EXPECT_EQ(GetEngineCodec("VP8").ToCodecParameters(),
4385 rtp_parameters.codecs[0]);
4386 EXPECT_EQ(GetEngineCodec("VP9").ToCodecParameters(),
4387 rtp_parameters.codecs[1]);
Taylor Brandstetter0cd086b2016-04-20 16:23:10 -07004388}
4389
deadbeeffb2aced2017-01-06 23:05:37 -08004390// Test that RtpParameters for send stream has one encoding and it has
4391// the correct SSRC.
eladalonf1841382017-06-12 01:16:46 -07004392TEST_F(WebRtcVideoChannelTest, GetRtpSendParametersSsrc) {
deadbeeffb2aced2017-01-06 23:05:37 -08004393 AddSendStream();
4394
4395 webrtc::RtpParameters rtp_parameters =
4396 channel_->GetRtpSendParameters(last_ssrc_);
4397 ASSERT_EQ(1u, rtp_parameters.encodings.size());
4398 EXPECT_EQ(rtc::Optional<uint32_t>(last_ssrc_),
4399 rtp_parameters.encodings[0].ssrc);
4400}
4401
Taylor Brandstetter0cd086b2016-04-20 16:23:10 -07004402// Test that if we set/get parameters multiple times, we get the same results.
eladalonf1841382017-06-12 01:16:46 -07004403TEST_F(WebRtcVideoChannelTest, SetAndGetRtpSendParameters) {
Taylor Brandstetter0cd086b2016-04-20 16:23:10 -07004404 AddSendStream();
4405 cricket::VideoSendParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08004406 parameters.codecs.push_back(GetEngineCodec("VP8"));
4407 parameters.codecs.push_back(GetEngineCodec("VP9"));
Taylor Brandstetter0cd086b2016-04-20 16:23:10 -07004408 EXPECT_TRUE(channel_->SetSendParameters(parameters));
4409
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07004410 webrtc::RtpParameters initial_params =
4411 channel_->GetRtpSendParameters(last_ssrc_);
Taylor Brandstetter0cd086b2016-04-20 16:23:10 -07004412
4413 // We should be able to set the params we just got.
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07004414 EXPECT_TRUE(channel_->SetRtpSendParameters(last_ssrc_, initial_params));
Taylor Brandstetter0cd086b2016-04-20 16:23:10 -07004415
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07004416 // ... And this shouldn't change the params returned by GetRtpSendParameters.
4417 EXPECT_EQ(initial_params, channel_->GetRtpSendParameters(last_ssrc_));
4418}
4419
4420// Test that GetRtpReceiveParameters returns the currently configured codecs.
eladalonf1841382017-06-12 01:16:46 -07004421TEST_F(WebRtcVideoChannelTest, GetRtpReceiveParametersCodecs) {
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07004422 AddRecvStream();
4423 cricket::VideoRecvParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08004424 parameters.codecs.push_back(GetEngineCodec("VP8"));
4425 parameters.codecs.push_back(GetEngineCodec("VP9"));
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07004426 EXPECT_TRUE(channel_->SetRecvParameters(parameters));
4427
4428 webrtc::RtpParameters rtp_parameters =
4429 channel_->GetRtpReceiveParameters(last_ssrc_);
4430 ASSERT_EQ(2u, rtp_parameters.codecs.size());
magjed509e4fe2016-11-18 01:34:11 -08004431 EXPECT_EQ(GetEngineCodec("VP8").ToCodecParameters(),
4432 rtp_parameters.codecs[0]);
4433 EXPECT_EQ(GetEngineCodec("VP9").ToCodecParameters(),
4434 rtp_parameters.codecs[1]);
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07004435}
4436
johan073ece42016-08-26 02:59:47 -07004437#if defined(WEBRTC_USE_H264)
eladalonf1841382017-06-12 01:16:46 -07004438TEST_F(WebRtcVideoChannelTest, GetRtpReceiveFmtpSprop) {
johan073ece42016-08-26 02:59:47 -07004439#else
eladalonf1841382017-06-12 01:16:46 -07004440TEST_F(WebRtcVideoChannelTest, DISABLED_GetRtpReceiveFmtpSprop) {
johan073ece42016-08-26 02:59:47 -07004441#endif
johan3859c892016-08-05 09:19:25 -07004442 cricket::VideoRecvParameters parameters;
perkj26752742016-10-24 01:21:16 -07004443 cricket::VideoCodec kH264sprop1(101, "H264");
magjed5dfac562016-11-25 03:56:37 -08004444 kH264sprop1.SetParam(kH264FmtpSpropParameterSets, "uvw");
johan3859c892016-08-05 09:19:25 -07004445 parameters.codecs.push_back(kH264sprop1);
perkj26752742016-10-24 01:21:16 -07004446 cricket::VideoCodec kH264sprop2(102, "H264");
magjed5dfac562016-11-25 03:56:37 -08004447 kH264sprop2.SetParam(kH264FmtpSpropParameterSets, "xyz");
johan3859c892016-08-05 09:19:25 -07004448 parameters.codecs.push_back(kH264sprop2);
4449 EXPECT_TRUE(channel_->SetRecvParameters(parameters));
4450
4451 FakeVideoReceiveStream* recv_stream = AddRecvStream();
4452 const webrtc::VideoReceiveStream::Config& cfg = recv_stream->GetConfig();
4453 webrtc::RtpParameters rtp_parameters =
4454 channel_->GetRtpReceiveParameters(last_ssrc_);
4455 ASSERT_EQ(2u, rtp_parameters.codecs.size());
4456 EXPECT_EQ(kH264sprop1.ToCodecParameters(), rtp_parameters.codecs[0]);
4457 ASSERT_EQ(2u, cfg.decoders.size());
4458 EXPECT_EQ(101, cfg.decoders[0].payload_type);
4459 EXPECT_EQ("H264", cfg.decoders[0].payload_name);
magjed5dfac562016-11-25 03:56:37 -08004460 const auto it0 =
4461 cfg.decoders[0].codec_params.find(kH264FmtpSpropParameterSets);
4462 ASSERT_TRUE(it0 != cfg.decoders[0].codec_params.end());
4463 EXPECT_EQ("uvw", it0->second);
johan3859c892016-08-05 09:19:25 -07004464
4465 EXPECT_EQ(102, cfg.decoders[1].payload_type);
4466 EXPECT_EQ("H264", cfg.decoders[1].payload_name);
magjed5dfac562016-11-25 03:56:37 -08004467 const auto it1 =
4468 cfg.decoders[1].codec_params.find(kH264FmtpSpropParameterSets);
4469 ASSERT_TRUE(it1 != cfg.decoders[1].codec_params.end());
4470 EXPECT_EQ("xyz", it1->second);
johan3859c892016-08-05 09:19:25 -07004471}
4472
sakal1fd95952016-06-22 00:46:15 -07004473// Test that RtpParameters for receive stream has one encoding and it has
4474// the correct SSRC.
eladalonf1841382017-06-12 01:16:46 -07004475TEST_F(WebRtcVideoChannelTest, GetRtpReceiveParametersSsrc) {
sakal1fd95952016-06-22 00:46:15 -07004476 AddRecvStream();
4477
4478 webrtc::RtpParameters rtp_parameters =
4479 channel_->GetRtpReceiveParameters(last_ssrc_);
4480 ASSERT_EQ(1u, rtp_parameters.encodings.size());
4481 EXPECT_EQ(rtc::Optional<uint32_t>(last_ssrc_),
4482 rtp_parameters.encodings[0].ssrc);
4483}
4484
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07004485// Test that if we set/get parameters multiple times, we get the same results.
eladalonf1841382017-06-12 01:16:46 -07004486TEST_F(WebRtcVideoChannelTest, SetAndGetRtpReceiveParameters) {
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07004487 AddRecvStream();
4488 cricket::VideoRecvParameters parameters;
magjed509e4fe2016-11-18 01:34:11 -08004489 parameters.codecs.push_back(GetEngineCodec("VP8"));
4490 parameters.codecs.push_back(GetEngineCodec("VP9"));
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07004491 EXPECT_TRUE(channel_->SetRecvParameters(parameters));
4492
4493 webrtc::RtpParameters initial_params =
4494 channel_->GetRtpReceiveParameters(last_ssrc_);
4495
4496 // We should be able to set the params we just got.
4497 EXPECT_TRUE(channel_->SetRtpReceiveParameters(last_ssrc_, initial_params));
4498
4499 // ... And this shouldn't change the params returned by
4500 // GetRtpReceiveParameters.
4501 EXPECT_EQ(initial_params, channel_->GetRtpReceiveParameters(last_ssrc_));
Taylor Brandstetter0cd086b2016-04-20 16:23:10 -07004502}
4503
deadbeef3bc15102017-04-20 19:25:07 -07004504// Test that GetRtpReceiveParameters returns parameters correctly when SSRCs
4505// aren't signaled. It should always return an empty "RtpEncodingParameters",
4506// even after a packet is received and the unsignaled SSRC is known.
eladalonf1841382017-06-12 01:16:46 -07004507TEST_F(WebRtcVideoChannelTest, GetRtpReceiveParametersWithUnsignaledSsrc) {
deadbeef3bc15102017-04-20 19:25:07 -07004508 // Call necessary methods to configure receiving a default stream as
4509 // soon as it arrives.
4510 cricket::VideoRecvParameters parameters;
4511 parameters.codecs.push_back(GetEngineCodec("VP8"));
4512 parameters.codecs.push_back(GetEngineCodec("VP9"));
4513 EXPECT_TRUE(channel_->SetRecvParameters(parameters));
4514
4515 // Call GetRtpReceiveParameters before configured to receive an unsignaled
4516 // stream. Should return nothing.
4517 EXPECT_EQ(webrtc::RtpParameters(), channel_->GetRtpReceiveParameters(0));
4518
4519 // Set a sink for an unsignaled stream.
4520 cricket::FakeVideoRenderer renderer;
4521 // Value of "0" means "unsignaled stream".
4522 EXPECT_TRUE(channel_->SetSink(0, &renderer));
4523
4524 // Call GetRtpReceiveParameters before the SSRC is known. Value of "0"
4525 // in this method means "unsignaled stream".
4526 webrtc::RtpParameters rtp_parameters = channel_->GetRtpReceiveParameters(0);
4527 ASSERT_EQ(1u, rtp_parameters.encodings.size());
4528 EXPECT_FALSE(rtp_parameters.encodings[0].ssrc);
4529
4530 // Receive VP8 packet.
4531 uint8_t data[kMinRtpPacketLen];
4532 cricket::RtpHeader rtpHeader;
4533 rtpHeader.payload_type = GetEngineCodec("VP8").id;
4534 rtpHeader.seq_num = rtpHeader.timestamp = 0;
4535 rtpHeader.ssrc = kIncomingUnsignalledSsrc;
4536 cricket::SetRtpHeader(data, sizeof(data), rtpHeader);
4537 rtc::CopyOnWriteBuffer packet(data, sizeof(data));
4538 rtc::PacketTime packet_time;
4539 channel_->OnPacketReceived(&packet, packet_time);
4540
4541 // The |ssrc| member should still be unset.
4542 rtp_parameters = channel_->GetRtpReceiveParameters(0);
4543 ASSERT_EQ(1u, rtp_parameters.encodings.size());
4544 EXPECT_FALSE(rtp_parameters.encodings[0].ssrc);
4545}
4546
eladalonf1841382017-06-12 01:16:46 -07004547void WebRtcVideoChannelTest::TestReceiverLocalSsrcConfiguration(
Peter Boström3548dd22015-05-22 18:48:36 +02004548 bool receiver_first) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02004549 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
Peter Boström3548dd22015-05-22 18:48:36 +02004550
4551 const uint32_t kSenderSsrc = 0xC0FFEE;
Peter Boströmdfa28152015-10-21 17:21:10 +02004552 const uint32_t kSecondSenderSsrc = 0xBADCAFE;
Peter Boström3548dd22015-05-22 18:48:36 +02004553 const uint32_t kReceiverSsrc = 0x4711;
Peter Boströmdfa28152015-10-21 17:21:10 +02004554 const uint32_t kExpectedDefaultReceiverSsrc = 1;
Peter Boström3548dd22015-05-22 18:48:36 +02004555
4556 if (receiver_first) {
4557 AddRecvStream(StreamParams::CreateLegacy(kReceiverSsrc));
4558 std::vector<FakeVideoReceiveStream*> receive_streams =
4559 fake_call_->GetVideoReceiveStreams();
4560 ASSERT_EQ(1u, receive_streams.size());
Peter Boströmdfa28152015-10-21 17:21:10 +02004561 // Default local SSRC when we have no sender.
4562 EXPECT_EQ(kExpectedDefaultReceiverSsrc,
4563 receive_streams[0]->GetConfig().rtp.local_ssrc);
Peter Boström3548dd22015-05-22 18:48:36 +02004564 }
4565 AddSendStream(StreamParams::CreateLegacy(kSenderSsrc));
4566 if (!receiver_first)
4567 AddRecvStream(StreamParams::CreateLegacy(kReceiverSsrc));
4568 std::vector<FakeVideoReceiveStream*> receive_streams =
4569 fake_call_->GetVideoReceiveStreams();
4570 ASSERT_EQ(1u, receive_streams.size());
4571 EXPECT_EQ(kSenderSsrc, receive_streams[0]->GetConfig().rtp.local_ssrc);
Peter Boströmdfa28152015-10-21 17:21:10 +02004572
4573 // Removing first sender should fall back to another (in this case the second)
4574 // local send stream's SSRC.
4575 AddSendStream(StreamParams::CreateLegacy(kSecondSenderSsrc));
4576 ASSERT_TRUE(channel_->RemoveSendStream(kSenderSsrc));
4577 receive_streams =
4578 fake_call_->GetVideoReceiveStreams();
4579 ASSERT_EQ(1u, receive_streams.size());
4580 EXPECT_EQ(kSecondSenderSsrc, receive_streams[0]->GetConfig().rtp.local_ssrc);
4581
4582 // Removing the last sender should fall back to default local SSRC.
4583 ASSERT_TRUE(channel_->RemoveSendStream(kSecondSenderSsrc));
4584 receive_streams =
4585 fake_call_->GetVideoReceiveStreams();
4586 ASSERT_EQ(1u, receive_streams.size());
4587 EXPECT_EQ(kExpectedDefaultReceiverSsrc,
4588 receive_streams[0]->GetConfig().rtp.local_ssrc);
Peter Boström3548dd22015-05-22 18:48:36 +02004589}
4590
eladalonf1841382017-06-12 01:16:46 -07004591TEST_F(WebRtcVideoChannelTest, ConfiguresLocalSsrc) {
Peter Boström3548dd22015-05-22 18:48:36 +02004592 TestReceiverLocalSsrcConfiguration(false);
4593}
4594
eladalonf1841382017-06-12 01:16:46 -07004595TEST_F(WebRtcVideoChannelTest, ConfiguresLocalSsrcOnExistingReceivers) {
Peter Boström3548dd22015-05-22 18:48:36 +02004596 TestReceiverLocalSsrcConfiguration(true);
4597}
4598
eladalonf1841382017-06-12 01:16:46 -07004599class WebRtcVideoChannelSimulcastTest : public testing::Test {
buildbot@webrtc.orga8530772014-12-10 09:01:18 +00004600 public:
eladalonf1841382017-06-12 01:16:46 -07004601 WebRtcVideoChannelSimulcastTest()
magjed2475ae22017-09-12 04:42:15 -07004602 : fake_call_(webrtc::Call::Config(&event_log_)),
Magnus Jedvert02e7a192017-09-23 17:21:32 +02004603 encoder_factory_(new cricket::FakeWebRtcVideoEncoderFactory),
4604 decoder_factory_(new cricket::FakeWebRtcVideoDecoderFactory),
4605 engine_(std::unique_ptr<cricket::WebRtcVideoEncoderFactory>(
4606 encoder_factory_),
4607 std::unique_ptr<cricket::WebRtcVideoDecoderFactory>(
4608 decoder_factory_)),
magjed2475ae22017-09-12 04:42:15 -07004609 last_ssrc_(0) {}
buildbot@webrtc.orga8530772014-12-10 09:01:18 +00004610
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00004611 void SetUp() override {
nisse51542be2016-02-12 02:27:06 -08004612 channel_.reset(
kthelgason2bc68642017-02-07 07:02:22 -08004613 engine_.CreateChannel(&fake_call_, GetMediaConfig(), VideoOptions()));
Sergey Ulanove2b15012016-11-22 16:08:30 -08004614 channel_->OnReadyToSend(true);
buildbot@webrtc.orga8530772014-12-10 09:01:18 +00004615 last_ssrc_ = 123;
4616 }
4617
4618 protected:
buildbot@webrtc.orga8530772014-12-10 09:01:18 +00004619 void VerifySimulcastSettings(const VideoCodec& codec,
perkj26752742016-10-24 01:21:16 -07004620 int capture_width,
4621 int capture_height,
buildbot@webrtc.orga8530772014-12-10 09:01:18 +00004622 size_t num_configured_streams,
sprang429600d2017-01-26 06:12:26 -08004623 size_t expected_num_streams,
4624 bool screenshare,
4625 bool conference_mode) {
Fredrik Solenbergb071a192015-09-17 16:42:56 +02004626 cricket::VideoSendParameters parameters;
Fredrik Solenbergb071a192015-09-17 16:42:56 +02004627 parameters.codecs.push_back(codec);
sprang429600d2017-01-26 06:12:26 -08004628 parameters.conference_mode = conference_mode;
Fredrik Solenbergb071a192015-09-17 16:42:56 +02004629 ASSERT_TRUE(channel_->SetSendParameters(parameters));
buildbot@webrtc.orga8530772014-12-10 09:01:18 +00004630
Peter Boström0c4e06b2015-10-07 12:23:21 +02004631 std::vector<uint32_t> ssrcs = MAKE_VECTOR(kSsrcs3);
henrikg91d6ede2015-09-17 00:24:34 -07004632 RTC_DCHECK(num_configured_streams <= ssrcs.size());
buildbot@webrtc.orga8530772014-12-10 09:01:18 +00004633 ssrcs.resize(num_configured_streams);
4634
sprangf24a0642017-02-28 13:23:26 -08004635 AddSendStream(CreateSimStreamParams("cname", ssrcs));
pbos@webrtc.org86196c42015-02-16 21:02:00 +00004636 // Send a full-size frame to trigger a stream reconfiguration to use all
4637 // expected simulcast layers.
4638 cricket::FakeVideoCapturer capturer;
sprangf24a0642017-02-28 13:23:26 -08004639 VideoOptions options;
4640 if (screenshare)
4641 options.is_screencast = rtc::Optional<bool>(screenshare);
deadbeef5a4a75a2016-06-02 16:23:38 -07004642 EXPECT_TRUE(
sprang429600d2017-01-26 06:12:26 -08004643 channel_->SetVideoSend(ssrcs.front(), true, &options, &capturer));
sprangf24a0642017-02-28 13:23:26 -08004644 // Fetch the latest stream since SetVideoSend() may recreate it if the
4645 // screen content setting is changed.
4646 FakeVideoSendStream* stream = fake_call_.GetVideoSendStreams().front();
pbos@webrtc.org86196c42015-02-16 21:02:00 +00004647 EXPECT_EQ(cricket::CS_RUNNING, capturer.Start(cricket::VideoFormat(
perkj26752742016-10-24 01:21:16 -07004648 capture_width, capture_height,
pbos@webrtc.org86196c42015-02-16 21:02:00 +00004649 cricket::VideoFormat::FpsToInterval(30),
4650 cricket::FOURCC_I420)));
4651 channel_->SetSend(true);
4652 EXPECT_TRUE(capturer.CaptureFrame());
buildbot@webrtc.orga8530772014-12-10 09:01:18 +00004653
4654 std::vector<webrtc::VideoStream> video_streams = stream->GetVideoStreams();
4655 ASSERT_EQ(expected_num_streams, video_streams.size());
4656
sprang429600d2017-01-26 06:12:26 -08004657 std::vector<webrtc::VideoStream> expected_streams;
4658 if (conference_mode) {
4659 expected_streams = GetSimulcastConfig(
4660 num_configured_streams, capture_width, capture_height, 0,
4661 kDefaultQpMax, kDefaultVideoMaxFramerate, screenshare);
sprang3ebabf12017-02-16 07:35:22 -08004662 if (screenshare) {
4663 for (const webrtc::VideoStream& stream : expected_streams) {
4664 // Never scale screen content.
4665 EXPECT_EQ(stream.width, capture_width);
4666 EXPECT_EQ(stream.height, capture_height);
4667 }
4668 }
sprang429600d2017-01-26 06:12:26 -08004669 } else {
4670 webrtc::VideoStream stream;
4671 stream.width = capture_width;
4672 stream.height = capture_height;
4673 stream.max_framerate = kDefaultVideoMaxFramerate;
4674 stream.min_bitrate_bps = cricket::kMinVideoBitrateKbps * 1000;
4675 int max_bitrate_kbps;
4676 if (capture_width * capture_height <= 320 * 240) {
4677 max_bitrate_kbps = 600;
4678 } else if (capture_width * capture_height <= 640 * 480) {
4679 max_bitrate_kbps = 1700;
4680 } else if (capture_width * capture_height <= 960 * 540) {
4681 max_bitrate_kbps = 2000;
4682 } else {
4683 max_bitrate_kbps = 2500;
4684 }
4685 stream.target_bitrate_bps = stream.max_bitrate_bps =
4686 max_bitrate_kbps * 1000;
4687 stream.max_qp = kDefaultQpMax;
4688 expected_streams.push_back(stream);
4689 }
buildbot@webrtc.orga8530772014-12-10 09:01:18 +00004690
4691 ASSERT_EQ(expected_streams.size(), video_streams.size());
4692
4693 size_t num_streams = video_streams.size();
pbos@webrtc.org77e11bb2015-02-23 16:39:07 +00004694 int total_max_bitrate_bps = 0;
buildbot@webrtc.orga8530772014-12-10 09:01:18 +00004695 for (size_t i = 0; i < num_streams; ++i) {
4696 EXPECT_EQ(expected_streams[i].width, video_streams[i].width);
4697 EXPECT_EQ(expected_streams[i].height, video_streams[i].height);
4698
4699 EXPECT_GT(video_streams[i].max_framerate, 0);
4700 EXPECT_EQ(expected_streams[i].max_framerate,
4701 video_streams[i].max_framerate);
4702
4703 EXPECT_GT(video_streams[i].min_bitrate_bps, 0);
4704 EXPECT_EQ(expected_streams[i].min_bitrate_bps,
4705 video_streams[i].min_bitrate_bps);
4706
4707 EXPECT_GT(video_streams[i].target_bitrate_bps, 0);
4708 EXPECT_EQ(expected_streams[i].target_bitrate_bps,
4709 video_streams[i].target_bitrate_bps);
4710
4711 EXPECT_GT(video_streams[i].max_bitrate_bps, 0);
4712 EXPECT_EQ(expected_streams[i].max_bitrate_bps,
4713 video_streams[i].max_bitrate_bps);
4714
4715 EXPECT_GT(video_streams[i].max_qp, 0);
4716 EXPECT_EQ(expected_streams[i].max_qp, video_streams[i].max_qp);
4717
sprang429600d2017-01-26 06:12:26 -08004718 EXPECT_EQ(!conference_mode,
4719 expected_streams[i].temporal_layer_thresholds_bps.empty());
buildbot@webrtc.orga8530772014-12-10 09:01:18 +00004720 EXPECT_EQ(expected_streams[i].temporal_layer_thresholds_bps,
4721 video_streams[i].temporal_layer_thresholds_bps);
pbos@webrtc.org77e11bb2015-02-23 16:39:07 +00004722
4723 if (i == num_streams - 1) {
4724 total_max_bitrate_bps += video_streams[i].max_bitrate_bps;
4725 } else {
4726 total_max_bitrate_bps += video_streams[i].target_bitrate_bps;
4727 }
buildbot@webrtc.orga8530772014-12-10 09:01:18 +00004728 }
pbos@webrtc.org77e11bb2015-02-23 16:39:07 +00004729
deadbeef5a4a75a2016-06-02 16:23:38 -07004730 EXPECT_TRUE(channel_->SetVideoSend(ssrcs.front(), true, nullptr, nullptr));
buildbot@webrtc.orga8530772014-12-10 09:01:18 +00004731 }
4732
4733 FakeVideoSendStream* AddSendStream() {
4734 return AddSendStream(StreamParams::CreateLegacy(last_ssrc_++));
4735 }
4736
4737 FakeVideoSendStream* AddSendStream(const StreamParams& sp) {
4738 size_t num_streams =
Fredrik Solenberg709ed672015-09-15 12:26:33 +02004739 fake_call_.GetVideoSendStreams().size();
buildbot@webrtc.orga8530772014-12-10 09:01:18 +00004740 EXPECT_TRUE(channel_->AddSendStream(sp));
4741 std::vector<FakeVideoSendStream*> streams =
Fredrik Solenberg709ed672015-09-15 12:26:33 +02004742 fake_call_.GetVideoSendStreams();
buildbot@webrtc.orga8530772014-12-10 09:01:18 +00004743 EXPECT_EQ(num_streams + 1, streams.size());
4744 return streams[streams.size() - 1];
4745 }
4746
4747 std::vector<FakeVideoSendStream*> GetFakeSendStreams() {
Fredrik Solenberg709ed672015-09-15 12:26:33 +02004748 return fake_call_.GetVideoSendStreams();
buildbot@webrtc.orga8530772014-12-10 09:01:18 +00004749 }
4750
4751 FakeVideoReceiveStream* AddRecvStream() {
4752 return AddRecvStream(StreamParams::CreateLegacy(last_ssrc_++));
4753 }
4754
4755 FakeVideoReceiveStream* AddRecvStream(const StreamParams& sp) {
4756 size_t num_streams =
Fredrik Solenberg709ed672015-09-15 12:26:33 +02004757 fake_call_.GetVideoReceiveStreams().size();
buildbot@webrtc.orga8530772014-12-10 09:01:18 +00004758 EXPECT_TRUE(channel_->AddRecvStream(sp));
4759 std::vector<FakeVideoReceiveStream*> streams =
Fredrik Solenberg709ed672015-09-15 12:26:33 +02004760 fake_call_.GetVideoReceiveStreams();
buildbot@webrtc.orga8530772014-12-10 09:01:18 +00004761 EXPECT_EQ(num_streams + 1, streams.size());
4762 return streams[streams.size() - 1];
4763 }
4764
skvlad11a9cbf2016-10-07 11:53:05 -07004765 webrtc::RtcEventLogNullImpl event_log_;
Fredrik Solenberg709ed672015-09-15 12:26:33 +02004766 FakeCall fake_call_;
Magnus Jedvert02e7a192017-09-23 17:21:32 +02004767 cricket::FakeWebRtcVideoEncoderFactory* encoder_factory_;
4768 cricket::FakeWebRtcVideoDecoderFactory* decoder_factory_;
eladalonf1841382017-06-12 01:16:46 -07004769 WebRtcVideoEngine engine_;
kwiberg686a8ef2016-02-26 03:00:35 -08004770 std::unique_ptr<VideoMediaChannel> channel_;
Peter Boström0c4e06b2015-10-07 12:23:21 +02004771 uint32_t last_ssrc_;
buildbot@webrtc.orga8530772014-12-10 09:01:18 +00004772};
4773
eladalonf1841382017-06-12 01:16:46 -07004774TEST_F(WebRtcVideoChannelSimulcastTest, SetSendCodecsWith2SimulcastStreams) {
sprang429600d2017-01-26 06:12:26 -08004775 VerifySimulcastSettings(cricket::VideoCodec("VP8"), 640, 360, 2, 2, false,
4776 true);
buildbot@webrtc.orga8530772014-12-10 09:01:18 +00004777}
4778
eladalonf1841382017-06-12 01:16:46 -07004779TEST_F(WebRtcVideoChannelSimulcastTest, SetSendCodecsWith3SimulcastStreams) {
sprang429600d2017-01-26 06:12:26 -08004780 VerifySimulcastSettings(cricket::VideoCodec("VP8"), 1280, 720, 3, 3, false,
4781 true);
buildbot@webrtc.orga8530772014-12-10 09:01:18 +00004782}
4783
4784// Test that we normalize send codec format size in simulcast.
eladalonf1841382017-06-12 01:16:46 -07004785TEST_F(WebRtcVideoChannelSimulcastTest, SetSendCodecsWithOddSizeInSimulcast) {
sprang429600d2017-01-26 06:12:26 -08004786 VerifySimulcastSettings(cricket::VideoCodec("VP8"), 541, 271, 2, 2, false,
4787 true);
buildbot@webrtc.orga8530772014-12-10 09:01:18 +00004788}
sprang429600d2017-01-26 06:12:26 -08004789
eladalonf1841382017-06-12 01:16:46 -07004790TEST_F(WebRtcVideoChannelSimulcastTest, SetSendCodecsForScreenshare) {
sprang429600d2017-01-26 06:12:26 -08004791 VerifySimulcastSettings(cricket::VideoCodec("VP8"), 1280, 720, 3, 1, true,
4792 false);
4793}
4794
eladalonf1841382017-06-12 01:16:46 -07004795TEST_F(WebRtcVideoChannelSimulcastTest,
sprang429600d2017-01-26 06:12:26 -08004796 SetSendCodecsForConferenceModeScreenshare) {
4797 VerifySimulcastSettings(cricket::VideoCodec("VP8"), 1280, 720, 3, 1, true,
4798 true);
4799}
4800
eladalonf1841382017-06-12 01:16:46 -07004801TEST_F(WebRtcVideoChannelSimulcastTest, SetSendCodecsForSimulcastScreenshare) {
sprang429600d2017-01-26 06:12:26 -08004802 webrtc::test::ScopedFieldTrials override_field_trials_(
4803 "WebRTC-SimulcastScreenshare/Enabled/");
4804 VerifySimulcastSettings(cricket::VideoCodec("VP8"), 1280, 720, 3, 2, true,
4805 true);
4806}
4807
eladalonf1841382017-06-12 01:16:46 -07004808TEST_F(WebRtcVideoChannelSimulcastTest,
sprangfe627f32017-03-29 08:24:59 -07004809 NoSimulcastScreenshareWithoutConference) {
4810 webrtc::test::ScopedFieldTrials override_field_trials_(
4811 "WebRTC-SimulcastScreenshare/Enabled/");
4812 VerifySimulcastSettings(cricket::VideoCodec("VP8"), 1280, 720, 3, 1, true,
4813 false);
4814}
4815
pbos@webrtc.orgb5a22b12014-05-13 11:07:01 +00004816} // namespace cricket