OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (c) 2004 The WebRTC project authors. All Rights Reserved. | |
3 * | |
4 * Use of this source code is governed by a BSD-style license | |
5 * that can be found in the LICENSE file in the root of the source | |
6 * tree. An additional intellectual property rights grant can be found | |
7 * in the file PATENTS. All contributing project authors may | |
8 * be found in the AUTHORS file in the root of the source tree. | |
9 */ | |
10 | |
11 #ifdef HAVE_WEBRTC_VIDEO | |
12 | |
13 #include <algorithm> | |
14 #include <map> | |
15 #include <vector> | |
16 | |
17 #include "webrtc/base/arraysize.h" | |
18 #include "webrtc/base/gunit.h" | |
19 #include "webrtc/base/stringutils.h" | |
20 #include "webrtc/media/base/testutils.h" | |
21 #include "webrtc/media/base/videoengine_unittest.h" | |
22 #include "webrtc/media/webrtc/fakewebrtccall.h" | |
23 #include "webrtc/media/webrtc/fakewebrtcvideoengine.h" | |
24 #include "webrtc/media/webrtc/simulcast.h" | |
25 #include "webrtc/media/webrtc/webrtcvideochannelfactory.h" | |
26 #include "webrtc/media/webrtc/webrtcvideoengine2.h" | |
27 #include "webrtc/media/webrtc/webrtcvoiceengine.h" | |
28 #include "webrtc/test/field_trial.h" | |
29 #include "webrtc/video_encoder.h" | |
30 | |
31 namespace { | |
32 static const int kDefaultQpMax = 56; | |
33 static const int kDefaultFramerate = 30; | |
34 | |
35 static const cricket::VideoCodec kVp8Codec720p(100, "VP8", 1280, 720, 30, 0); | |
36 static const cricket::VideoCodec kVp8Codec360p(100, "VP8", 640, 360, 30, 0); | |
37 static const cricket::VideoCodec kVp8Codec270p(100, "VP8", 480, 270, 30, 0); | |
38 | |
39 static const cricket::VideoCodec kVp8Codec(100, "VP8", 640, 400, 30, 0); | |
40 static const cricket::VideoCodec kVp9Codec(101, "VP9", 640, 400, 30, 0); | |
41 static const cricket::VideoCodec kH264Codec(102, "H264", 640, 400, 30, 0); | |
42 | |
43 static const cricket::VideoCodec kRedCodec(116, "red", 0, 0, 0, 0); | |
44 static const cricket::VideoCodec kUlpfecCodec(117, "ulpfec", 0, 0, 0, 0); | |
45 | |
46 static const uint8_t kRedRtxPayloadType = 125; | |
47 | |
48 static const uint32_t kSsrcs1[] = {1}; | |
49 static const uint32_t kSsrcs3[] = {1, 2, 3}; | |
50 static const uint32_t kRtxSsrcs1[] = {4}; | |
51 static const uint32_t kIncomingUnsignalledSsrc = 0xC0FFEE; | |
52 static const char kUnsupportedExtensionName[] = | |
53 "urn:ietf:params:rtp-hdrext:unsupported"; | |
54 | |
55 void VerifyCodecHasDefaultFeedbackParams(const cricket::VideoCodec& codec) { | |
56 EXPECT_TRUE(codec.HasFeedbackParam(cricket::FeedbackParam( | |
57 cricket::kRtcpFbParamNack, cricket::kParamValueEmpty))); | |
58 EXPECT_TRUE(codec.HasFeedbackParam(cricket::FeedbackParam( | |
59 cricket::kRtcpFbParamNack, cricket::kRtcpFbNackParamPli))); | |
60 EXPECT_TRUE(codec.HasFeedbackParam(cricket::FeedbackParam( | |
61 cricket::kRtcpFbParamRemb, cricket::kParamValueEmpty))); | |
62 EXPECT_TRUE(codec.HasFeedbackParam(cricket::FeedbackParam( | |
63 cricket::kRtcpFbParamTransportCc, cricket::kParamValueEmpty))); | |
64 EXPECT_TRUE(codec.HasFeedbackParam(cricket::FeedbackParam( | |
65 cricket::kRtcpFbParamCcm, cricket::kRtcpFbCcmParamFir))); | |
66 } | |
67 | |
68 static void CreateBlackFrame(webrtc::VideoFrame* video_frame, | |
69 int width, | |
70 int height) { | |
71 video_frame->CreateEmptyFrame( | |
72 width, height, width, (width + 1) / 2, (width + 1) / 2); | |
73 memset(video_frame->buffer(webrtc::kYPlane), 16, | |
74 video_frame->allocated_size(webrtc::kYPlane)); | |
75 memset(video_frame->buffer(webrtc::kUPlane), 128, | |
76 video_frame->allocated_size(webrtc::kUPlane)); | |
77 memset(video_frame->buffer(webrtc::kVPlane), 128, | |
78 video_frame->allocated_size(webrtc::kVPlane)); | |
79 } | |
80 | |
81 void VerifySendStreamHasRtxTypes(const webrtc::VideoSendStream::Config& config, | |
82 const std::map<int, int>& rtx_types) { | |
83 std::map<int, int>::const_iterator it; | |
84 it = rtx_types.find(config.encoder_settings.payload_type); | |
85 EXPECT_TRUE(it != rtx_types.end() && | |
86 it->second == config.rtp.rtx.payload_type); | |
87 | |
88 if (config.rtp.fec.red_rtx_payload_type != -1) { | |
89 it = rtx_types.find(config.rtp.fec.red_payload_type); | |
90 EXPECT_TRUE(it != rtx_types.end() && | |
91 it->second == config.rtp.fec.red_rtx_payload_type); | |
92 } | |
93 } | |
94 } // namespace | |
95 | |
96 namespace cricket { | |
97 class WebRtcVideoEngine2Test : public ::testing::Test { | |
98 public: | |
99 WebRtcVideoEngine2Test() : WebRtcVideoEngine2Test("") {} | |
100 explicit WebRtcVideoEngine2Test(const char* field_trials) | |
101 : WebRtcVideoEngine2Test(nullptr, field_trials) {} | |
102 WebRtcVideoEngine2Test(WebRtcVoiceEngine* voice_engine, | |
103 const char* field_trials) | |
104 : override_field_trials_(field_trials), | |
105 call_(webrtc::Call::Create(webrtc::Call::Config())), | |
106 engine_() { | |
107 std::vector<VideoCodec> engine_codecs = engine_.codecs(); | |
108 RTC_DCHECK(!engine_codecs.empty()); | |
109 bool codec_set = false; | |
110 for (size_t i = 0; i < engine_codecs.size(); ++i) { | |
111 if (engine_codecs[i].name == "red") { | |
112 default_red_codec_ = engine_codecs[i]; | |
113 } else if (engine_codecs[i].name == "ulpfec") { | |
114 default_ulpfec_codec_ = engine_codecs[i]; | |
115 } else if (engine_codecs[i].name == "rtx") { | |
116 int associated_payload_type; | |
117 if (engine_codecs[i].GetParam(kCodecParamAssociatedPayloadType, | |
118 &associated_payload_type)) { | |
119 default_apt_rtx_types_[associated_payload_type] = engine_codecs[i].id; | |
120 } | |
121 } else if (!codec_set) { | |
122 default_codec_ = engine_codecs[i]; | |
123 codec_set = true; | |
124 } | |
125 } | |
126 | |
127 RTC_DCHECK(codec_set); | |
128 } | |
129 | |
130 protected: | |
131 VideoMediaChannel* SetUpForExternalEncoderFactory( | |
132 cricket::WebRtcVideoEncoderFactory* encoder_factory, | |
133 const std::vector<VideoCodec>& codecs); | |
134 | |
135 VideoMediaChannel* SetUpForExternalDecoderFactory( | |
136 cricket::WebRtcVideoDecoderFactory* decoder_factory, | |
137 const std::vector<VideoCodec>& codecs); | |
138 | |
139 void TestExtendedEncoderOveruse(bool use_external_encoder); | |
140 | |
141 webrtc::test::ScopedFieldTrials override_field_trials_; | |
142 // Used in WebRtcVideoEngine2VoiceTest, but defined here so it's properly | |
143 // initialized when the constructor is called. | |
144 rtc::scoped_ptr<webrtc::Call> call_; | |
145 WebRtcVoiceEngine voice_engine_; | |
146 WebRtcVideoEngine2 engine_; | |
147 VideoCodec default_codec_; | |
148 VideoCodec default_red_codec_; | |
149 VideoCodec default_ulpfec_codec_; | |
150 std::map<int, int> default_apt_rtx_types_; | |
151 }; | |
152 | |
153 TEST_F(WebRtcVideoEngine2Test, DefaultRtxCodecHasAssociatedPayloadTypeSet) { | |
154 std::vector<VideoCodec> engine_codecs = engine_.codecs(); | |
155 for (size_t i = 0; i < engine_codecs.size(); ++i) { | |
156 if (engine_codecs[i].name != kRtxCodecName) | |
157 continue; | |
158 int associated_payload_type; | |
159 EXPECT_TRUE(engine_codecs[i].GetParam(kCodecParamAssociatedPayloadType, | |
160 &associated_payload_type)); | |
161 EXPECT_EQ(default_codec_.id, associated_payload_type); | |
162 return; | |
163 } | |
164 FAIL() << "No RTX codec found among default codecs."; | |
165 } | |
166 | |
167 TEST_F(WebRtcVideoEngine2Test, SupportsTimestampOffsetHeaderExtension) { | |
168 RtpCapabilities capabilities = engine_.GetCapabilities(); | |
169 ASSERT_FALSE(capabilities.header_extensions.empty()); | |
170 for (const RtpHeaderExtension& extension : capabilities.header_extensions) { | |
171 if (extension.uri == kRtpTimestampOffsetHeaderExtension) { | |
172 EXPECT_EQ(kRtpTimestampOffsetHeaderExtensionDefaultId, extension.id); | |
173 return; | |
174 } | |
175 } | |
176 FAIL() << "Timestamp offset extension not in header-extension list."; | |
177 } | |
178 | |
179 TEST_F(WebRtcVideoEngine2Test, SupportsAbsoluteSenderTimeHeaderExtension) { | |
180 RtpCapabilities capabilities = engine_.GetCapabilities(); | |
181 ASSERT_FALSE(capabilities.header_extensions.empty()); | |
182 for (const RtpHeaderExtension& extension : capabilities.header_extensions) { | |
183 if (extension.uri == kRtpAbsoluteSenderTimeHeaderExtension) { | |
184 EXPECT_EQ(kRtpAbsoluteSenderTimeHeaderExtensionDefaultId, extension.id); | |
185 return; | |
186 } | |
187 } | |
188 FAIL() << "Absolute Sender Time extension not in header-extension list."; | |
189 } | |
190 | |
191 class WebRtcVideoEngine2WithSendSideBweTest : public WebRtcVideoEngine2Test { | |
192 public: | |
193 WebRtcVideoEngine2WithSendSideBweTest() | |
194 : WebRtcVideoEngine2Test("WebRTC-SendSideBwe/Enabled/") {} | |
195 }; | |
196 | |
197 TEST_F(WebRtcVideoEngine2WithSendSideBweTest, | |
198 SupportsTransportSequenceNumberHeaderExtension) { | |
199 RtpCapabilities capabilities = engine_.GetCapabilities(); | |
200 ASSERT_FALSE(capabilities.header_extensions.empty()); | |
201 for (const RtpHeaderExtension& extension : capabilities.header_extensions) { | |
202 if (extension.uri == kRtpTransportSequenceNumberHeaderExtension) { | |
203 EXPECT_EQ(kRtpTransportSequenceNumberHeaderExtensionDefaultId, | |
204 extension.id); | |
205 return; | |
206 } | |
207 } | |
208 FAIL() << "Transport sequence number extension not in header-extension list."; | |
209 } | |
210 | |
211 TEST_F(WebRtcVideoEngine2Test, SupportsVideoRotationHeaderExtension) { | |
212 RtpCapabilities capabilities = engine_.GetCapabilities(); | |
213 ASSERT_FALSE(capabilities.header_extensions.empty()); | |
214 for (const RtpHeaderExtension& extension : capabilities.header_extensions) { | |
215 if (extension.uri == kRtpVideoRotationHeaderExtension) { | |
216 EXPECT_EQ(kRtpVideoRotationHeaderExtensionDefaultId, extension.id); | |
217 return; | |
218 } | |
219 } | |
220 FAIL() << "Video Rotation extension not in header-extension list."; | |
221 } | |
222 | |
223 TEST_F(WebRtcVideoEngine2Test, CVOSetHeaderExtensionBeforeCapturer) { | |
224 // Allocate the capturer first to prevent early destruction before channel's | |
225 // dtor is called. | |
226 cricket::FakeVideoCapturer capturer; | |
227 | |
228 cricket::FakeWebRtcVideoEncoderFactory encoder_factory; | |
229 encoder_factory.AddSupportedVideoCodecType(webrtc::kVideoCodecVP8, "VP8"); | |
230 cricket::VideoSendParameters parameters; | |
231 parameters.codecs.push_back(kVp8Codec); | |
232 | |
233 rtc::scoped_ptr<VideoMediaChannel> channel( | |
234 SetUpForExternalEncoderFactory(&encoder_factory, parameters.codecs)); | |
235 EXPECT_TRUE(channel->AddSendStream(StreamParams::CreateLegacy(kSsrc))); | |
236 | |
237 // Add CVO extension. | |
238 const int id = 1; | |
239 parameters.extensions.push_back( | |
240 cricket::RtpHeaderExtension(kRtpVideoRotationHeaderExtension, id)); | |
241 EXPECT_TRUE(channel->SetSendParameters(parameters)); | |
242 | |
243 // Set capturer. | |
244 EXPECT_TRUE(channel->SetCapturer(kSsrc, &capturer)); | |
245 | |
246 // Verify capturer has turned off applying rotation. | |
247 EXPECT_FALSE(capturer.GetApplyRotation()); | |
248 | |
249 // Verify removing header extension turns on applying rotation. | |
250 parameters.extensions.clear(); | |
251 EXPECT_TRUE(channel->SetSendParameters(parameters)); | |
252 EXPECT_TRUE(capturer.GetApplyRotation()); | |
253 } | |
254 | |
255 TEST_F(WebRtcVideoEngine2Test, CVOSetHeaderExtensionAfterCapturer) { | |
256 cricket::FakeVideoCapturer capturer; | |
257 | |
258 cricket::FakeWebRtcVideoEncoderFactory encoder_factory; | |
259 encoder_factory.AddSupportedVideoCodecType(webrtc::kVideoCodecVP8, "VP8"); | |
260 cricket::VideoSendParameters parameters; | |
261 parameters.codecs.push_back(kVp8Codec); | |
262 | |
263 rtc::scoped_ptr<VideoMediaChannel> channel( | |
264 SetUpForExternalEncoderFactory(&encoder_factory, parameters.codecs)); | |
265 EXPECT_TRUE(channel->AddSendStream(StreamParams::CreateLegacy(kSsrc))); | |
266 | |
267 // Set capturer. | |
268 EXPECT_TRUE(channel->SetCapturer(kSsrc, &capturer)); | |
269 | |
270 // Add CVO extension. | |
271 const int id = 1; | |
272 parameters.extensions.push_back( | |
273 cricket::RtpHeaderExtension(kRtpVideoRotationHeaderExtension, id)); | |
274 EXPECT_TRUE(channel->SetSendParameters(parameters)); | |
275 | |
276 // Verify capturer has turned off applying rotation. | |
277 EXPECT_FALSE(capturer.GetApplyRotation()); | |
278 | |
279 // Verify removing header extension turns on applying rotation. | |
280 parameters.extensions.clear(); | |
281 EXPECT_TRUE(channel->SetSendParameters(parameters)); | |
282 EXPECT_TRUE(capturer.GetApplyRotation()); | |
283 } | |
284 | |
285 TEST_F(WebRtcVideoEngine2Test, SetSendFailsBeforeSettingCodecs) { | |
286 engine_.Init(); | |
287 rtc::scoped_ptr<VideoMediaChannel> channel( | |
288 engine_.CreateChannel(call_.get(), cricket::VideoOptions())); | |
289 | |
290 EXPECT_TRUE(channel->AddSendStream(StreamParams::CreateLegacy(123))); | |
291 | |
292 EXPECT_FALSE(channel->SetSend(true)) | |
293 << "Channel should not start without codecs."; | |
294 EXPECT_TRUE(channel->SetSend(false)) | |
295 << "Channel should be stoppable even without set codecs."; | |
296 } | |
297 | |
298 TEST_F(WebRtcVideoEngine2Test, GetStatsWithoutSendCodecsSetDoesNotCrash) { | |
299 engine_.Init(); | |
300 rtc::scoped_ptr<VideoMediaChannel> channel( | |
301 engine_.CreateChannel(call_.get(), cricket::VideoOptions())); | |
302 EXPECT_TRUE(channel->AddSendStream(StreamParams::CreateLegacy(123))); | |
303 VideoMediaInfo info; | |
304 channel->GetStats(&info); | |
305 } | |
306 | |
307 TEST_F(WebRtcVideoEngine2Test, UseExternalFactoryForVp8WhenSupported) { | |
308 cricket::FakeWebRtcVideoEncoderFactory encoder_factory; | |
309 encoder_factory.AddSupportedVideoCodecType(webrtc::kVideoCodecVP8, "VP8"); | |
310 cricket::VideoSendParameters parameters; | |
311 parameters.codecs.push_back(kVp8Codec); | |
312 | |
313 rtc::scoped_ptr<VideoMediaChannel> channel( | |
314 SetUpForExternalEncoderFactory(&encoder_factory, parameters.codecs)); | |
315 | |
316 EXPECT_TRUE( | |
317 channel->AddSendStream(cricket::StreamParams::CreateLegacy(kSsrc))); | |
318 ASSERT_EQ(1u, encoder_factory.encoders().size()); | |
319 EXPECT_TRUE(channel->SetSend(true)); | |
320 | |
321 cricket::FakeVideoCapturer capturer; | |
322 EXPECT_TRUE(channel->SetCapturer(kSsrc, &capturer)); | |
323 EXPECT_EQ(cricket::CS_RUNNING, | |
324 capturer.Start(capturer.GetSupportedFormats()->front())); | |
325 EXPECT_TRUE(capturer.CaptureFrame()); | |
326 EXPECT_TRUE_WAIT(encoder_factory.encoders()[0]->GetNumEncodedFrames() > 0, | |
327 kTimeout); | |
328 | |
329 // Sending one frame will have reallocated the encoder since input size | |
330 // changes from a small default to the actual frame width/height. | |
331 int num_created_encoders = encoder_factory.GetNumCreatedEncoders(); | |
332 EXPECT_EQ(num_created_encoders, 2); | |
333 | |
334 // Setting codecs of the same type should not reallocate any encoders | |
335 // (expecting a no-op). | |
336 EXPECT_TRUE(channel->SetSendParameters(parameters)); | |
337 EXPECT_EQ(num_created_encoders, encoder_factory.GetNumCreatedEncoders()); | |
338 | |
339 // Remove stream previously added to free the external encoder instance. | |
340 EXPECT_TRUE(channel->RemoveSendStream(kSsrc)); | |
341 EXPECT_EQ(0u, encoder_factory.encoders().size()); | |
342 } | |
343 | |
344 void WebRtcVideoEngine2Test::TestExtendedEncoderOveruse( | |
345 bool use_external_encoder) { | |
346 cricket::FakeWebRtcVideoEncoderFactory encoder_factory; | |
347 encoder_factory.AddSupportedVideoCodecType(webrtc::kVideoCodecVP8, "VP8"); | |
348 cricket::VideoSendParameters parameters; | |
349 parameters.codecs.push_back(kVp8Codec); | |
350 rtc::scoped_ptr<VideoMediaChannel> channel; | |
351 FakeCall* fake_call = new FakeCall(webrtc::Call::Config()); | |
352 call_.reset(fake_call); | |
353 if (use_external_encoder) { | |
354 channel.reset( | |
355 SetUpForExternalEncoderFactory(&encoder_factory, parameters.codecs)); | |
356 } else { | |
357 engine_.Init(); | |
358 channel.reset(engine_.CreateChannel(call_.get(), cricket::VideoOptions())); | |
359 } | |
360 ASSERT_TRUE( | |
361 channel->AddSendStream(cricket::StreamParams::CreateLegacy(kSsrc))); | |
362 EXPECT_TRUE(channel->SetSendParameters(parameters)); | |
363 EXPECT_TRUE(channel->SetSend(true)); | |
364 FakeVideoSendStream* stream = fake_call->GetVideoSendStreams()[0]; | |
365 | |
366 EXPECT_EQ(use_external_encoder, | |
367 stream->GetConfig().encoder_settings.full_overuse_time); | |
368 // Remove stream previously added to free the external encoder instance. | |
369 EXPECT_TRUE(channel->RemoveSendStream(kSsrc)); | |
370 } | |
371 | |
372 TEST_F(WebRtcVideoEngine2Test, EnablesFullEncoderTimeForExternalEncoders) { | |
373 TestExtendedEncoderOveruse(true); | |
374 } | |
375 | |
376 TEST_F(WebRtcVideoEngine2Test, DisablesFullEncoderTimeForNonExternalEncoders) { | |
377 TestExtendedEncoderOveruse(false); | |
378 } | |
379 | |
380 TEST_F(WebRtcVideoEngine2Test, CanConstructDecoderForVp9EncoderFactory) { | |
381 cricket::FakeWebRtcVideoEncoderFactory encoder_factory; | |
382 encoder_factory.AddSupportedVideoCodecType(webrtc::kVideoCodecVP9, "VP9"); | |
383 std::vector<cricket::VideoCodec> codecs; | |
384 codecs.push_back(kVp9Codec); | |
385 | |
386 rtc::scoped_ptr<VideoMediaChannel> channel( | |
387 SetUpForExternalEncoderFactory(&encoder_factory, codecs)); | |
388 | |
389 EXPECT_TRUE( | |
390 channel->AddRecvStream(cricket::StreamParams::CreateLegacy(kSsrc))); | |
391 } | |
392 | |
393 TEST_F(WebRtcVideoEngine2Test, PropagatesInputFrameTimestamp) { | |
394 cricket::FakeWebRtcVideoEncoderFactory encoder_factory; | |
395 encoder_factory.AddSupportedVideoCodecType(webrtc::kVideoCodecVP8, "VP8"); | |
396 std::vector<cricket::VideoCodec> codecs; | |
397 codecs.push_back(kVp8Codec); | |
398 | |
399 FakeCall* fake_call = new FakeCall(webrtc::Call::Config()); | |
400 call_.reset(fake_call); | |
401 rtc::scoped_ptr<VideoMediaChannel> channel( | |
402 SetUpForExternalEncoderFactory(&encoder_factory, codecs)); | |
403 | |
404 EXPECT_TRUE( | |
405 channel->AddSendStream(cricket::StreamParams::CreateLegacy(kSsrc))); | |
406 | |
407 FakeVideoCapturer capturer; | |
408 EXPECT_TRUE(channel->SetCapturer(kSsrc, &capturer)); | |
409 capturer.Start(cricket::VideoFormat(1280, 720, | |
410 cricket::VideoFormat::FpsToInterval(60), | |
411 cricket::FOURCC_I420)); | |
412 channel->SetSend(true); | |
413 | |
414 FakeVideoSendStream* stream = fake_call->GetVideoSendStreams()[0]; | |
415 | |
416 EXPECT_TRUE(capturer.CaptureFrame()); | |
417 int64_t last_timestamp = stream->GetLastTimestamp(); | |
418 for (int i = 0; i < 10; i++) { | |
419 EXPECT_TRUE(capturer.CaptureFrame()); | |
420 int64_t timestamp = stream->GetLastTimestamp(); | |
421 int64_t interval = timestamp - last_timestamp; | |
422 | |
423 // Precision changes from nanosecond to millisecond. | |
424 // Allow error to be no more than 1. | |
425 EXPECT_NEAR(cricket::VideoFormat::FpsToInterval(60) / 1E6, interval, 1); | |
426 | |
427 last_timestamp = timestamp; | |
428 } | |
429 | |
430 capturer.Start(cricket::VideoFormat(1280, 720, | |
431 cricket::VideoFormat::FpsToInterval(30), | |
432 cricket::FOURCC_I420)); | |
433 | |
434 EXPECT_TRUE(capturer.CaptureFrame()); | |
435 last_timestamp = stream->GetLastTimestamp(); | |
436 for (int i = 0; i < 10; i++) { | |
437 EXPECT_TRUE(capturer.CaptureFrame()); | |
438 int64_t timestamp = stream->GetLastTimestamp(); | |
439 int64_t interval = timestamp - last_timestamp; | |
440 | |
441 // Precision changes from nanosecond to millisecond. | |
442 // Allow error to be no more than 1. | |
443 EXPECT_NEAR(cricket::VideoFormat::FpsToInterval(30) / 1E6, interval, 1); | |
444 | |
445 last_timestamp = timestamp; | |
446 } | |
447 | |
448 // Remove stream previously added to free the external encoder instance. | |
449 EXPECT_TRUE(channel->RemoveSendStream(kSsrc)); | |
450 } | |
451 | |
452 TEST_F(WebRtcVideoEngine2Test, | |
453 ProducesIncreasingTimestampsWithResetInputSources) { | |
454 cricket::FakeWebRtcVideoEncoderFactory encoder_factory; | |
455 encoder_factory.AddSupportedVideoCodecType(webrtc::kVideoCodecVP8, "VP8"); | |
456 std::vector<cricket::VideoCodec> codecs; | |
457 codecs.push_back(kVp8Codec); | |
458 | |
459 FakeCall* fake_call = new FakeCall(webrtc::Call::Config()); | |
460 call_.reset(fake_call); | |
461 rtc::scoped_ptr<VideoMediaChannel> channel( | |
462 SetUpForExternalEncoderFactory(&encoder_factory, codecs)); | |
463 | |
464 EXPECT_TRUE( | |
465 channel->AddSendStream(cricket::StreamParams::CreateLegacy(kSsrc))); | |
466 channel->SetSend(true); | |
467 FakeVideoSendStream* stream = fake_call->GetVideoSendStreams()[0]; | |
468 | |
469 FakeVideoCapturer capturer1; | |
470 EXPECT_TRUE(channel->SetCapturer(kSsrc, &capturer1)); | |
471 | |
472 cricket::CapturedFrame frame; | |
473 frame.width = 1280; | |
474 frame.height = 720; | |
475 frame.fourcc = cricket::FOURCC_I420; | |
476 frame.data_size = static_cast<uint32_t>( | |
477 cricket::VideoFrame::SizeOf(frame.width, frame.height)); | |
478 rtc::scoped_ptr<char[]> data(new char[frame.data_size]); | |
479 frame.data = data.get(); | |
480 memset(frame.data, 1, frame.data_size); | |
481 const int kInitialTimestamp = 123456; | |
482 frame.time_stamp = kInitialTimestamp; | |
483 | |
484 // Deliver initial frame. | |
485 capturer1.SignalCapturedFrame(&frame); | |
486 // Deliver next frame 1 second later. | |
487 frame.time_stamp += rtc::kNumNanosecsPerSec; | |
488 rtc::Thread::Current()->SleepMs(1000); | |
489 capturer1.SignalCapturedFrame(&frame); | |
490 | |
491 int64_t capturer1_last_timestamp = stream->GetLastTimestamp(); | |
492 // Reset input source, should still be continuous even though input-frame | |
493 // timestamp is less than before. | |
494 FakeVideoCapturer capturer2; | |
495 EXPECT_TRUE(channel->SetCapturer(kSsrc, &capturer2)); | |
496 | |
497 rtc::Thread::Current()->SleepMs(1); | |
498 // Deliver with a timestamp (10 seconds) before the previous initial one, | |
499 // these should not be related at all anymore and it should still work fine. | |
500 frame.time_stamp = kInitialTimestamp - 10000; | |
501 capturer2.SignalCapturedFrame(&frame); | |
502 | |
503 // New timestamp should be at least 1ms in the future and not old. | |
504 EXPECT_GT(stream->GetLastTimestamp(), capturer1_last_timestamp); | |
505 | |
506 EXPECT_TRUE(channel->RemoveSendStream(kSsrc)); | |
507 } | |
508 | |
509 VideoMediaChannel* WebRtcVideoEngine2Test::SetUpForExternalEncoderFactory( | |
510 cricket::WebRtcVideoEncoderFactory* encoder_factory, | |
511 const std::vector<VideoCodec>& codecs) { | |
512 engine_.SetExternalEncoderFactory(encoder_factory); | |
513 engine_.Init(); | |
514 | |
515 VideoMediaChannel* channel = | |
516 engine_.CreateChannel(call_.get(), cricket::VideoOptions()); | |
517 cricket::VideoSendParameters parameters; | |
518 parameters.codecs = codecs; | |
519 EXPECT_TRUE(channel->SetSendParameters(parameters)); | |
520 | |
521 return channel; | |
522 } | |
523 | |
524 VideoMediaChannel* WebRtcVideoEngine2Test::SetUpForExternalDecoderFactory( | |
525 cricket::WebRtcVideoDecoderFactory* decoder_factory, | |
526 const std::vector<VideoCodec>& codecs) { | |
527 engine_.SetExternalDecoderFactory(decoder_factory); | |
528 engine_.Init(); | |
529 | |
530 VideoMediaChannel* channel = | |
531 engine_.CreateChannel(call_.get(), cricket::VideoOptions()); | |
532 cricket::VideoRecvParameters parameters; | |
533 parameters.codecs = codecs; | |
534 EXPECT_TRUE(channel->SetRecvParameters(parameters)); | |
535 | |
536 return channel; | |
537 } | |
538 | |
539 TEST_F(WebRtcVideoEngine2Test, UsesSimulcastAdapterForVp8Factories) { | |
540 cricket::FakeWebRtcVideoEncoderFactory encoder_factory; | |
541 encoder_factory.AddSupportedVideoCodecType(webrtc::kVideoCodecVP8, "VP8"); | |
542 std::vector<cricket::VideoCodec> codecs; | |
543 codecs.push_back(kVp8Codec); | |
544 | |
545 rtc::scoped_ptr<VideoMediaChannel> channel( | |
546 SetUpForExternalEncoderFactory(&encoder_factory, codecs)); | |
547 | |
548 std::vector<uint32_t> ssrcs = MAKE_VECTOR(kSsrcs3); | |
549 | |
550 EXPECT_TRUE( | |
551 channel->AddSendStream(CreateSimStreamParams("cname", ssrcs))); | |
552 EXPECT_TRUE(channel->SetSend(true)); | |
553 | |
554 cricket::FakeVideoCapturer capturer; | |
555 EXPECT_TRUE(channel->SetCapturer(ssrcs.front(), &capturer)); | |
556 EXPECT_EQ(cricket::CS_RUNNING, | |
557 capturer.Start(capturer.GetSupportedFormats()->front())); | |
558 EXPECT_TRUE(capturer.CaptureFrame()); | |
559 | |
560 EXPECT_GT(encoder_factory.encoders().size(), 1u); | |
561 | |
562 // Verify that encoders are configured for simulcast through adapter | |
563 // (increasing resolution and only configured to send one stream each). | |
564 int prev_width = -1; | |
565 for (size_t i = 0; i < encoder_factory.encoders().size(); ++i) { | |
566 webrtc::VideoCodec codec_settings = | |
567 encoder_factory.encoders()[i]->GetCodecSettings(); | |
568 EXPECT_EQ(0, codec_settings.numberOfSimulcastStreams); | |
569 EXPECT_GT(codec_settings.width, prev_width); | |
570 prev_width = codec_settings.width; | |
571 } | |
572 | |
573 EXPECT_TRUE(channel->SetCapturer(ssrcs.front(), NULL)); | |
574 | |
575 channel.reset(); | |
576 ASSERT_EQ(0u, encoder_factory.encoders().size()); | |
577 } | |
578 | |
579 TEST_F(WebRtcVideoEngine2Test, ChannelWithExternalH264CanChangeToInternalVp8) { | |
580 cricket::FakeWebRtcVideoEncoderFactory encoder_factory; | |
581 encoder_factory.AddSupportedVideoCodecType(webrtc::kVideoCodecH264, "H264"); | |
582 std::vector<cricket::VideoCodec> codecs; | |
583 codecs.push_back(kH264Codec); | |
584 | |
585 rtc::scoped_ptr<VideoMediaChannel> channel( | |
586 SetUpForExternalEncoderFactory(&encoder_factory, codecs)); | |
587 | |
588 EXPECT_TRUE( | |
589 channel->AddSendStream(cricket::StreamParams::CreateLegacy(kSsrc))); | |
590 ASSERT_EQ(1u, encoder_factory.encoders().size()); | |
591 | |
592 cricket::VideoSendParameters parameters; | |
593 parameters.codecs.push_back(kVp8Codec); | |
594 EXPECT_TRUE(channel->SetSendParameters(parameters)); | |
595 ASSERT_EQ(0u, encoder_factory.encoders().size()); | |
596 } | |
597 | |
598 TEST_F(WebRtcVideoEngine2Test, | |
599 DontUseExternalEncoderFactoryForUnsupportedCodecs) { | |
600 cricket::FakeWebRtcVideoEncoderFactory encoder_factory; | |
601 encoder_factory.AddSupportedVideoCodecType(webrtc::kVideoCodecH264, "H264"); | |
602 std::vector<cricket::VideoCodec> codecs; | |
603 codecs.push_back(kVp8Codec); | |
604 | |
605 rtc::scoped_ptr<VideoMediaChannel> channel( | |
606 SetUpForExternalEncoderFactory(&encoder_factory, codecs)); | |
607 | |
608 EXPECT_TRUE( | |
609 channel->AddSendStream(cricket::StreamParams::CreateLegacy(kSsrc))); | |
610 // Make sure DestroyVideoEncoder was called on the factory. | |
611 ASSERT_EQ(0u, encoder_factory.encoders().size()); | |
612 } | |
613 | |
614 TEST_F(WebRtcVideoEngine2Test, | |
615 UsesSimulcastAdapterForVp8WithCombinedVP8AndH264Factory) { | |
616 cricket::FakeWebRtcVideoEncoderFactory encoder_factory; | |
617 encoder_factory.AddSupportedVideoCodecType(webrtc::kVideoCodecVP8, "VP8"); | |
618 encoder_factory.AddSupportedVideoCodecType(webrtc::kVideoCodecH264, "H264"); | |
619 | |
620 std::vector<cricket::VideoCodec> codecs; | |
621 codecs.push_back(kVp8Codec); | |
622 | |
623 rtc::scoped_ptr<VideoMediaChannel> channel( | |
624 SetUpForExternalEncoderFactory(&encoder_factory, codecs)); | |
625 | |
626 std::vector<uint32_t> ssrcs = MAKE_VECTOR(kSsrcs3); | |
627 | |
628 EXPECT_TRUE( | |
629 channel->AddSendStream(CreateSimStreamParams("cname", ssrcs))); | |
630 EXPECT_TRUE(channel->SetSend(true)); | |
631 | |
632 // Send a fake frame, or else the media engine will configure the simulcast | |
633 // encoder adapter at a low-enough size that it'll only create a single | |
634 // encoder layer. | |
635 cricket::FakeVideoCapturer capturer; | |
636 EXPECT_TRUE(channel->SetCapturer(ssrcs.front(), &capturer)); | |
637 EXPECT_EQ(cricket::CS_RUNNING, | |
638 capturer.Start(capturer.GetSupportedFormats()->front())); | |
639 EXPECT_TRUE(capturer.CaptureFrame()); | |
640 | |
641 ASSERT_GT(encoder_factory.encoders().size(), 1u); | |
642 EXPECT_EQ(webrtc::kVideoCodecVP8, | |
643 encoder_factory.encoders()[0]->GetCodecSettings().codecType); | |
644 | |
645 channel.reset(); | |
646 // Make sure DestroyVideoEncoder was called on the factory. | |
647 EXPECT_EQ(0u, encoder_factory.encoders().size()); | |
648 } | |
649 | |
650 TEST_F(WebRtcVideoEngine2Test, | |
651 DestroysNonSimulcastEncoderFromCombinedVP8AndH264Factory) { | |
652 cricket::FakeWebRtcVideoEncoderFactory encoder_factory; | |
653 encoder_factory.AddSupportedVideoCodecType(webrtc::kVideoCodecVP8, "VP8"); | |
654 encoder_factory.AddSupportedVideoCodecType(webrtc::kVideoCodecH264, "H264"); | |
655 | |
656 std::vector<cricket::VideoCodec> codecs; | |
657 codecs.push_back(kH264Codec); | |
658 | |
659 rtc::scoped_ptr<VideoMediaChannel> channel( | |
660 SetUpForExternalEncoderFactory(&encoder_factory, codecs)); | |
661 | |
662 EXPECT_TRUE( | |
663 channel->AddSendStream(cricket::StreamParams::CreateLegacy(kSsrc))); | |
664 ASSERT_EQ(1u, encoder_factory.encoders().size()); | |
665 EXPECT_EQ(webrtc::kVideoCodecH264, | |
666 encoder_factory.encoders()[0]->GetCodecSettings().codecType); | |
667 | |
668 channel.reset(); | |
669 // Make sure DestroyVideoEncoder was called on the factory. | |
670 ASSERT_EQ(0u, encoder_factory.encoders().size()); | |
671 } | |
672 | |
673 TEST_F(WebRtcVideoEngine2Test, SimulcastDisabledForH264) { | |
674 cricket::FakeWebRtcVideoEncoderFactory encoder_factory; | |
675 encoder_factory.AddSupportedVideoCodecType(webrtc::kVideoCodecH264, "H264"); | |
676 std::vector<cricket::VideoCodec> codecs; | |
677 codecs.push_back(kH264Codec); | |
678 | |
679 rtc::scoped_ptr<VideoMediaChannel> channel( | |
680 SetUpForExternalEncoderFactory(&encoder_factory, codecs)); | |
681 | |
682 const std::vector<uint32_t> ssrcs = MAKE_VECTOR(kSsrcs3); | |
683 EXPECT_TRUE( | |
684 channel->AddSendStream(cricket::CreateSimStreamParams("cname", ssrcs))); | |
685 | |
686 // Send a frame of 720p. This should trigger a "real" encoder initialization. | |
687 cricket::VideoFormat format( | |
688 1280, 720, cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420); | |
689 cricket::FakeVideoCapturer capturer; | |
690 EXPECT_TRUE(channel->SetCapturer(ssrcs[0], &capturer)); | |
691 EXPECT_EQ(cricket::CS_RUNNING, capturer.Start(format)); | |
692 EXPECT_TRUE(capturer.CaptureFrame()); | |
693 | |
694 ASSERT_EQ(1u, encoder_factory.encoders().size()); | |
695 FakeWebRtcVideoEncoder* encoder = encoder_factory.encoders()[0]; | |
696 EXPECT_EQ(webrtc::kVideoCodecH264, encoder->GetCodecSettings().codecType); | |
697 EXPECT_EQ(1u, encoder->GetCodecSettings().numberOfSimulcastStreams); | |
698 EXPECT_TRUE(channel->SetCapturer(ssrcs[0], nullptr)); | |
699 } | |
700 | |
701 // Test that external codecs are added to the end of the supported codec list. | |
702 TEST_F(WebRtcVideoEngine2Test, ReportSupportedExternalCodecs) { | |
703 cricket::FakeWebRtcVideoEncoderFactory encoder_factory; | |
704 encoder_factory.AddSupportedVideoCodecType(webrtc::kVideoCodecUnknown, | |
705 "FakeExternalCodec"); | |
706 engine_.SetExternalEncoderFactory(&encoder_factory); | |
707 engine_.Init(); | |
708 | |
709 std::vector<cricket::VideoCodec> codecs(engine_.codecs()); | |
710 ASSERT_GE(codecs.size(), 2u); | |
711 cricket::VideoCodec internal_codec = codecs.front(); | |
712 cricket::VideoCodec external_codec = codecs.back(); | |
713 | |
714 // The external codec will appear at last. | |
715 EXPECT_EQ("VP8", internal_codec.name); | |
716 EXPECT_EQ("FakeExternalCodec", external_codec.name); | |
717 } | |
718 | |
719 TEST_F(WebRtcVideoEngine2Test, RegisterExternalDecodersIfSupported) { | |
720 cricket::FakeWebRtcVideoDecoderFactory decoder_factory; | |
721 decoder_factory.AddSupportedVideoCodecType(webrtc::kVideoCodecVP8); | |
722 cricket::VideoRecvParameters parameters; | |
723 parameters.codecs.push_back(kVp8Codec); | |
724 | |
725 rtc::scoped_ptr<VideoMediaChannel> channel( | |
726 SetUpForExternalDecoderFactory(&decoder_factory, parameters.codecs)); | |
727 | |
728 EXPECT_TRUE( | |
729 channel->AddRecvStream(cricket::StreamParams::CreateLegacy(kSsrc))); | |
730 ASSERT_EQ(1u, decoder_factory.decoders().size()); | |
731 | |
732 // Setting codecs of the same type should not reallocate the decoder. | |
733 EXPECT_TRUE(channel->SetRecvParameters(parameters)); | |
734 EXPECT_EQ(1, decoder_factory.GetNumCreatedDecoders()); | |
735 | |
736 // Remove stream previously added to free the external decoder instance. | |
737 EXPECT_TRUE(channel->RemoveRecvStream(kSsrc)); | |
738 EXPECT_EQ(0u, decoder_factory.decoders().size()); | |
739 } | |
740 | |
741 // Verifies that we can set up decoders that are not internally supported. | |
742 TEST_F(WebRtcVideoEngine2Test, RegisterExternalH264DecoderIfSupported) { | |
743 // TODO(pbos): Do not assume that encoder/decoder support is symmetric. We | |
744 // can't even query the WebRtcVideoDecoderFactory for supported codecs. | |
745 // For now we add a FakeWebRtcVideoEncoderFactory to add H264 to supported | |
746 // codecs. | |
747 cricket::FakeWebRtcVideoEncoderFactory encoder_factory; | |
748 encoder_factory.AddSupportedVideoCodecType(webrtc::kVideoCodecH264, "H264"); | |
749 engine_.SetExternalEncoderFactory(&encoder_factory); | |
750 cricket::FakeWebRtcVideoDecoderFactory decoder_factory; | |
751 decoder_factory.AddSupportedVideoCodecType(webrtc::kVideoCodecH264); | |
752 std::vector<cricket::VideoCodec> codecs; | |
753 codecs.push_back(kH264Codec); | |
754 | |
755 rtc::scoped_ptr<VideoMediaChannel> channel( | |
756 SetUpForExternalDecoderFactory(&decoder_factory, codecs)); | |
757 | |
758 EXPECT_TRUE( | |
759 channel->AddRecvStream(cricket::StreamParams::CreateLegacy(kSsrc))); | |
760 ASSERT_EQ(1u, decoder_factory.decoders().size()); | |
761 } | |
762 | |
763 class WebRtcVideoChannel2BaseTest | |
764 : public VideoMediaChannelTest<WebRtcVideoEngine2, WebRtcVideoChannel2> { | |
765 protected: | |
766 typedef VideoMediaChannelTest<WebRtcVideoEngine2, WebRtcVideoChannel2> Base; | |
767 | |
768 cricket::VideoCodec DefaultCodec() override { return kVp8Codec; } | |
769 }; | |
770 | |
771 #define WEBRTC_BASE_TEST(test) \ | |
772 TEST_F(WebRtcVideoChannel2BaseTest, test) { Base::test(); } | |
773 | |
774 #define WEBRTC_DISABLED_BASE_TEST(test) \ | |
775 TEST_F(WebRtcVideoChannel2BaseTest, DISABLED_##test) { Base::test(); } | |
776 | |
777 WEBRTC_BASE_TEST(SetSend); | |
778 WEBRTC_BASE_TEST(SetSendWithoutCodecs); | |
779 WEBRTC_BASE_TEST(SetSendSetsTransportBufferSizes); | |
780 | |
781 WEBRTC_BASE_TEST(GetStats); | |
782 WEBRTC_BASE_TEST(GetStatsMultipleRecvStreams); | |
783 WEBRTC_BASE_TEST(GetStatsMultipleSendStreams); | |
784 | |
785 WEBRTC_BASE_TEST(SetSendBandwidth); | |
786 | |
787 WEBRTC_BASE_TEST(SetSendSsrc); | |
788 WEBRTC_BASE_TEST(SetSendSsrcAfterSetCodecs); | |
789 | |
790 WEBRTC_BASE_TEST(SetSink); | |
791 | |
792 WEBRTC_BASE_TEST(AddRemoveSendStreams); | |
793 | |
794 WEBRTC_BASE_TEST(SimulateConference); | |
795 | |
796 WEBRTC_BASE_TEST(AddRemoveCapturer); | |
797 | |
798 WEBRTC_BASE_TEST(RemoveCapturerWithoutAdd); | |
799 | |
800 WEBRTC_BASE_TEST(AddRemoveCapturerMultipleSources); | |
801 | |
802 // TODO(pbos): Figure out why this fails so often. | |
803 WEBRTC_DISABLED_BASE_TEST(HighAspectHighHeightCapturer); | |
804 | |
805 WEBRTC_BASE_TEST(RejectEmptyStreamParams); | |
806 | |
807 WEBRTC_BASE_TEST(AdaptResolution16x10); | |
808 | |
809 WEBRTC_BASE_TEST(AdaptResolution4x3); | |
810 | |
811 // TODO(juberti): Restore this test once we support sending 0 fps. | |
812 WEBRTC_DISABLED_BASE_TEST(AdaptDropAllFrames); | |
813 // TODO(juberti): Understand why we get decode errors on this test. | |
814 WEBRTC_DISABLED_BASE_TEST(AdaptFramerate); | |
815 | |
816 WEBRTC_BASE_TEST(SendsLowerResolutionOnSmallerFrames); | |
817 | |
818 WEBRTC_BASE_TEST(MuteStream); | |
819 | |
820 WEBRTC_BASE_TEST(MultipleSendStreams); | |
821 | |
822 TEST_F(WebRtcVideoChannel2BaseTest, SendAndReceiveVp8Vga) { | |
823 SendAndReceive(cricket::VideoCodec(100, "VP8", 640, 400, 30, 0)); | |
824 } | |
825 | |
826 TEST_F(WebRtcVideoChannel2BaseTest, SendAndReceiveVp8Qvga) { | |
827 SendAndReceive(cricket::VideoCodec(100, "VP8", 320, 200, 30, 0)); | |
828 } | |
829 | |
830 TEST_F(WebRtcVideoChannel2BaseTest, SendAndReceiveVp8SvcQqvga) { | |
831 SendAndReceive(cricket::VideoCodec(100, "VP8", 160, 100, 30, 0)); | |
832 } | |
833 | |
834 TEST_F(WebRtcVideoChannel2BaseTest, TwoStreamsSendAndReceive) { | |
835 Base::TwoStreamsSendAndReceive(kVp8Codec); | |
836 } | |
837 | |
838 TEST_F(WebRtcVideoChannel2BaseTest, TwoStreamsReUseFirstStream) { | |
839 Base::TwoStreamsReUseFirstStream(kVp8Codec); | |
840 } | |
841 | |
842 class WebRtcVideoChannel2Test : public WebRtcVideoEngine2Test { | |
843 public: | |
844 WebRtcVideoChannel2Test() : WebRtcVideoChannel2Test("") {} | |
845 explicit WebRtcVideoChannel2Test(const char* field_trials) | |
846 : WebRtcVideoEngine2Test(field_trials), last_ssrc_(0) {} | |
847 void SetUp() override { | |
848 fake_call_.reset(new FakeCall(webrtc::Call::Config())); | |
849 engine_.Init(); | |
850 channel_.reset( | |
851 engine_.CreateChannel(fake_call_.get(), cricket::VideoOptions())); | |
852 last_ssrc_ = 123; | |
853 send_parameters_.codecs = engine_.codecs(); | |
854 recv_parameters_.codecs = engine_.codecs(); | |
855 ASSERT_TRUE(channel_->SetSendParameters(send_parameters_)); | |
856 } | |
857 | |
858 protected: | |
859 FakeVideoSendStream* AddSendStream() { | |
860 return AddSendStream(StreamParams::CreateLegacy(++last_ssrc_)); | |
861 } | |
862 | |
863 FakeVideoSendStream* AddSendStream(const StreamParams& sp) { | |
864 size_t num_streams = fake_call_->GetVideoSendStreams().size(); | |
865 EXPECT_TRUE(channel_->AddSendStream(sp)); | |
866 std::vector<FakeVideoSendStream*> streams = | |
867 fake_call_->GetVideoSendStreams(); | |
868 EXPECT_EQ(num_streams + 1, streams.size()); | |
869 return streams[streams.size() - 1]; | |
870 } | |
871 | |
872 std::vector<FakeVideoSendStream*> GetFakeSendStreams() { | |
873 return fake_call_->GetVideoSendStreams(); | |
874 } | |
875 | |
876 FakeVideoReceiveStream* AddRecvStream() { | |
877 return AddRecvStream(StreamParams::CreateLegacy(++last_ssrc_)); | |
878 } | |
879 | |
880 FakeVideoReceiveStream* AddRecvStream(const StreamParams& sp) { | |
881 size_t num_streams = fake_call_->GetVideoReceiveStreams().size(); | |
882 EXPECT_TRUE(channel_->AddRecvStream(sp)); | |
883 std::vector<FakeVideoReceiveStream*> streams = | |
884 fake_call_->GetVideoReceiveStreams(); | |
885 EXPECT_EQ(num_streams + 1, streams.size()); | |
886 return streams[streams.size() - 1]; | |
887 } | |
888 | |
889 void SetSendCodecsShouldWorkForBitrates(const char* min_bitrate_kbps, | |
890 int expected_min_bitrate_bps, | |
891 const char* start_bitrate_kbps, | |
892 int expected_start_bitrate_bps, | |
893 const char* max_bitrate_kbps, | |
894 int expected_max_bitrate_bps) { | |
895 auto& codecs = send_parameters_.codecs; | |
896 codecs.clear(); | |
897 codecs.push_back(kVp8Codec); | |
898 codecs[0].params[kCodecParamMinBitrate] = min_bitrate_kbps; | |
899 codecs[0].params[kCodecParamStartBitrate] = start_bitrate_kbps; | |
900 codecs[0].params[kCodecParamMaxBitrate] = max_bitrate_kbps; | |
901 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_)); | |
902 | |
903 EXPECT_EQ(expected_min_bitrate_bps, | |
904 fake_call_->GetConfig().bitrate_config.min_bitrate_bps); | |
905 EXPECT_EQ(expected_start_bitrate_bps, | |
906 fake_call_->GetConfig().bitrate_config.start_bitrate_bps); | |
907 EXPECT_EQ(expected_max_bitrate_bps, | |
908 fake_call_->GetConfig().bitrate_config.max_bitrate_bps); | |
909 } | |
910 | |
911 void TestSetSendRtpHeaderExtensions(const std::string& cricket_ext, | |
912 const std::string& webrtc_ext) { | |
913 // Enable extension. | |
914 const int id = 1; | |
915 cricket::VideoSendParameters parameters = send_parameters_; | |
916 parameters.extensions.push_back( | |
917 cricket::RtpHeaderExtension(cricket_ext, id)); | |
918 EXPECT_TRUE(channel_->SetSendParameters(parameters)); | |
919 FakeVideoSendStream* send_stream = | |
920 AddSendStream(cricket::StreamParams::CreateLegacy(123)); | |
921 | |
922 // Verify the send extension id. | |
923 ASSERT_EQ(1u, send_stream->GetConfig().rtp.extensions.size()); | |
924 EXPECT_EQ(id, send_stream->GetConfig().rtp.extensions[0].id); | |
925 EXPECT_EQ(webrtc_ext, send_stream->GetConfig().rtp.extensions[0].name); | |
926 // Verify call with same set of extensions returns true. | |
927 EXPECT_TRUE(channel_->SetSendParameters(parameters)); | |
928 // Verify that SetSendRtpHeaderExtensions doesn't implicitly add them for | |
929 // receivers. | |
930 EXPECT_TRUE(AddRecvStream(cricket::StreamParams::CreateLegacy(123)) | |
931 ->GetConfig() | |
932 .rtp.extensions.empty()); | |
933 | |
934 // Verify that existing RTP header extensions can be removed. | |
935 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_)); | |
936 ASSERT_EQ(1u, fake_call_->GetVideoSendStreams().size()); | |
937 send_stream = fake_call_->GetVideoSendStreams()[0]; | |
938 EXPECT_TRUE(send_stream->GetConfig().rtp.extensions.empty()); | |
939 | |
940 // Verify that adding receive RTP header extensions adds them for existing | |
941 // streams. | |
942 EXPECT_TRUE(channel_->SetSendParameters(parameters)); | |
943 send_stream = fake_call_->GetVideoSendStreams()[0]; | |
944 ASSERT_EQ(1u, send_stream->GetConfig().rtp.extensions.size()); | |
945 EXPECT_EQ(id, send_stream->GetConfig().rtp.extensions[0].id); | |
946 EXPECT_EQ(webrtc_ext, send_stream->GetConfig().rtp.extensions[0].name); | |
947 } | |
948 | |
949 void TestSetRecvRtpHeaderExtensions(const std::string& cricket_ext, | |
950 const std::string& webrtc_ext) { | |
951 // Enable extension. | |
952 const int id = 1; | |
953 cricket::VideoRecvParameters parameters = recv_parameters_; | |
954 parameters.extensions.push_back( | |
955 cricket::RtpHeaderExtension(cricket_ext, id)); | |
956 EXPECT_TRUE(channel_->SetRecvParameters(parameters)); | |
957 | |
958 FakeVideoReceiveStream* recv_stream = | |
959 AddRecvStream(cricket::StreamParams::CreateLegacy(123)); | |
960 | |
961 // Verify the recv extension id. | |
962 ASSERT_EQ(1u, recv_stream->GetConfig().rtp.extensions.size()); | |
963 EXPECT_EQ(id, recv_stream->GetConfig().rtp.extensions[0].id); | |
964 EXPECT_EQ(webrtc_ext, recv_stream->GetConfig().rtp.extensions[0].name); | |
965 // Verify call with same set of extensions returns true. | |
966 EXPECT_TRUE(channel_->SetRecvParameters(parameters)); | |
967 | |
968 // Verify that SetRecvRtpHeaderExtensions doesn't implicitly add them for | |
969 // senders. | |
970 EXPECT_TRUE(AddSendStream(cricket::StreamParams::CreateLegacy(123)) | |
971 ->GetConfig() | |
972 .rtp.extensions.empty()); | |
973 | |
974 // Verify that existing RTP header extensions can be removed. | |
975 EXPECT_TRUE(channel_->SetRecvParameters(recv_parameters_)); | |
976 ASSERT_EQ(1u, fake_call_->GetVideoReceiveStreams().size()); | |
977 recv_stream = fake_call_->GetVideoReceiveStreams()[0]; | |
978 EXPECT_TRUE(recv_stream->GetConfig().rtp.extensions.empty()); | |
979 | |
980 // Verify that adding receive RTP header extensions adds them for existing | |
981 // streams. | |
982 EXPECT_TRUE(channel_->SetRecvParameters(parameters)); | |
983 recv_stream = fake_call_->GetVideoReceiveStreams()[0]; | |
984 ASSERT_EQ(1u, recv_stream->GetConfig().rtp.extensions.size()); | |
985 EXPECT_EQ(id, recv_stream->GetConfig().rtp.extensions[0].id); | |
986 EXPECT_EQ(webrtc_ext, recv_stream->GetConfig().rtp.extensions[0].name); | |
987 } | |
988 | |
989 void TestExtensionFilter(const std::vector<std::string>& extensions, | |
990 const std::string& expected_extension) { | |
991 cricket::VideoSendParameters parameters = send_parameters_; | |
992 int expected_id = -1; | |
993 int id = 1; | |
994 for (const std::string& extension : extensions) { | |
995 if (extension == expected_extension) | |
996 expected_id = id; | |
997 parameters.extensions.push_back( | |
998 cricket::RtpHeaderExtension(extension, id++)); | |
999 } | |
1000 EXPECT_TRUE(channel_->SetSendParameters(parameters)); | |
1001 FakeVideoSendStream* send_stream = | |
1002 AddSendStream(cricket::StreamParams::CreateLegacy(123)); | |
1003 | |
1004 // Verify that only one of them has been set, and that it is the one with | |
1005 // highest priority (transport sequence number). | |
1006 ASSERT_EQ(1u, send_stream->GetConfig().rtp.extensions.size()); | |
1007 EXPECT_EQ(expected_id, send_stream->GetConfig().rtp.extensions[0].id); | |
1008 EXPECT_EQ(expected_extension, | |
1009 send_stream->GetConfig().rtp.extensions[0].name); | |
1010 } | |
1011 | |
1012 void TestCpuAdaptation(bool enable_overuse, bool is_screenshare); | |
1013 void TestReceiverLocalSsrcConfiguration(bool receiver_first); | |
1014 void TestReceiveUnsignalledSsrcPacket(uint8_t payload_type, | |
1015 bool expect_created_receive_stream); | |
1016 | |
1017 FakeVideoSendStream* SetDenoisingOption( | |
1018 const cricket::VideoSendParameters& parameters, bool enabled) { | |
1019 cricket::VideoSendParameters params = parameters; | |
1020 params.options.video_noise_reduction = rtc::Optional<bool>(enabled); | |
1021 channel_->SetSendParameters(params); | |
1022 return fake_call_->GetVideoSendStreams().back(); | |
1023 } | |
1024 | |
1025 FakeVideoSendStream* SetUpSimulcast(bool enabled, bool with_rtx) { | |
1026 const int kRtxSsrcOffset = 0xDEADBEEF; | |
1027 last_ssrc_ += 3; | |
1028 std::vector<uint32_t> ssrcs; | |
1029 std::vector<uint32_t> rtx_ssrcs; | |
1030 uint32_t num_streams = enabled ? 3 : 1; | |
1031 for (uint32_t i = 0; i < num_streams; ++i) { | |
1032 uint32_t ssrc = last_ssrc_ + i; | |
1033 ssrcs.push_back(ssrc); | |
1034 if (with_rtx) { | |
1035 rtx_ssrcs.push_back(ssrc + kRtxSsrcOffset); | |
1036 } | |
1037 } | |
1038 if (with_rtx) { | |
1039 return AddSendStream( | |
1040 cricket::CreateSimWithRtxStreamParams("cname", ssrcs, rtx_ssrcs)); | |
1041 } | |
1042 return AddSendStream(CreateSimStreamParams("cname", ssrcs)); | |
1043 } | |
1044 | |
1045 rtc::scoped_ptr<FakeCall> fake_call_; | |
1046 rtc::scoped_ptr<VideoMediaChannel> channel_; | |
1047 cricket::VideoSendParameters send_parameters_; | |
1048 cricket::VideoRecvParameters recv_parameters_; | |
1049 uint32_t last_ssrc_; | |
1050 }; | |
1051 | |
1052 TEST_F(WebRtcVideoChannel2Test, SetsSyncGroupFromSyncLabel) { | |
1053 const uint32_t kVideoSsrc = 123; | |
1054 const std::string kSyncLabel = "AvSyncLabel"; | |
1055 | |
1056 cricket::StreamParams sp = cricket::StreamParams::CreateLegacy(kVideoSsrc); | |
1057 sp.sync_label = kSyncLabel; | |
1058 EXPECT_TRUE(channel_->AddRecvStream(sp)); | |
1059 | |
1060 EXPECT_EQ(1, fake_call_->GetVideoReceiveStreams().size()); | |
1061 EXPECT_EQ(kSyncLabel, | |
1062 fake_call_->GetVideoReceiveStreams()[0]->GetConfig().sync_group) | |
1063 << "SyncGroup should be set based on sync_label"; | |
1064 } | |
1065 | |
1066 TEST_F(WebRtcVideoChannel2Test, RecvStreamWithSimAndRtx) { | |
1067 cricket::VideoSendParameters parameters; | |
1068 parameters.codecs = engine_.codecs(); | |
1069 EXPECT_TRUE(channel_->SetSendParameters(parameters)); | |
1070 EXPECT_TRUE(channel_->SetSend(true)); | |
1071 parameters.options.conference_mode = rtc::Optional<bool>(true); | |
1072 EXPECT_TRUE(channel_->SetSendParameters(parameters)); | |
1073 | |
1074 // Send side. | |
1075 const std::vector<uint32_t> ssrcs = MAKE_VECTOR(kSsrcs1); | |
1076 const std::vector<uint32_t> rtx_ssrcs = MAKE_VECTOR(kRtxSsrcs1); | |
1077 FakeVideoSendStream* send_stream = AddSendStream( | |
1078 cricket::CreateSimWithRtxStreamParams("cname", ssrcs, rtx_ssrcs)); | |
1079 | |
1080 ASSERT_EQ(rtx_ssrcs.size(), send_stream->GetConfig().rtp.rtx.ssrcs.size()); | |
1081 for (size_t i = 0; i < rtx_ssrcs.size(); ++i) | |
1082 EXPECT_EQ(rtx_ssrcs[i], send_stream->GetConfig().rtp.rtx.ssrcs[i]); | |
1083 | |
1084 // Receiver side. | |
1085 FakeVideoReceiveStream* recv_stream = AddRecvStream( | |
1086 cricket::CreateSimWithRtxStreamParams("cname", ssrcs, rtx_ssrcs)); | |
1087 ASSERT_GT(recv_stream->GetConfig().rtp.rtx.size(), 0u) | |
1088 << "No SSRCs for RTX configured by AddRecvStream."; | |
1089 EXPECT_EQ(rtx_ssrcs[0], | |
1090 recv_stream->GetConfig().rtp.rtx.begin()->second.ssrc); | |
1091 // TODO(pbos): Make sure we set the RTX for correct payloads etc. | |
1092 } | |
1093 | |
1094 TEST_F(WebRtcVideoChannel2Test, RecvStreamWithRtx) { | |
1095 // Setup one channel with an associated RTX stream. | |
1096 cricket::StreamParams params = | |
1097 cricket::StreamParams::CreateLegacy(kSsrcs1[0]); | |
1098 params.AddFidSsrc(kSsrcs1[0], kRtxSsrcs1[0]); | |
1099 FakeVideoReceiveStream* recv_stream = AddRecvStream(params); | |
1100 EXPECT_EQ(kRtxSsrcs1[0], | |
1101 recv_stream->GetConfig().rtp.rtx.begin()->second.ssrc); | |
1102 } | |
1103 | |
1104 TEST_F(WebRtcVideoChannel2Test, RecvStreamNoRtx) { | |
1105 // Setup one channel without an associated RTX stream. | |
1106 cricket::StreamParams params = | |
1107 cricket::StreamParams::CreateLegacy(kSsrcs1[0]); | |
1108 FakeVideoReceiveStream* recv_stream = AddRecvStream(params); | |
1109 ASSERT_TRUE(recv_stream->GetConfig().rtp.rtx.empty()); | |
1110 } | |
1111 | |
1112 TEST_F(WebRtcVideoChannel2Test, NoHeaderExtesionsByDefault) { | |
1113 FakeVideoSendStream* send_stream = | |
1114 AddSendStream(cricket::StreamParams::CreateLegacy(kSsrcs1[0])); | |
1115 ASSERT_TRUE(send_stream->GetConfig().rtp.extensions.empty()); | |
1116 | |
1117 FakeVideoReceiveStream* recv_stream = | |
1118 AddRecvStream(cricket::StreamParams::CreateLegacy(kSsrcs1[0])); | |
1119 ASSERT_TRUE(recv_stream->GetConfig().rtp.extensions.empty()); | |
1120 } | |
1121 | |
1122 // Test support for RTP timestamp offset header extension. | |
1123 TEST_F(WebRtcVideoChannel2Test, SendRtpTimestampOffsetHeaderExtensions) { | |
1124 TestSetSendRtpHeaderExtensions(kRtpTimestampOffsetHeaderExtension, | |
1125 webrtc::RtpExtension::kTOffset); | |
1126 } | |
1127 TEST_F(WebRtcVideoChannel2Test, RecvRtpTimestampOffsetHeaderExtensions) { | |
1128 TestSetRecvRtpHeaderExtensions(kRtpTimestampOffsetHeaderExtension, | |
1129 webrtc::RtpExtension::kTOffset); | |
1130 } | |
1131 | |
1132 // Test support for absolute send time header extension. | |
1133 TEST_F(WebRtcVideoChannel2Test, SendAbsoluteSendTimeHeaderExtensions) { | |
1134 TestSetSendRtpHeaderExtensions(kRtpAbsoluteSenderTimeHeaderExtension, | |
1135 webrtc::RtpExtension::kAbsSendTime); | |
1136 } | |
1137 TEST_F(WebRtcVideoChannel2Test, RecvAbsoluteSendTimeHeaderExtensions) { | |
1138 TestSetRecvRtpHeaderExtensions(kRtpAbsoluteSenderTimeHeaderExtension, | |
1139 webrtc::RtpExtension::kAbsSendTime); | |
1140 } | |
1141 | |
1142 TEST_F(WebRtcVideoChannel2Test, FiltersExtensionsPicksTransportSeqNum) { | |
1143 // Enable three redundant extensions. | |
1144 std::vector<std::string> extensions; | |
1145 extensions.push_back(kRtpAbsoluteSenderTimeHeaderExtension); | |
1146 extensions.push_back(kRtpTimestampOffsetHeaderExtension); | |
1147 extensions.push_back(kRtpTransportSequenceNumberHeaderExtension); | |
1148 TestExtensionFilter(extensions, kRtpTransportSequenceNumberHeaderExtension); | |
1149 } | |
1150 | |
1151 TEST_F(WebRtcVideoChannel2Test, FiltersExtensionsPicksAbsSendTime) { | |
1152 // Enable two redundant extensions. | |
1153 std::vector<std::string> extensions; | |
1154 extensions.push_back(kRtpAbsoluteSenderTimeHeaderExtension); | |
1155 extensions.push_back(kRtpTimestampOffsetHeaderExtension); | |
1156 TestExtensionFilter(extensions, kRtpAbsoluteSenderTimeHeaderExtension); | |
1157 } | |
1158 | |
1159 class WebRtcVideoChannel2WithSendSideBweTest : public WebRtcVideoChannel2Test { | |
1160 public: | |
1161 WebRtcVideoChannel2WithSendSideBweTest() | |
1162 : WebRtcVideoChannel2Test("WebRTC-SendSideBwe/Enabled/") {} | |
1163 }; | |
1164 | |
1165 // Test support for transport sequence number header extension. | |
1166 TEST_F(WebRtcVideoChannel2WithSendSideBweTest, | |
1167 SendTransportSequenceNumberHeaderExtensions) { | |
1168 TestSetSendRtpHeaderExtensions( | |
1169 kRtpTransportSequenceNumberHeaderExtension, | |
1170 webrtc::RtpExtension::kTransportSequenceNumber); | |
1171 } | |
1172 TEST_F(WebRtcVideoChannel2WithSendSideBweTest, | |
1173 RecvTransportSequenceNumberHeaderExtensions) { | |
1174 TestSetRecvRtpHeaderExtensions( | |
1175 kRtpTransportSequenceNumberHeaderExtension, | |
1176 webrtc::RtpExtension::kTransportSequenceNumber); | |
1177 } | |
1178 | |
1179 // Test support for video rotation header extension. | |
1180 TEST_F(WebRtcVideoChannel2Test, SendVideoRotationHeaderExtensions) { | |
1181 TestSetSendRtpHeaderExtensions(kRtpVideoRotationHeaderExtension, | |
1182 webrtc::RtpExtension::kVideoRotation); | |
1183 } | |
1184 TEST_F(WebRtcVideoChannel2Test, RecvVideoRotationHeaderExtensions) { | |
1185 TestSetRecvRtpHeaderExtensions(kRtpVideoRotationHeaderExtension, | |
1186 webrtc::RtpExtension::kVideoRotation); | |
1187 } | |
1188 | |
1189 TEST_F(WebRtcVideoChannel2Test, IdenticalSendExtensionsDoesntRecreateStream) { | |
1190 const int kAbsSendTimeId = 1; | |
1191 const int kVideoRotationId = 2; | |
1192 send_parameters_.extensions.push_back(cricket::RtpHeaderExtension( | |
1193 kRtpAbsoluteSenderTimeHeaderExtension, kAbsSendTimeId)); | |
1194 send_parameters_.extensions.push_back(cricket::RtpHeaderExtension( | |
1195 kRtpVideoRotationHeaderExtension, kVideoRotationId)); | |
1196 | |
1197 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_)); | |
1198 FakeVideoSendStream* send_stream = | |
1199 AddSendStream(cricket::StreamParams::CreateLegacy(123)); | |
1200 | |
1201 EXPECT_EQ(1, fake_call_->GetNumCreatedSendStreams()); | |
1202 ASSERT_EQ(2u, send_stream->GetConfig().rtp.extensions.size()); | |
1203 | |
1204 // Setting the same extensions (even if in different order) shouldn't | |
1205 // reallocate the stream. | |
1206 std::reverse(send_parameters_.extensions.begin(), | |
1207 send_parameters_.extensions.end()); | |
1208 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_)); | |
1209 | |
1210 EXPECT_EQ(1, fake_call_->GetNumCreatedSendStreams()); | |
1211 | |
1212 // Setting different extensions should recreate the stream. | |
1213 send_parameters_.extensions.resize(1); | |
1214 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_)); | |
1215 | |
1216 EXPECT_EQ(2, fake_call_->GetNumCreatedSendStreams()); | |
1217 } | |
1218 | |
1219 TEST_F(WebRtcVideoChannel2Test, IdenticalRecvExtensionsDoesntRecreateStream) { | |
1220 const int kTOffsetId = 1; | |
1221 const int kAbsSendTimeId = 2; | |
1222 const int kVideoRotationId = 3; | |
1223 recv_parameters_.extensions.push_back(cricket::RtpHeaderExtension( | |
1224 kRtpAbsoluteSenderTimeHeaderExtension, kAbsSendTimeId)); | |
1225 recv_parameters_.extensions.push_back(cricket::RtpHeaderExtension( | |
1226 kRtpTimestampOffsetHeaderExtension, kTOffsetId)); | |
1227 recv_parameters_.extensions.push_back(cricket::RtpHeaderExtension( | |
1228 kRtpVideoRotationHeaderExtension, kVideoRotationId)); | |
1229 | |
1230 EXPECT_TRUE(channel_->SetRecvParameters(recv_parameters_)); | |
1231 FakeVideoReceiveStream* recv_stream = | |
1232 AddRecvStream(cricket::StreamParams::CreateLegacy(123)); | |
1233 | |
1234 EXPECT_EQ(1, fake_call_->GetNumCreatedReceiveStreams()); | |
1235 ASSERT_EQ(3u, recv_stream->GetConfig().rtp.extensions.size()); | |
1236 | |
1237 // Setting the same extensions (even if in different order) shouldn't | |
1238 // reallocate the stream. | |
1239 std::reverse(recv_parameters_.extensions.begin(), | |
1240 recv_parameters_.extensions.end()); | |
1241 EXPECT_TRUE(channel_->SetRecvParameters(recv_parameters_)); | |
1242 | |
1243 EXPECT_EQ(1, fake_call_->GetNumCreatedReceiveStreams()); | |
1244 | |
1245 // Setting different extensions should recreate the stream. | |
1246 recv_parameters_.extensions.resize(1); | |
1247 EXPECT_TRUE(channel_->SetRecvParameters(recv_parameters_)); | |
1248 | |
1249 EXPECT_EQ(2, fake_call_->GetNumCreatedReceiveStreams()); | |
1250 } | |
1251 | |
1252 TEST_F(WebRtcVideoChannel2Test, | |
1253 SetSendRtpHeaderExtensionsExcludeUnsupportedExtensions) { | |
1254 const int kUnsupportedId = 1; | |
1255 const int kTOffsetId = 2; | |
1256 | |
1257 send_parameters_.extensions.push_back( | |
1258 cricket::RtpHeaderExtension(kUnsupportedExtensionName, kUnsupportedId)); | |
1259 send_parameters_.extensions.push_back( | |
1260 cricket::RtpHeaderExtension(webrtc::RtpExtension::kTOffset, kTOffsetId)); | |
1261 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_)); | |
1262 FakeVideoSendStream* send_stream = | |
1263 AddSendStream(cricket::StreamParams::CreateLegacy(123)); | |
1264 | |
1265 // Only timestamp offset extension is set to send stream, | |
1266 // unsupported rtp extension is ignored. | |
1267 ASSERT_EQ(1u, send_stream->GetConfig().rtp.extensions.size()); | |
1268 EXPECT_STREQ(webrtc::RtpExtension::kTOffset, | |
1269 send_stream->GetConfig().rtp.extensions[0].name.c_str()); | |
1270 } | |
1271 | |
1272 TEST_F(WebRtcVideoChannel2Test, | |
1273 SetRecvRtpHeaderExtensionsExcludeUnsupportedExtensions) { | |
1274 const int kUnsupportedId = 1; | |
1275 const int kTOffsetId = 2; | |
1276 | |
1277 recv_parameters_.extensions.push_back( | |
1278 cricket::RtpHeaderExtension(kUnsupportedExtensionName, kUnsupportedId)); | |
1279 recv_parameters_.extensions.push_back( | |
1280 cricket::RtpHeaderExtension(webrtc::RtpExtension::kTOffset, kTOffsetId)); | |
1281 EXPECT_TRUE(channel_->SetRecvParameters(recv_parameters_)); | |
1282 FakeVideoReceiveStream* recv_stream = | |
1283 AddRecvStream(cricket::StreamParams::CreateLegacy(123)); | |
1284 | |
1285 // Only timestamp offset extension is set to receive stream, | |
1286 // unsupported rtp extension is ignored. | |
1287 ASSERT_EQ(1u, recv_stream->GetConfig().rtp.extensions.size()); | |
1288 EXPECT_STREQ(webrtc::RtpExtension::kTOffset, | |
1289 recv_stream->GetConfig().rtp.extensions[0].name.c_str()); | |
1290 } | |
1291 | |
1292 TEST_F(WebRtcVideoChannel2Test, SetSendRtpHeaderExtensionsRejectsIncorrectIds) { | |
1293 const int kIncorrectIds[] = {-2, -1, 0, 15, 16}; | |
1294 for (size_t i = 0; i < arraysize(kIncorrectIds); ++i) { | |
1295 send_parameters_.extensions.push_back(cricket::RtpHeaderExtension( | |
1296 webrtc::RtpExtension::kTOffset, kIncorrectIds[i])); | |
1297 EXPECT_FALSE(channel_->SetSendParameters(send_parameters_)) | |
1298 << "Bad extension id '" << kIncorrectIds[i] << "' accepted."; | |
1299 } | |
1300 } | |
1301 | |
1302 TEST_F(WebRtcVideoChannel2Test, SetRecvRtpHeaderExtensionsRejectsIncorrectIds) { | |
1303 const int kIncorrectIds[] = {-2, -1, 0, 15, 16}; | |
1304 for (size_t i = 0; i < arraysize(kIncorrectIds); ++i) { | |
1305 recv_parameters_.extensions.push_back(cricket::RtpHeaderExtension( | |
1306 webrtc::RtpExtension::kTOffset, kIncorrectIds[i])); | |
1307 EXPECT_FALSE(channel_->SetRecvParameters(recv_parameters_)) | |
1308 << "Bad extension id '" << kIncorrectIds[i] << "' accepted."; | |
1309 } | |
1310 } | |
1311 | |
1312 TEST_F(WebRtcVideoChannel2Test, SetSendRtpHeaderExtensionsRejectsDuplicateIds) { | |
1313 const int id = 1; | |
1314 send_parameters_.extensions.push_back( | |
1315 cricket::RtpHeaderExtension(webrtc::RtpExtension::kTOffset, id)); | |
1316 send_parameters_.extensions.push_back( | |
1317 cricket::RtpHeaderExtension(kRtpAbsoluteSenderTimeHeaderExtension, id)); | |
1318 EXPECT_FALSE(channel_->SetSendParameters(send_parameters_)); | |
1319 | |
1320 // Duplicate entries are also not supported. | |
1321 send_parameters_.extensions.clear(); | |
1322 send_parameters_.extensions.push_back( | |
1323 cricket::RtpHeaderExtension(webrtc::RtpExtension::kTOffset, id)); | |
1324 send_parameters_.extensions.push_back(send_parameters_.extensions.back()); | |
1325 EXPECT_FALSE(channel_->SetSendParameters(send_parameters_)); | |
1326 } | |
1327 | |
1328 TEST_F(WebRtcVideoChannel2Test, SetRecvRtpHeaderExtensionsRejectsDuplicateIds) { | |
1329 const int id = 1; | |
1330 recv_parameters_.extensions.push_back( | |
1331 cricket::RtpHeaderExtension(webrtc::RtpExtension::kTOffset, id)); | |
1332 recv_parameters_.extensions.push_back( | |
1333 cricket::RtpHeaderExtension(kRtpAbsoluteSenderTimeHeaderExtension, id)); | |
1334 EXPECT_FALSE(channel_->SetRecvParameters(recv_parameters_)); | |
1335 | |
1336 // Duplicate entries are also not supported. | |
1337 recv_parameters_.extensions.clear(); | |
1338 recv_parameters_.extensions.push_back( | |
1339 cricket::RtpHeaderExtension(webrtc::RtpExtension::kTOffset, id)); | |
1340 recv_parameters_.extensions.push_back(recv_parameters_.extensions.back()); | |
1341 EXPECT_FALSE(channel_->SetRecvParameters(recv_parameters_)); | |
1342 } | |
1343 | |
1344 TEST_F(WebRtcVideoChannel2Test, AddRecvStreamOnlyUsesOneReceiveStream) { | |
1345 EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(1))); | |
1346 EXPECT_EQ(1u, fake_call_->GetVideoReceiveStreams().size()); | |
1347 } | |
1348 | |
1349 TEST_F(WebRtcVideoChannel2Test, RtcpIsCompoundByDefault) { | |
1350 FakeVideoReceiveStream* stream = AddRecvStream(); | |
1351 EXPECT_EQ(webrtc::RtcpMode::kCompound, stream->GetConfig().rtp.rtcp_mode); | |
1352 } | |
1353 | |
1354 TEST_F(WebRtcVideoChannel2Test, RembIsEnabledByDefault) { | |
1355 FakeVideoReceiveStream* stream = AddRecvStream(); | |
1356 EXPECT_TRUE(stream->GetConfig().rtp.remb); | |
1357 } | |
1358 | |
1359 TEST_F(WebRtcVideoChannel2Test, TransportCcIsEnabledByDefault) { | |
1360 FakeVideoReceiveStream* stream = AddRecvStream(); | |
1361 EXPECT_TRUE(stream->GetConfig().rtp.transport_cc); | |
1362 } | |
1363 | |
1364 TEST_F(WebRtcVideoChannel2Test, RembCanBeEnabledAndDisabled) { | |
1365 FakeVideoReceiveStream* stream = AddRecvStream(); | |
1366 EXPECT_TRUE(stream->GetConfig().rtp.remb); | |
1367 | |
1368 // Verify that REMB is turned off when send(!) codecs without REMB are set. | |
1369 cricket::VideoSendParameters parameters; | |
1370 parameters.codecs.push_back(kVp8Codec); | |
1371 EXPECT_TRUE(parameters.codecs[0].feedback_params.params().empty()); | |
1372 EXPECT_TRUE(channel_->SetSendParameters(parameters)); | |
1373 stream = fake_call_->GetVideoReceiveStreams()[0]; | |
1374 EXPECT_FALSE(stream->GetConfig().rtp.remb); | |
1375 | |
1376 // Verify that REMB is turned on when setting default codecs since the | |
1377 // default codecs have REMB enabled. | |
1378 parameters.codecs = engine_.codecs(); | |
1379 EXPECT_TRUE(channel_->SetSendParameters(parameters)); | |
1380 stream = fake_call_->GetVideoReceiveStreams()[0]; | |
1381 EXPECT_TRUE(stream->GetConfig().rtp.remb); | |
1382 } | |
1383 | |
1384 TEST_F(WebRtcVideoChannel2Test, TransportCcCanBeEnabledAndDisabled) { | |
1385 FakeVideoReceiveStream* stream = AddRecvStream(); | |
1386 EXPECT_TRUE(stream->GetConfig().rtp.transport_cc); | |
1387 | |
1388 // Verify that transport cc feedback is turned off when send(!) codecs without | |
1389 // transport cc feedback are set. | |
1390 cricket::VideoSendParameters parameters; | |
1391 parameters.codecs.push_back(kVp8Codec); | |
1392 EXPECT_TRUE(parameters.codecs[0].feedback_params.params().empty()); | |
1393 EXPECT_TRUE(channel_->SetSendParameters(parameters)); | |
1394 stream = fake_call_->GetVideoReceiveStreams()[0]; | |
1395 EXPECT_FALSE(stream->GetConfig().rtp.transport_cc); | |
1396 | |
1397 // Verify that transport cc feedback is turned on when setting default codecs | |
1398 // since the default codecs have transport cc feedback enabled. | |
1399 parameters.codecs = engine_.codecs(); | |
1400 EXPECT_TRUE(channel_->SetSendParameters(parameters)); | |
1401 stream = fake_call_->GetVideoReceiveStreams()[0]; | |
1402 EXPECT_TRUE(stream->GetConfig().rtp.transport_cc); | |
1403 } | |
1404 | |
1405 TEST_F(WebRtcVideoChannel2Test, NackIsEnabledByDefault) { | |
1406 VerifyCodecHasDefaultFeedbackParams(default_codec_); | |
1407 | |
1408 cricket::VideoSendParameters parameters; | |
1409 parameters.codecs = engine_.codecs(); | |
1410 EXPECT_TRUE(channel_->SetSendParameters(parameters)); | |
1411 EXPECT_TRUE(channel_->SetSend(true)); | |
1412 | |
1413 // Send side. | |
1414 FakeVideoSendStream* send_stream = | |
1415 AddSendStream(cricket::StreamParams::CreateLegacy(1)); | |
1416 EXPECT_GT(send_stream->GetConfig().rtp.nack.rtp_history_ms, 0); | |
1417 | |
1418 // Receiver side. | |
1419 FakeVideoReceiveStream* recv_stream = | |
1420 AddRecvStream(cricket::StreamParams::CreateLegacy(1)); | |
1421 EXPECT_GT(recv_stream->GetConfig().rtp.nack.rtp_history_ms, 0); | |
1422 | |
1423 // Nack history size should match between sender and receiver. | |
1424 EXPECT_EQ(send_stream->GetConfig().rtp.nack.rtp_history_ms, | |
1425 recv_stream->GetConfig().rtp.nack.rtp_history_ms); | |
1426 } | |
1427 | |
1428 TEST_F(WebRtcVideoChannel2Test, NackCanBeEnabledAndDisabled) { | |
1429 FakeVideoSendStream* send_stream = AddSendStream(); | |
1430 FakeVideoReceiveStream* recv_stream = AddRecvStream(); | |
1431 | |
1432 EXPECT_GT(recv_stream->GetConfig().rtp.nack.rtp_history_ms, 0); | |
1433 EXPECT_GT(send_stream->GetConfig().rtp.nack.rtp_history_ms, 0); | |
1434 | |
1435 // Verify that NACK is turned off when send(!) codecs without NACK are set. | |
1436 cricket::VideoSendParameters parameters; | |
1437 parameters.codecs.push_back(kVp8Codec); | |
1438 EXPECT_TRUE(parameters.codecs[0].feedback_params.params().empty()); | |
1439 EXPECT_TRUE(channel_->SetSendParameters(parameters)); | |
1440 recv_stream = fake_call_->GetVideoReceiveStreams()[0]; | |
1441 EXPECT_EQ(0, recv_stream->GetConfig().rtp.nack.rtp_history_ms); | |
1442 send_stream = fake_call_->GetVideoSendStreams()[0]; | |
1443 EXPECT_EQ(0, send_stream->GetConfig().rtp.nack.rtp_history_ms); | |
1444 | |
1445 // Verify that NACK is turned on when setting default codecs since the | |
1446 // default codecs have NACK enabled. | |
1447 parameters.codecs = engine_.codecs(); | |
1448 EXPECT_TRUE(channel_->SetSendParameters(parameters)); | |
1449 recv_stream = fake_call_->GetVideoReceiveStreams()[0]; | |
1450 EXPECT_GT(recv_stream->GetConfig().rtp.nack.rtp_history_ms, 0); | |
1451 send_stream = fake_call_->GetVideoSendStreams()[0]; | |
1452 EXPECT_GT(send_stream->GetConfig().rtp.nack.rtp_history_ms, 0); | |
1453 } | |
1454 | |
1455 TEST_F(WebRtcVideoChannel2Test, UsesCorrectSettingsForScreencast) { | |
1456 static const int kScreenshareMinBitrateKbps = 800; | |
1457 cricket::VideoCodec codec = kVp8Codec360p; | |
1458 cricket::VideoSendParameters parameters; | |
1459 parameters.codecs.push_back(codec); | |
1460 parameters.options.screencast_min_bitrate_kbps = | |
1461 rtc::Optional<int>(kScreenshareMinBitrateKbps); | |
1462 EXPECT_TRUE(channel_->SetSendParameters(parameters)); | |
1463 | |
1464 AddSendStream(); | |
1465 | |
1466 cricket::FakeVideoCapturer capturer; | |
1467 capturer.SetScreencast(false); | |
1468 EXPECT_TRUE(channel_->SetCapturer(last_ssrc_, &capturer)); | |
1469 cricket::VideoFormat capture_format_hd = | |
1470 capturer.GetSupportedFormats()->front(); | |
1471 EXPECT_EQ(1280, capture_format_hd.width); | |
1472 EXPECT_EQ(720, capture_format_hd.height); | |
1473 EXPECT_EQ(cricket::CS_RUNNING, capturer.Start(capture_format_hd)); | |
1474 | |
1475 EXPECT_TRUE(channel_->SetSend(true)); | |
1476 | |
1477 EXPECT_TRUE(capturer.CaptureFrame()); | |
1478 ASSERT_EQ(1u, fake_call_->GetVideoSendStreams().size()); | |
1479 FakeVideoSendStream* send_stream = fake_call_->GetVideoSendStreams().front(); | |
1480 | |
1481 EXPECT_EQ(1, send_stream->GetNumberOfSwappedFrames()); | |
1482 | |
1483 // Verify non-screencast settings. | |
1484 webrtc::VideoEncoderConfig encoder_config = send_stream->GetEncoderConfig(); | |
1485 EXPECT_EQ(webrtc::VideoEncoderConfig::ContentType::kRealtimeVideo, | |
1486 encoder_config.content_type); | |
1487 EXPECT_EQ(codec.width, encoder_config.streams.front().width); | |
1488 EXPECT_EQ(codec.height, encoder_config.streams.front().height); | |
1489 EXPECT_EQ(0, encoder_config.min_transmit_bitrate_bps) | |
1490 << "Non-screenshare shouldn't use min-transmit bitrate."; | |
1491 | |
1492 capturer.SetScreencast(true); | |
1493 EXPECT_TRUE(capturer.CaptureFrame()); | |
1494 | |
1495 EXPECT_EQ(2, send_stream->GetNumberOfSwappedFrames()); | |
1496 | |
1497 // Verify screencast settings. | |
1498 encoder_config = send_stream->GetEncoderConfig(); | |
1499 EXPECT_EQ(webrtc::VideoEncoderConfig::ContentType::kScreen, | |
1500 encoder_config.content_type); | |
1501 EXPECT_EQ(kScreenshareMinBitrateKbps * 1000, | |
1502 encoder_config.min_transmit_bitrate_bps); | |
1503 | |
1504 EXPECT_EQ(capture_format_hd.width, encoder_config.streams.front().width); | |
1505 EXPECT_EQ(capture_format_hd.height, encoder_config.streams.front().height); | |
1506 EXPECT_TRUE(encoder_config.streams[0].temporal_layer_thresholds_bps.empty()); | |
1507 | |
1508 EXPECT_TRUE(channel_->SetCapturer(last_ssrc_, NULL)); | |
1509 } | |
1510 | |
1511 TEST_F(WebRtcVideoChannel2Test, | |
1512 ConferenceModeScreencastConfiguresTemporalLayer) { | |
1513 static const int kConferenceScreencastTemporalBitrateBps = | |
1514 ScreenshareLayerConfig::GetDefault().tl0_bitrate_kbps * 1000; | |
1515 send_parameters_.options.conference_mode = rtc::Optional<bool>(true); | |
1516 channel_->SetSendParameters(send_parameters_); | |
1517 | |
1518 AddSendStream(); | |
1519 | |
1520 cricket::FakeVideoCapturer capturer; | |
1521 capturer.SetScreencast(true); | |
1522 EXPECT_TRUE(channel_->SetCapturer(last_ssrc_, &capturer)); | |
1523 cricket::VideoFormat capture_format_hd = | |
1524 capturer.GetSupportedFormats()->front(); | |
1525 EXPECT_EQ(cricket::CS_RUNNING, capturer.Start(capture_format_hd)); | |
1526 | |
1527 EXPECT_TRUE(channel_->SetSend(true)); | |
1528 | |
1529 EXPECT_TRUE(capturer.CaptureFrame()); | |
1530 ASSERT_EQ(1u, fake_call_->GetVideoSendStreams().size()); | |
1531 FakeVideoSendStream* send_stream = fake_call_->GetVideoSendStreams().front(); | |
1532 | |
1533 webrtc::VideoEncoderConfig encoder_config = send_stream->GetEncoderConfig(); | |
1534 | |
1535 // Verify screencast settings. | |
1536 encoder_config = send_stream->GetEncoderConfig(); | |
1537 EXPECT_EQ(webrtc::VideoEncoderConfig::ContentType::kScreen, | |
1538 encoder_config.content_type); | |
1539 ASSERT_EQ(1u, encoder_config.streams.size()); | |
1540 ASSERT_EQ(1u, encoder_config.streams[0].temporal_layer_thresholds_bps.size()); | |
1541 EXPECT_EQ(kConferenceScreencastTemporalBitrateBps, | |
1542 encoder_config.streams[0].temporal_layer_thresholds_bps[0]); | |
1543 | |
1544 EXPECT_TRUE(channel_->SetCapturer(last_ssrc_, NULL)); | |
1545 } | |
1546 | |
1547 TEST_F(WebRtcVideoChannel2Test, SuspendBelowMinBitrateDisabledByDefault) { | |
1548 FakeVideoSendStream* stream = AddSendStream(); | |
1549 EXPECT_FALSE(stream->GetConfig().suspend_below_min_bitrate); | |
1550 } | |
1551 | |
1552 TEST_F(WebRtcVideoChannel2Test, SetOptionsWithSuspendBelowMinBitrate) { | |
1553 send_parameters_.options.suspend_below_min_bitrate = | |
1554 rtc::Optional<bool>(true); | |
1555 channel_->SetSendParameters(send_parameters_); | |
1556 | |
1557 FakeVideoSendStream* stream = AddSendStream(); | |
1558 EXPECT_TRUE(stream->GetConfig().suspend_below_min_bitrate); | |
1559 | |
1560 send_parameters_.options.suspend_below_min_bitrate = | |
1561 rtc::Optional<bool>(false); | |
1562 channel_->SetSendParameters(send_parameters_); | |
1563 | |
1564 stream = fake_call_->GetVideoSendStreams()[0]; | |
1565 EXPECT_FALSE(stream->GetConfig().suspend_below_min_bitrate); | |
1566 } | |
1567 | |
1568 TEST_F(WebRtcVideoChannel2Test, Vp8DenoisingEnabledByDefault) { | |
1569 FakeVideoSendStream* stream = AddSendStream(); | |
1570 webrtc::VideoCodecVP8 vp8_settings; | |
1571 ASSERT_TRUE(stream->GetVp8Settings(&vp8_settings)) << "No VP8 config set."; | |
1572 EXPECT_TRUE(vp8_settings.denoisingOn); | |
1573 } | |
1574 | |
1575 TEST_F(WebRtcVideoChannel2Test, VerifyVp8SpecificSettings) { | |
1576 cricket::VideoSendParameters parameters; | |
1577 parameters.codecs.push_back(kVp8Codec720p); | |
1578 ASSERT_TRUE(channel_->SetSendParameters(parameters)); | |
1579 | |
1580 // Single-stream settings should apply with RTX as well (verifies that we | |
1581 // check number of regular SSRCs and not StreamParams::ssrcs which contains | |
1582 // both RTX and regular SSRCs). | |
1583 FakeVideoSendStream* stream = SetUpSimulcast(false, true); | |
1584 | |
1585 cricket::FakeVideoCapturer capturer; | |
1586 capturer.SetScreencast(false); | |
1587 EXPECT_EQ(cricket::CS_RUNNING, | |
1588 capturer.Start(capturer.GetSupportedFormats()->front())); | |
1589 EXPECT_TRUE(channel_->SetCapturer(last_ssrc_, &capturer)); | |
1590 channel_->SetSend(true); | |
1591 | |
1592 EXPECT_TRUE(capturer.CaptureFrame()); | |
1593 | |
1594 webrtc::VideoCodecVP8 vp8_settings; | |
1595 ASSERT_TRUE(stream->GetVp8Settings(&vp8_settings)) << "No VP8 config set."; | |
1596 EXPECT_TRUE(vp8_settings.denoisingOn) | |
1597 << "VP8 denoising should be on by default."; | |
1598 | |
1599 stream = SetDenoisingOption(parameters, false); | |
1600 | |
1601 ASSERT_TRUE(stream->GetVp8Settings(&vp8_settings)) << "No VP8 config set."; | |
1602 EXPECT_FALSE(vp8_settings.denoisingOn); | |
1603 EXPECT_TRUE(vp8_settings.automaticResizeOn); | |
1604 EXPECT_TRUE(vp8_settings.frameDroppingOn); | |
1605 | |
1606 stream = SetDenoisingOption(parameters, true); | |
1607 | |
1608 ASSERT_TRUE(stream->GetVp8Settings(&vp8_settings)) << "No VP8 config set."; | |
1609 EXPECT_TRUE(vp8_settings.denoisingOn); | |
1610 EXPECT_TRUE(vp8_settings.automaticResizeOn); | |
1611 EXPECT_TRUE(vp8_settings.frameDroppingOn); | |
1612 | |
1613 EXPECT_TRUE(channel_->SetCapturer(last_ssrc_, NULL)); | |
1614 stream = SetUpSimulcast(true, false); | |
1615 EXPECT_TRUE(channel_->SetCapturer(last_ssrc_, &capturer)); | |
1616 channel_->SetSend(true); | |
1617 EXPECT_TRUE(capturer.CaptureFrame()); | |
1618 | |
1619 EXPECT_EQ(3, stream->GetVideoStreams().size()); | |
1620 ASSERT_TRUE(stream->GetVp8Settings(&vp8_settings)) << "No VP8 config set."; | |
1621 // Autmatic resize off when using simulcast. | |
1622 EXPECT_FALSE(vp8_settings.automaticResizeOn); | |
1623 EXPECT_TRUE(vp8_settings.frameDroppingOn); | |
1624 | |
1625 // In screen-share mode, denoising is forced off and simulcast disabled. | |
1626 capturer.SetScreencast(true); | |
1627 EXPECT_TRUE(capturer.CaptureFrame()); | |
1628 stream = SetDenoisingOption(parameters, false); | |
1629 | |
1630 EXPECT_EQ(1, stream->GetVideoStreams().size()); | |
1631 ASSERT_TRUE(stream->GetVp8Settings(&vp8_settings)) << "No VP8 config set."; | |
1632 EXPECT_FALSE(vp8_settings.denoisingOn); | |
1633 // Resizing and frame dropping always off for screen sharing. | |
1634 EXPECT_FALSE(vp8_settings.automaticResizeOn); | |
1635 EXPECT_FALSE(vp8_settings.frameDroppingOn); | |
1636 | |
1637 stream = SetDenoisingOption(parameters, true); | |
1638 | |
1639 ASSERT_TRUE(stream->GetVp8Settings(&vp8_settings)) << "No VP8 config set."; | |
1640 EXPECT_FALSE(vp8_settings.denoisingOn); | |
1641 EXPECT_FALSE(vp8_settings.automaticResizeOn); | |
1642 EXPECT_FALSE(vp8_settings.frameDroppingOn); | |
1643 | |
1644 EXPECT_TRUE(channel_->SetCapturer(last_ssrc_, NULL)); | |
1645 } | |
1646 | |
1647 class Vp9SettingsTest : public WebRtcVideoChannel2Test { | |
1648 public: | |
1649 Vp9SettingsTest() : WebRtcVideoChannel2Test() { | |
1650 encoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecVP9, "VP9"); | |
1651 } | |
1652 virtual ~Vp9SettingsTest() {} | |
1653 | |
1654 protected: | |
1655 void SetUp() override { | |
1656 engine_.SetExternalEncoderFactory(&encoder_factory_); | |
1657 | |
1658 WebRtcVideoChannel2Test::SetUp(); | |
1659 } | |
1660 | |
1661 void TearDown() override { | |
1662 // Remove references to encoder_factory_ since this will be destroyed | |
1663 // before channel_ and engine_. | |
1664 ASSERT_TRUE(channel_->SetSendParameters(send_parameters_)); | |
1665 } | |
1666 | |
1667 cricket::FakeWebRtcVideoEncoderFactory encoder_factory_; | |
1668 }; | |
1669 | |
1670 TEST_F(Vp9SettingsTest, VerifyVp9SpecificSettings) { | |
1671 cricket::VideoSendParameters parameters; | |
1672 parameters.codecs.push_back(kVp9Codec); | |
1673 ASSERT_TRUE(channel_->SetSendParameters(parameters)); | |
1674 | |
1675 FakeVideoSendStream* stream = SetUpSimulcast(false, false); | |
1676 | |
1677 cricket::FakeVideoCapturer capturer; | |
1678 capturer.SetScreencast(false); | |
1679 EXPECT_EQ(cricket::CS_RUNNING, | |
1680 capturer.Start(capturer.GetSupportedFormats()->front())); | |
1681 EXPECT_TRUE(channel_->SetCapturer(last_ssrc_, &capturer)); | |
1682 channel_->SetSend(true); | |
1683 | |
1684 EXPECT_TRUE(capturer.CaptureFrame()); | |
1685 | |
1686 webrtc::VideoCodecVP9 vp9_settings; | |
1687 ASSERT_TRUE(stream->GetVp9Settings(&vp9_settings)) << "No VP9 config set."; | |
1688 EXPECT_FALSE(vp9_settings.denoisingOn) | |
1689 << "VP9 denoising should be off by default."; | |
1690 | |
1691 stream = SetDenoisingOption(parameters, false); | |
1692 | |
1693 ASSERT_TRUE(stream->GetVp9Settings(&vp9_settings)) << "No VP9 config set."; | |
1694 EXPECT_FALSE(vp9_settings.denoisingOn); | |
1695 // Frame dropping always on for real time video. | |
1696 EXPECT_TRUE(vp9_settings.frameDroppingOn); | |
1697 | |
1698 stream = SetDenoisingOption(parameters, true); | |
1699 | |
1700 ASSERT_TRUE(stream->GetVp9Settings(&vp9_settings)) << "No VP9 config set."; | |
1701 EXPECT_TRUE(vp9_settings.denoisingOn); | |
1702 EXPECT_TRUE(vp9_settings.frameDroppingOn); | |
1703 | |
1704 // In screen-share mode, denoising is forced off. | |
1705 capturer.SetScreencast(true); | |
1706 EXPECT_TRUE(capturer.CaptureFrame()); | |
1707 stream = SetDenoisingOption(parameters, false); | |
1708 | |
1709 ASSERT_TRUE(stream->GetVp9Settings(&vp9_settings)) << "No VP9 config set."; | |
1710 EXPECT_FALSE(vp9_settings.denoisingOn); | |
1711 // Frame dropping always off for screen sharing. | |
1712 EXPECT_FALSE(vp9_settings.frameDroppingOn); | |
1713 | |
1714 stream = SetDenoisingOption(parameters, false); | |
1715 | |
1716 ASSERT_TRUE(stream->GetVp9Settings(&vp9_settings)) << "No VP9 config set."; | |
1717 EXPECT_FALSE(vp9_settings.denoisingOn); | |
1718 EXPECT_FALSE(vp9_settings.frameDroppingOn); | |
1719 | |
1720 EXPECT_TRUE(channel_->SetCapturer(last_ssrc_, NULL)); | |
1721 } | |
1722 | |
1723 TEST_F(WebRtcVideoChannel2Test, AdaptsOnOveruse) { | |
1724 TestCpuAdaptation(true, false); | |
1725 } | |
1726 | |
1727 TEST_F(WebRtcVideoChannel2Test, DoesNotAdaptOnOveruseWhenDisabled) { | |
1728 TestCpuAdaptation(false, false); | |
1729 } | |
1730 | |
1731 TEST_F(WebRtcVideoChannel2Test, DoesNotAdaptOnOveruseWhenScreensharing) { | |
1732 TestCpuAdaptation(true, true); | |
1733 } | |
1734 | |
1735 void WebRtcVideoChannel2Test::TestCpuAdaptation(bool enable_overuse, | |
1736 bool is_screenshare) { | |
1737 cricket::VideoCodec codec = kVp8Codec720p; | |
1738 cricket::VideoSendParameters parameters; | |
1739 parameters.codecs.push_back(codec); | |
1740 if (!enable_overuse) { | |
1741 parameters.options.cpu_overuse_detection = rtc::Optional<bool>(false); | |
1742 } | |
1743 EXPECT_TRUE(channel_->SetSendParameters(parameters)); | |
1744 | |
1745 AddSendStream(); | |
1746 | |
1747 cricket::FakeVideoCapturer capturer; | |
1748 capturer.SetScreencast(is_screenshare); | |
1749 EXPECT_TRUE(channel_->SetCapturer(last_ssrc_, &capturer)); | |
1750 EXPECT_EQ(cricket::CS_RUNNING, | |
1751 capturer.Start(capturer.GetSupportedFormats()->front())); | |
1752 | |
1753 EXPECT_TRUE(channel_->SetSend(true)); | |
1754 | |
1755 // Trigger overuse. | |
1756 ASSERT_EQ(1u, fake_call_->GetVideoSendStreams().size()); | |
1757 FakeVideoSendStream* send_stream = fake_call_->GetVideoSendStreams().front(); | |
1758 webrtc::LoadObserver* overuse_callback = | |
1759 send_stream->GetConfig().overuse_callback; | |
1760 ASSERT_TRUE(overuse_callback != NULL); | |
1761 overuse_callback->OnLoadUpdate(webrtc::LoadObserver::kOveruse); | |
1762 | |
1763 EXPECT_TRUE(capturer.CaptureFrame()); | |
1764 EXPECT_EQ(1, send_stream->GetNumberOfSwappedFrames()); | |
1765 | |
1766 if (enable_overuse && !is_screenshare) { | |
1767 EXPECT_LT(send_stream->GetLastWidth(), codec.width); | |
1768 EXPECT_LT(send_stream->GetLastHeight(), codec.height); | |
1769 } else { | |
1770 EXPECT_EQ(codec.width, send_stream->GetLastWidth()); | |
1771 EXPECT_EQ(codec.height, send_stream->GetLastHeight()); | |
1772 } | |
1773 | |
1774 // Trigger underuse which should go back to normal resolution. | |
1775 overuse_callback->OnLoadUpdate(webrtc::LoadObserver::kUnderuse); | |
1776 EXPECT_TRUE(capturer.CaptureFrame()); | |
1777 | |
1778 EXPECT_EQ(2, send_stream->GetNumberOfSwappedFrames()); | |
1779 | |
1780 EXPECT_EQ(codec.width, send_stream->GetLastWidth()); | |
1781 EXPECT_EQ(codec.height, send_stream->GetLastHeight()); | |
1782 | |
1783 EXPECT_TRUE(channel_->SetCapturer(last_ssrc_, NULL)); | |
1784 } | |
1785 | |
1786 TEST_F(WebRtcVideoChannel2Test, EstimatesNtpStartTimeCorrectly) { | |
1787 // Start at last timestamp to verify that wraparounds are estimated correctly. | |
1788 static const uint32_t kInitialTimestamp = 0xFFFFFFFFu; | |
1789 static const int64_t kInitialNtpTimeMs = 1247891230; | |
1790 static const int kFrameOffsetMs = 20; | |
1791 EXPECT_TRUE(channel_->SetRecvParameters(recv_parameters_)); | |
1792 | |
1793 FakeVideoReceiveStream* stream = AddRecvStream(); | |
1794 cricket::FakeVideoRenderer renderer; | |
1795 EXPECT_TRUE(channel_->SetSink(last_ssrc_, &renderer)); | |
1796 | |
1797 webrtc::VideoFrame video_frame; | |
1798 CreateBlackFrame(&video_frame, 4, 4); | |
1799 video_frame.set_timestamp(kInitialTimestamp); | |
1800 // Initial NTP time is not available on the first frame, but should still be | |
1801 // able to be estimated. | |
1802 stream->InjectFrame(video_frame, 0); | |
1803 | |
1804 EXPECT_EQ(1, renderer.num_rendered_frames()); | |
1805 | |
1806 // This timestamp is kInitialTimestamp (-1) + kFrameOffsetMs * 90, which | |
1807 // triggers a constant-overflow warning, hence we're calculating it explicitly | |
1808 // here. | |
1809 video_frame.set_timestamp(kFrameOffsetMs * 90 - 1); | |
1810 video_frame.set_ntp_time_ms(kInitialNtpTimeMs + kFrameOffsetMs); | |
1811 stream->InjectFrame(video_frame, 0); | |
1812 | |
1813 EXPECT_EQ(2, renderer.num_rendered_frames()); | |
1814 | |
1815 // Verify that NTP time has been correctly deduced. | |
1816 cricket::VideoMediaInfo info; | |
1817 ASSERT_TRUE(channel_->GetStats(&info)); | |
1818 ASSERT_EQ(1u, info.receivers.size()); | |
1819 EXPECT_EQ(kInitialNtpTimeMs, info.receivers[0].capture_start_ntp_time_ms); | |
1820 } | |
1821 | |
1822 TEST_F(WebRtcVideoChannel2Test, SetDefaultSendCodecs) { | |
1823 ASSERT_TRUE(channel_->SetSendParameters(send_parameters_)); | |
1824 | |
1825 VideoCodec codec; | |
1826 EXPECT_TRUE(channel_->GetSendCodec(&codec)); | |
1827 EXPECT_TRUE(codec.Matches(engine_.codecs()[0])); | |
1828 | |
1829 // Using a RTX setup to verify that the default RTX payload type is good. | |
1830 const std::vector<uint32_t> ssrcs = MAKE_VECTOR(kSsrcs1); | |
1831 const std::vector<uint32_t> rtx_ssrcs = MAKE_VECTOR(kRtxSsrcs1); | |
1832 FakeVideoSendStream* stream = AddSendStream( | |
1833 cricket::CreateSimWithRtxStreamParams("cname", ssrcs, rtx_ssrcs)); | |
1834 webrtc::VideoSendStream::Config config = stream->GetConfig(); | |
1835 | |
1836 // Make sure NACK and FEC are enabled on the correct payload types. | |
1837 EXPECT_EQ(1000, config.rtp.nack.rtp_history_ms); | |
1838 EXPECT_EQ(default_ulpfec_codec_.id, config.rtp.fec.ulpfec_payload_type); | |
1839 EXPECT_EQ(default_red_codec_.id, config.rtp.fec.red_payload_type); | |
1840 | |
1841 EXPECT_EQ(1u, config.rtp.rtx.ssrcs.size()); | |
1842 EXPECT_EQ(kRtxSsrcs1[0], config.rtp.rtx.ssrcs[0]); | |
1843 VerifySendStreamHasRtxTypes(config, default_apt_rtx_types_); | |
1844 // TODO(juberti): Check RTCP, PLI, TMMBR. | |
1845 } | |
1846 | |
1847 TEST_F(WebRtcVideoChannel2Test, SetSendCodecsWithoutFec) { | |
1848 cricket::VideoSendParameters parameters; | |
1849 parameters.codecs.push_back(kVp8Codec); | |
1850 ASSERT_TRUE(channel_->SetSendParameters(parameters)); | |
1851 | |
1852 FakeVideoSendStream* stream = AddSendStream(); | |
1853 webrtc::VideoSendStream::Config config = stream->GetConfig(); | |
1854 | |
1855 EXPECT_EQ(-1, config.rtp.fec.ulpfec_payload_type); | |
1856 EXPECT_EQ(-1, config.rtp.fec.red_payload_type); | |
1857 } | |
1858 | |
1859 TEST_F(WebRtcVideoChannel2Test, | |
1860 SetSendCodecRejectsRtxWithoutAssociatedPayloadType) { | |
1861 cricket::VideoSendParameters parameters; | |
1862 cricket::VideoCodec rtx_codec(96, "rtx", 0, 0, 0, 0); | |
1863 parameters.codecs.push_back(rtx_codec); | |
1864 EXPECT_FALSE(channel_->SetSendParameters(parameters)) | |
1865 << "RTX codec without associated payload type should be rejected."; | |
1866 } | |
1867 | |
1868 TEST_F(WebRtcVideoChannel2Test, | |
1869 SetSendCodecRejectsRtxWithoutMatchingVideoCodec) { | |
1870 cricket::VideoSendParameters parameters; | |
1871 cricket::VideoCodec rtx_codec = | |
1872 cricket::VideoCodec::CreateRtxCodec(96, kVp8Codec.id); | |
1873 parameters.codecs.push_back(kVp8Codec); | |
1874 parameters.codecs.push_back(rtx_codec); | |
1875 ASSERT_TRUE(channel_->SetSendParameters(parameters)); | |
1876 | |
1877 cricket::VideoCodec rtx_codec2 = | |
1878 cricket::VideoCodec::CreateRtxCodec(96, kVp8Codec.id + 1); | |
1879 parameters.codecs.pop_back(); | |
1880 parameters.codecs.push_back(rtx_codec2); | |
1881 EXPECT_FALSE(channel_->SetSendParameters(parameters)) | |
1882 << "RTX without matching video codec should be rejected."; | |
1883 } | |
1884 | |
1885 TEST_F(WebRtcVideoChannel2Test, SetSendCodecsWithoutFecDisablesFec) { | |
1886 cricket::VideoSendParameters parameters; | |
1887 parameters.codecs.push_back(kVp8Codec); | |
1888 parameters.codecs.push_back(kUlpfecCodec); | |
1889 ASSERT_TRUE(channel_->SetSendParameters(parameters)); | |
1890 | |
1891 FakeVideoSendStream* stream = AddSendStream(); | |
1892 webrtc::VideoSendStream::Config config = stream->GetConfig(); | |
1893 | |
1894 EXPECT_EQ(kUlpfecCodec.id, config.rtp.fec.ulpfec_payload_type); | |
1895 | |
1896 parameters.codecs.pop_back(); | |
1897 ASSERT_TRUE(channel_->SetSendParameters(parameters)); | |
1898 stream = fake_call_->GetVideoSendStreams()[0]; | |
1899 ASSERT_TRUE(stream != NULL); | |
1900 config = stream->GetConfig(); | |
1901 EXPECT_EQ(-1, config.rtp.fec.ulpfec_payload_type) | |
1902 << "SetSendCodec without FEC should disable current FEC."; | |
1903 } | |
1904 | |
1905 TEST_F(WebRtcVideoChannel2Test, SetSendCodecsChangesExistingStreams) { | |
1906 cricket::VideoSendParameters parameters; | |
1907 parameters.codecs.push_back(kVp8Codec720p); | |
1908 ASSERT_TRUE(channel_->SetSendParameters(parameters)); | |
1909 channel_->SetSend(true); | |
1910 | |
1911 FakeVideoSendStream* stream = AddSendStream(); | |
1912 | |
1913 cricket::FakeVideoCapturer capturer; | |
1914 EXPECT_TRUE(channel_->SetCapturer(last_ssrc_, &capturer)); | |
1915 EXPECT_EQ(cricket::CS_RUNNING, | |
1916 capturer.Start(capturer.GetSupportedFormats()->front())); | |
1917 EXPECT_TRUE(capturer.CaptureFrame()); | |
1918 | |
1919 std::vector<webrtc::VideoStream> streams = stream->GetVideoStreams(); | |
1920 EXPECT_EQ(kVp8Codec720p.width, streams[0].width); | |
1921 EXPECT_EQ(kVp8Codec720p.height, streams[0].height); | |
1922 | |
1923 parameters.codecs.clear(); | |
1924 parameters.codecs.push_back(kVp8Codec360p); | |
1925 ASSERT_TRUE(channel_->SetSendParameters(parameters)); | |
1926 streams = fake_call_->GetVideoSendStreams()[0]->GetVideoStreams(); | |
1927 EXPECT_EQ(kVp8Codec360p.width, streams[0].width); | |
1928 EXPECT_EQ(kVp8Codec360p.height, streams[0].height); | |
1929 EXPECT_TRUE(channel_->SetCapturer(last_ssrc_, NULL)); | |
1930 } | |
1931 | |
1932 TEST_F(WebRtcVideoChannel2Test, SetSendCodecsWithBitrates) { | |
1933 SetSendCodecsShouldWorkForBitrates("100", 100000, "150", 150000, "200", | |
1934 200000); | |
1935 } | |
1936 | |
1937 TEST_F(WebRtcVideoChannel2Test, SetSendCodecsWithHighMaxBitrate) { | |
1938 SetSendCodecsShouldWorkForBitrates("", 0, "", -1, "10000", 10000000); | |
1939 std::vector<webrtc::VideoStream> streams = AddSendStream()->GetVideoStreams(); | |
1940 ASSERT_EQ(1u, streams.size()); | |
1941 EXPECT_EQ(10000000, streams[0].max_bitrate_bps); | |
1942 } | |
1943 | |
1944 TEST_F(WebRtcVideoChannel2Test, | |
1945 SetSendCodecsWithoutBitratesUsesCorrectDefaults) { | |
1946 SetSendCodecsShouldWorkForBitrates( | |
1947 "", 0, "", -1, "", -1); | |
1948 } | |
1949 | |
1950 TEST_F(WebRtcVideoChannel2Test, SetSendCodecsCapsMinAndStartBitrate) { | |
1951 SetSendCodecsShouldWorkForBitrates("-1", 0, "-100", -1, "", -1); | |
1952 } | |
1953 | |
1954 TEST_F(WebRtcVideoChannel2Test, SetSendCodecsRejectsMaxLessThanMinBitrate) { | |
1955 send_parameters_.codecs[0].params[kCodecParamMinBitrate] = "300"; | |
1956 send_parameters_.codecs[0].params[kCodecParamMaxBitrate] = "200"; | |
1957 EXPECT_FALSE(channel_->SetSendParameters(send_parameters_)); | |
1958 } | |
1959 | |
1960 TEST_F(WebRtcVideoChannel2Test, | |
1961 SetMaxSendBandwidthShouldPreserveOtherBitrates) { | |
1962 SetSendCodecsShouldWorkForBitrates("100", 100000, "150", 150000, "200", | |
1963 200000); | |
1964 send_parameters_.max_bandwidth_bps = 300000; | |
1965 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_)); | |
1966 EXPECT_EQ(100000, fake_call_->GetConfig().bitrate_config.min_bitrate_bps) | |
1967 << "Setting max bitrate should keep previous min bitrate."; | |
1968 EXPECT_EQ(-1, fake_call_->GetConfig().bitrate_config.start_bitrate_bps) | |
1969 << "Setting max bitrate should not reset start bitrate."; | |
1970 EXPECT_EQ(300000, fake_call_->GetConfig().bitrate_config.max_bitrate_bps); | |
1971 } | |
1972 | |
1973 TEST_F(WebRtcVideoChannel2Test, SetMaxSendBandwidthShouldBeRemovable) { | |
1974 send_parameters_.max_bandwidth_bps = 300000; | |
1975 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_)); | |
1976 EXPECT_EQ(300000, fake_call_->GetConfig().bitrate_config.max_bitrate_bps); | |
1977 // <= 0 means disable (infinite) max bitrate. | |
1978 send_parameters_.max_bandwidth_bps = 0; | |
1979 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_)); | |
1980 EXPECT_EQ(-1, fake_call_->GetConfig().bitrate_config.max_bitrate_bps) | |
1981 << "Setting zero max bitrate did not reset start bitrate."; | |
1982 } | |
1983 | |
1984 TEST_F(WebRtcVideoChannel2Test, SetMaxSendBitrateCanIncreaseSenderBitrate) { | |
1985 cricket::VideoSendParameters parameters; | |
1986 parameters.codecs.push_back(kVp8Codec720p); | |
1987 ASSERT_TRUE(channel_->SetSendParameters(parameters)); | |
1988 channel_->SetSend(true); | |
1989 | |
1990 FakeVideoSendStream* stream = AddSendStream(); | |
1991 | |
1992 cricket::FakeVideoCapturer capturer; | |
1993 EXPECT_TRUE(channel_->SetCapturer(last_ssrc_, &capturer)); | |
1994 EXPECT_EQ(cricket::CS_RUNNING, | |
1995 capturer.Start(capturer.GetSupportedFormats()->front())); | |
1996 | |
1997 std::vector<webrtc::VideoStream> streams = stream->GetVideoStreams(); | |
1998 int initial_max_bitrate_bps = streams[0].max_bitrate_bps; | |
1999 EXPECT_GT(initial_max_bitrate_bps, 0); | |
2000 | |
2001 parameters.max_bandwidth_bps = initial_max_bitrate_bps * 2; | |
2002 EXPECT_TRUE(channel_->SetSendParameters(parameters)); | |
2003 // Insert a frame to update the encoder config. | |
2004 EXPECT_TRUE(capturer.CaptureFrame()); | |
2005 streams = stream->GetVideoStreams(); | |
2006 EXPECT_EQ(initial_max_bitrate_bps * 2, streams[0].max_bitrate_bps); | |
2007 EXPECT_TRUE(channel_->SetCapturer(last_ssrc_, nullptr)); | |
2008 } | |
2009 | |
2010 TEST_F(WebRtcVideoChannel2Test, | |
2011 SetMaxSendBitrateCanIncreaseSimulcastSenderBitrate) { | |
2012 cricket::VideoSendParameters parameters; | |
2013 parameters.codecs.push_back(kVp8Codec720p); | |
2014 ASSERT_TRUE(channel_->SetSendParameters(parameters)); | |
2015 channel_->SetSend(true); | |
2016 | |
2017 FakeVideoSendStream* stream = AddSendStream( | |
2018 cricket::CreateSimStreamParams("cname", MAKE_VECTOR(kSsrcs3))); | |
2019 | |
2020 // Send a frame to make sure this scales up to >1 stream (simulcast). | |
2021 cricket::FakeVideoCapturer capturer; | |
2022 EXPECT_TRUE(channel_->SetCapturer(kSsrcs3[0], &capturer)); | |
2023 EXPECT_EQ(cricket::CS_RUNNING, | |
2024 capturer.Start(capturer.GetSupportedFormats()->front())); | |
2025 EXPECT_TRUE(capturer.CaptureFrame()); | |
2026 | |
2027 std::vector<webrtc::VideoStream> streams = stream->GetVideoStreams(); | |
2028 ASSERT_GT(streams.size(), 1u) | |
2029 << "Without simulcast this test doesn't make sense."; | |
2030 int initial_max_bitrate_bps = GetTotalMaxBitrateBps(streams); | |
2031 EXPECT_GT(initial_max_bitrate_bps, 0); | |
2032 | |
2033 parameters.max_bandwidth_bps = initial_max_bitrate_bps * 2; | |
2034 EXPECT_TRUE(channel_->SetSendParameters(parameters)); | |
2035 // Insert a frame to update the encoder config. | |
2036 EXPECT_TRUE(capturer.CaptureFrame()); | |
2037 streams = stream->GetVideoStreams(); | |
2038 int increased_max_bitrate_bps = GetTotalMaxBitrateBps(streams); | |
2039 EXPECT_EQ(initial_max_bitrate_bps * 2, increased_max_bitrate_bps); | |
2040 | |
2041 EXPECT_TRUE(channel_->SetCapturer(kSsrcs3[0], nullptr)); | |
2042 } | |
2043 | |
2044 TEST_F(WebRtcVideoChannel2Test, SetSendCodecsWithMaxQuantization) { | |
2045 static const char* kMaxQuantization = "21"; | |
2046 cricket::VideoSendParameters parameters; | |
2047 parameters.codecs.push_back(kVp8Codec); | |
2048 parameters.codecs[0].params[kCodecParamMaxQuantization] = kMaxQuantization; | |
2049 EXPECT_TRUE(channel_->SetSendParameters(parameters)); | |
2050 EXPECT_EQ(static_cast<unsigned int>(atoi(kMaxQuantization)), | |
2051 AddSendStream()->GetVideoStreams().back().max_qp); | |
2052 | |
2053 VideoCodec codec; | |
2054 EXPECT_TRUE(channel_->GetSendCodec(&codec)); | |
2055 EXPECT_EQ(kMaxQuantization, codec.params[kCodecParamMaxQuantization]); | |
2056 } | |
2057 | |
2058 TEST_F(WebRtcVideoChannel2Test, SetSendCodecsRejectBadDimensions) { | |
2059 cricket::VideoSendParameters parameters; | |
2060 parameters.codecs.push_back(kVp8Codec); | |
2061 | |
2062 parameters.codecs[0].width = 0; | |
2063 EXPECT_FALSE(channel_->SetSendParameters(parameters)) | |
2064 << "Codec set though codec width is zero."; | |
2065 | |
2066 parameters.codecs[0].width = kVp8Codec.width; | |
2067 parameters.codecs[0].height = 0; | |
2068 EXPECT_FALSE(channel_->SetSendParameters(parameters)) | |
2069 << "Codec set though codec height is zero."; | |
2070 } | |
2071 | |
2072 TEST_F(WebRtcVideoChannel2Test, SetSendCodecsRejectBadPayloadTypes) { | |
2073 // TODO(pbos): Should we only allow the dynamic range? | |
2074 static const int kIncorrectPayloads[] = {-2, -1, 128, 129}; | |
2075 cricket::VideoSendParameters parameters; | |
2076 parameters.codecs.push_back(kVp8Codec); | |
2077 for (size_t i = 0; i < arraysize(kIncorrectPayloads); ++i) { | |
2078 parameters.codecs[0].id = kIncorrectPayloads[i]; | |
2079 EXPECT_FALSE(channel_->SetSendParameters(parameters)) | |
2080 << "Bad payload type '" << kIncorrectPayloads[i] << "' accepted."; | |
2081 } | |
2082 } | |
2083 | |
2084 TEST_F(WebRtcVideoChannel2Test, SetSendCodecsAcceptAllValidPayloadTypes) { | |
2085 cricket::VideoSendParameters parameters; | |
2086 parameters.codecs.push_back(kVp8Codec); | |
2087 for (int payload_type = 0; payload_type <= 127; ++payload_type) { | |
2088 parameters.codecs[0].id = payload_type; | |
2089 EXPECT_TRUE(channel_->SetSendParameters(parameters)) | |
2090 << "Payload type '" << payload_type << "' rejected."; | |
2091 } | |
2092 } | |
2093 | |
2094 TEST_F(WebRtcVideoChannel2Test, SetRecvCodecsWithOnlyVp8) { | |
2095 cricket::VideoRecvParameters parameters; | |
2096 parameters.codecs.push_back(kVp8Codec); | |
2097 EXPECT_TRUE(channel_->SetRecvParameters(parameters)); | |
2098 } | |
2099 | |
2100 // Test that we set our inbound RTX codecs properly. | |
2101 TEST_F(WebRtcVideoChannel2Test, SetRecvCodecsWithRtx) { | |
2102 cricket::VideoRecvParameters parameters; | |
2103 parameters.codecs.push_back(kVp8Codec); | |
2104 cricket::VideoCodec rtx_codec(96, "rtx", 0, 0, 0, 0); | |
2105 parameters.codecs.push_back(rtx_codec); | |
2106 EXPECT_FALSE(channel_->SetRecvParameters(parameters)) | |
2107 << "RTX codec without associated payload should be rejected."; | |
2108 | |
2109 parameters.codecs[1].SetParam("apt", kVp8Codec.id + 1); | |
2110 EXPECT_FALSE(channel_->SetRecvParameters(parameters)) | |
2111 << "RTX codec with invalid associated payload type should be rejected."; | |
2112 | |
2113 parameters.codecs[1].SetParam("apt", kVp8Codec.id); | |
2114 EXPECT_TRUE(channel_->SetRecvParameters(parameters)); | |
2115 | |
2116 cricket::VideoCodec rtx_codec2(97, "rtx", 0, 0, 0, 0); | |
2117 rtx_codec2.SetParam("apt", rtx_codec.id); | |
2118 parameters.codecs.push_back(rtx_codec2); | |
2119 | |
2120 EXPECT_FALSE(channel_->SetRecvParameters(parameters)) << | |
2121 "RTX codec with another RTX as associated payload type should be " | |
2122 "rejected."; | |
2123 } | |
2124 | |
2125 TEST_F(WebRtcVideoChannel2Test, SetRecvCodecsDifferentPayloadType) { | |
2126 cricket::VideoRecvParameters parameters; | |
2127 parameters.codecs.push_back(kVp8Codec); | |
2128 parameters.codecs[0].id = 99; | |
2129 EXPECT_TRUE(channel_->SetRecvParameters(parameters)); | |
2130 } | |
2131 | |
2132 TEST_F(WebRtcVideoChannel2Test, SetRecvCodecsAcceptDefaultCodecs) { | |
2133 cricket::VideoRecvParameters parameters; | |
2134 parameters.codecs = engine_.codecs(); | |
2135 EXPECT_TRUE(channel_->SetRecvParameters(parameters)); | |
2136 | |
2137 FakeVideoReceiveStream* stream = AddRecvStream(); | |
2138 webrtc::VideoReceiveStream::Config config = stream->GetConfig(); | |
2139 EXPECT_EQ(engine_.codecs()[0].name, config.decoders[0].payload_name); | |
2140 EXPECT_EQ(engine_.codecs()[0].id, config.decoders[0].payload_type); | |
2141 } | |
2142 | |
2143 TEST_F(WebRtcVideoChannel2Test, SetRecvCodecsRejectUnsupportedCodec) { | |
2144 cricket::VideoRecvParameters parameters; | |
2145 parameters.codecs.push_back(kVp8Codec); | |
2146 parameters.codecs.push_back(VideoCodec(101, "WTF3", 640, 400, 30, 0)); | |
2147 EXPECT_FALSE(channel_->SetRecvParameters(parameters)); | |
2148 } | |
2149 | |
2150 // TODO(pbos): Enable VP9 through external codec support | |
2151 TEST_F(WebRtcVideoChannel2Test, | |
2152 DISABLED_SetRecvCodecsAcceptsMultipleVideoCodecs) { | |
2153 cricket::VideoRecvParameters parameters; | |
2154 parameters.codecs.push_back(kVp8Codec); | |
2155 parameters.codecs.push_back(kVp9Codec); | |
2156 EXPECT_TRUE(channel_->SetRecvParameters(parameters)); | |
2157 } | |
2158 | |
2159 TEST_F(WebRtcVideoChannel2Test, | |
2160 DISABLED_SetRecvCodecsSetsFecForAllVideoCodecs) { | |
2161 cricket::VideoRecvParameters parameters; | |
2162 parameters.codecs.push_back(kVp8Codec); | |
2163 parameters.codecs.push_back(kVp9Codec); | |
2164 EXPECT_TRUE(channel_->SetRecvParameters(parameters)); | |
2165 FAIL(); // TODO(pbos): Verify that the FEC parameters are set for all codecs. | |
2166 } | |
2167 | |
2168 TEST_F(WebRtcVideoChannel2Test, SetRecvCodecsWithoutFecDisablesFec) { | |
2169 cricket::VideoSendParameters send_parameters; | |
2170 send_parameters.codecs.push_back(kVp8Codec); | |
2171 send_parameters.codecs.push_back(kUlpfecCodec); | |
2172 ASSERT_TRUE(channel_->SetSendParameters(send_parameters)); | |
2173 | |
2174 FakeVideoReceiveStream* stream = AddRecvStream(); | |
2175 webrtc::VideoReceiveStream::Config config = stream->GetConfig(); | |
2176 | |
2177 EXPECT_EQ(kUlpfecCodec.id, config.rtp.fec.ulpfec_payload_type); | |
2178 | |
2179 cricket::VideoRecvParameters recv_parameters; | |
2180 recv_parameters.codecs.push_back(kVp8Codec); | |
2181 ASSERT_TRUE(channel_->SetRecvParameters(recv_parameters)); | |
2182 stream = fake_call_->GetVideoReceiveStreams()[0]; | |
2183 ASSERT_TRUE(stream != NULL); | |
2184 config = stream->GetConfig(); | |
2185 EXPECT_EQ(-1, config.rtp.fec.ulpfec_payload_type) | |
2186 << "SetSendCodec without FEC should disable current FEC."; | |
2187 } | |
2188 | |
2189 TEST_F(WebRtcVideoChannel2Test, SetSendCodecsRejectDuplicateFecPayloads) { | |
2190 cricket::VideoRecvParameters parameters; | |
2191 parameters.codecs.push_back(kVp8Codec); | |
2192 parameters.codecs.push_back(kRedCodec); | |
2193 parameters.codecs[1].id = parameters.codecs[0].id; | |
2194 EXPECT_FALSE(channel_->SetRecvParameters(parameters)); | |
2195 } | |
2196 | |
2197 TEST_F(WebRtcVideoChannel2Test, SetRecvCodecsRejectDuplicateCodecPayloads) { | |
2198 cricket::VideoRecvParameters parameters; | |
2199 parameters.codecs.push_back(kVp8Codec); | |
2200 parameters.codecs.push_back(kVp9Codec); | |
2201 parameters.codecs[1].id = parameters.codecs[0].id; | |
2202 EXPECT_FALSE(channel_->SetRecvParameters(parameters)); | |
2203 } | |
2204 | |
2205 TEST_F(WebRtcVideoChannel2Test, | |
2206 SetRecvCodecsAcceptSameCodecOnMultiplePayloadTypes) { | |
2207 cricket::VideoRecvParameters parameters; | |
2208 parameters.codecs.push_back(kVp8Codec); | |
2209 parameters.codecs.push_back(kVp8Codec); | |
2210 parameters.codecs[1].id += 1; | |
2211 EXPECT_TRUE(channel_->SetRecvParameters(parameters)); | |
2212 } | |
2213 | |
2214 // Test that setting the same codecs but with a different order and preference | |
2215 // doesn't result in the stream being recreated. | |
2216 TEST_F(WebRtcVideoChannel2Test, | |
2217 SetRecvCodecsDifferentOrderAndPreferenceDoesntRecreateStream) { | |
2218 cricket::VideoRecvParameters parameters1; | |
2219 parameters1.codecs.push_back(kVp8Codec); | |
2220 parameters1.codecs.push_back(kRedCodec); | |
2221 EXPECT_TRUE(channel_->SetRecvParameters(parameters1)); | |
2222 | |
2223 AddRecvStream(cricket::StreamParams::CreateLegacy(123)); | |
2224 EXPECT_EQ(1, fake_call_->GetNumCreatedReceiveStreams()); | |
2225 | |
2226 cricket::VideoRecvParameters parameters2; | |
2227 parameters2.codecs.push_back(kRedCodec); | |
2228 parameters2.codecs.push_back(kVp8Codec); | |
2229 parameters2.codecs[1].preference += 1; | |
2230 EXPECT_TRUE(channel_->SetRecvParameters(parameters2)); | |
2231 EXPECT_EQ(1, fake_call_->GetNumCreatedReceiveStreams()); | |
2232 } | |
2233 | |
2234 TEST_F(WebRtcVideoChannel2Test, SendStreamNotSendingByDefault) { | |
2235 EXPECT_FALSE(AddSendStream()->IsSending()); | |
2236 } | |
2237 | |
2238 TEST_F(WebRtcVideoChannel2Test, ReceiveStreamReceivingByDefault) { | |
2239 EXPECT_TRUE(AddRecvStream()->IsReceiving()); | |
2240 } | |
2241 | |
2242 TEST_F(WebRtcVideoChannel2Test, SetSend) { | |
2243 FakeVideoSendStream* stream = AddSendStream(); | |
2244 EXPECT_FALSE(stream->IsSending()); | |
2245 | |
2246 // false->true | |
2247 EXPECT_TRUE(channel_->SetSend(true)); | |
2248 EXPECT_TRUE(stream->IsSending()); | |
2249 // true->true | |
2250 EXPECT_TRUE(channel_->SetSend(true)); | |
2251 EXPECT_TRUE(stream->IsSending()); | |
2252 // true->false | |
2253 EXPECT_TRUE(channel_->SetSend(false)); | |
2254 EXPECT_FALSE(stream->IsSending()); | |
2255 // false->false | |
2256 EXPECT_TRUE(channel_->SetSend(false)); | |
2257 EXPECT_FALSE(stream->IsSending()); | |
2258 | |
2259 EXPECT_TRUE(channel_->SetSend(true)); | |
2260 FakeVideoSendStream* new_stream = AddSendStream(); | |
2261 EXPECT_TRUE(new_stream->IsSending()) | |
2262 << "Send stream created after SetSend(true) not sending initially."; | |
2263 } | |
2264 | |
2265 // This test verifies DSCP settings are properly applied on video media channel. | |
2266 TEST_F(WebRtcVideoChannel2Test, TestSetDscpOptions) { | |
2267 rtc::scoped_ptr<cricket::FakeNetworkInterface> network_interface( | |
2268 new cricket::FakeNetworkInterface); | |
2269 channel_->SetInterface(network_interface.get()); | |
2270 cricket::VideoSendParameters parameters = send_parameters_; | |
2271 EXPECT_TRUE(channel_->SetSendParameters(parameters)); | |
2272 EXPECT_EQ(rtc::DSCP_NO_CHANGE, network_interface->dscp()); | |
2273 parameters.options.dscp = rtc::Optional<bool>(true); | |
2274 EXPECT_TRUE(channel_->SetSendParameters(parameters)); | |
2275 EXPECT_EQ(rtc::DSCP_AF41, network_interface->dscp()); | |
2276 // Verify previous value is not modified if dscp option is not set. | |
2277 cricket::VideoSendParameters parameters1 = send_parameters_; | |
2278 EXPECT_TRUE(channel_->SetSendParameters(parameters1)); | |
2279 EXPECT_EQ(rtc::DSCP_AF41, network_interface->dscp()); | |
2280 parameters1.options.dscp = rtc::Optional<bool>(false); | |
2281 EXPECT_TRUE(channel_->SetSendParameters(parameters1)); | |
2282 EXPECT_EQ(rtc::DSCP_DEFAULT, network_interface->dscp()); | |
2283 channel_->SetInterface(NULL); | |
2284 } | |
2285 | |
2286 // This test verifies that the RTCP reduced size mode is properly applied to | |
2287 // send video streams. | |
2288 TEST_F(WebRtcVideoChannel2Test, TestSetSendRtcpReducedSize) { | |
2289 // Create stream, expecting that default mode is "compound". | |
2290 FakeVideoSendStream* stream1 = AddSendStream(); | |
2291 EXPECT_EQ(webrtc::RtcpMode::kCompound, stream1->GetConfig().rtp.rtcp_mode); | |
2292 | |
2293 // Now enable reduced size mode. | |
2294 send_parameters_.rtcp.reduced_size = true; | |
2295 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_)); | |
2296 stream1 = fake_call_->GetVideoSendStreams()[0]; | |
2297 EXPECT_EQ(webrtc::RtcpMode::kReducedSize, stream1->GetConfig().rtp.rtcp_mode); | |
2298 | |
2299 // Create a new stream and ensure it picks up the reduced size mode. | |
2300 FakeVideoSendStream* stream2 = AddSendStream(); | |
2301 EXPECT_EQ(webrtc::RtcpMode::kReducedSize, stream2->GetConfig().rtp.rtcp_mode); | |
2302 } | |
2303 | |
2304 // This test verifies that the RTCP reduced size mode is properly applied to | |
2305 // receive video streams. | |
2306 TEST_F(WebRtcVideoChannel2Test, TestSetRecvRtcpReducedSize) { | |
2307 // Create stream, expecting that default mode is "compound". | |
2308 FakeVideoReceiveStream* stream1 = AddRecvStream(); | |
2309 EXPECT_EQ(webrtc::RtcpMode::kCompound, stream1->GetConfig().rtp.rtcp_mode); | |
2310 | |
2311 // Now enable reduced size mode. | |
2312 recv_parameters_.rtcp.reduced_size = true; | |
2313 EXPECT_TRUE(channel_->SetRecvParameters(recv_parameters_)); | |
2314 stream1 = fake_call_->GetVideoReceiveStreams()[0]; | |
2315 EXPECT_EQ(webrtc::RtcpMode::kReducedSize, stream1->GetConfig().rtp.rtcp_mode); | |
2316 | |
2317 // Create a new stream and ensure it picks up the reduced size mode. | |
2318 FakeVideoReceiveStream* stream2 = AddRecvStream(); | |
2319 EXPECT_EQ(webrtc::RtcpMode::kReducedSize, stream2->GetConfig().rtp.rtcp_mode); | |
2320 } | |
2321 | |
2322 TEST_F(WebRtcVideoChannel2Test, OnReadyToSendSignalsNetworkState) { | |
2323 EXPECT_EQ(webrtc::kNetworkUp, fake_call_->GetNetworkState()); | |
2324 | |
2325 channel_->OnReadyToSend(false); | |
2326 EXPECT_EQ(webrtc::kNetworkDown, fake_call_->GetNetworkState()); | |
2327 | |
2328 channel_->OnReadyToSend(true); | |
2329 EXPECT_EQ(webrtc::kNetworkUp, fake_call_->GetNetworkState()); | |
2330 } | |
2331 | |
2332 TEST_F(WebRtcVideoChannel2Test, GetStatsReportsSentCodecName) { | |
2333 cricket::VideoSendParameters parameters; | |
2334 parameters.codecs.push_back(kVp8Codec); | |
2335 EXPECT_TRUE(channel_->SetSendParameters(parameters)); | |
2336 | |
2337 AddSendStream(); | |
2338 | |
2339 cricket::VideoMediaInfo info; | |
2340 ASSERT_TRUE(channel_->GetStats(&info)); | |
2341 EXPECT_EQ(kVp8Codec.name, info.senders[0].codec_name); | |
2342 } | |
2343 | |
2344 TEST_F(WebRtcVideoChannel2Test, GetStatsReportsEncoderImplementationName) { | |
2345 FakeVideoSendStream* stream = AddSendStream(); | |
2346 webrtc::VideoSendStream::Stats stats; | |
2347 stats.encoder_implementation_name = "encoder_implementation_name"; | |
2348 stream->SetStats(stats); | |
2349 | |
2350 cricket::VideoMediaInfo info; | |
2351 ASSERT_TRUE(channel_->GetStats(&info)); | |
2352 EXPECT_EQ(stats.encoder_implementation_name, | |
2353 info.senders[0].encoder_implementation_name); | |
2354 } | |
2355 | |
2356 TEST_F(WebRtcVideoChannel2Test, GetStatsReportsCpuOveruseMetrics) { | |
2357 FakeVideoSendStream* stream = AddSendStream(); | |
2358 webrtc::VideoSendStream::Stats stats; | |
2359 stats.avg_encode_time_ms = 13; | |
2360 stats.encode_usage_percent = 42; | |
2361 stream->SetStats(stats); | |
2362 | |
2363 cricket::VideoMediaInfo info; | |
2364 ASSERT_TRUE(channel_->GetStats(&info)); | |
2365 EXPECT_EQ(stats.avg_encode_time_ms, info.senders[0].avg_encode_ms); | |
2366 EXPECT_EQ(stats.encode_usage_percent, info.senders[0].encode_usage_percent); | |
2367 } | |
2368 | |
2369 TEST_F(WebRtcVideoChannel2Test, GetStatsReportsUpperResolution) { | |
2370 FakeVideoSendStream* stream = AddSendStream(); | |
2371 webrtc::VideoSendStream::Stats stats; | |
2372 stats.substreams[17].width = 123; | |
2373 stats.substreams[17].height = 40; | |
2374 stats.substreams[42].width = 80; | |
2375 stats.substreams[42].height = 31; | |
2376 stats.substreams[11].width = 20; | |
2377 stats.substreams[11].height = 90; | |
2378 stream->SetStats(stats); | |
2379 | |
2380 cricket::VideoMediaInfo info; | |
2381 ASSERT_TRUE(channel_->GetStats(&info)); | |
2382 ASSERT_EQ(1u, info.senders.size()); | |
2383 EXPECT_EQ(123, info.senders[0].send_frame_width); | |
2384 EXPECT_EQ(90, info.senders[0].send_frame_height); | |
2385 } | |
2386 | |
2387 TEST_F(WebRtcVideoChannel2Test, GetStatsTracksAdaptationStats) { | |
2388 AddSendStream(cricket::CreateSimStreamParams("cname", MAKE_VECTOR(kSsrcs3))); | |
2389 | |
2390 // Capture format VGA. | |
2391 cricket::FakeVideoCapturer video_capturer_vga; | |
2392 const std::vector<cricket::VideoFormat>* formats = | |
2393 video_capturer_vga.GetSupportedFormats(); | |
2394 cricket::VideoFormat capture_format_vga = (*formats)[1]; | |
2395 EXPECT_EQ(cricket::CS_RUNNING, video_capturer_vga.Start(capture_format_vga)); | |
2396 EXPECT_TRUE(channel_->SetCapturer(kSsrcs3[0], &video_capturer_vga)); | |
2397 EXPECT_TRUE(video_capturer_vga.CaptureFrame()); | |
2398 | |
2399 cricket::VideoCodec send_codec(100, "VP8", 640, 480, 30, 0); | |
2400 cricket::VideoSendParameters parameters; | |
2401 parameters.codecs.push_back(send_codec); | |
2402 EXPECT_TRUE(channel_->SetSendParameters(parameters)); | |
2403 EXPECT_TRUE(channel_->SetSend(true)); | |
2404 | |
2405 // Verify that the CpuOveruseObserver is registered and trigger downgrade. | |
2406 parameters.options.cpu_overuse_detection = rtc::Optional<bool>(true); | |
2407 EXPECT_TRUE(channel_->SetSendParameters(parameters)); | |
2408 | |
2409 // Trigger overuse. | |
2410 ASSERT_EQ(1u, fake_call_->GetVideoSendStreams().size()); | |
2411 webrtc::LoadObserver* overuse_callback = | |
2412 fake_call_->GetVideoSendStreams().front()->GetConfig().overuse_callback; | |
2413 ASSERT_TRUE(overuse_callback != NULL); | |
2414 overuse_callback->OnLoadUpdate(webrtc::LoadObserver::kOveruse); | |
2415 | |
2416 // Capture format VGA -> adapt (OnCpuResolutionRequest downgrade) -> VGA/2. | |
2417 EXPECT_TRUE(video_capturer_vga.CaptureFrame()); | |
2418 cricket::VideoMediaInfo info; | |
2419 EXPECT_TRUE(channel_->GetStats(&info)); | |
2420 ASSERT_EQ(1U, info.senders.size()); | |
2421 EXPECT_EQ(1, info.senders[0].adapt_changes); | |
2422 EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_CPU, | |
2423 info.senders[0].adapt_reason); | |
2424 | |
2425 // Trigger upgrade and verify that we adapt back up to VGA. | |
2426 overuse_callback->OnLoadUpdate(webrtc::LoadObserver::kUnderuse); | |
2427 EXPECT_TRUE(video_capturer_vga.CaptureFrame()); | |
2428 info.Clear(); | |
2429 EXPECT_TRUE(channel_->GetStats(&info)); | |
2430 ASSERT_EQ(1U, info.senders.size()); | |
2431 EXPECT_EQ(2, info.senders[0].adapt_changes); | |
2432 EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_NONE, | |
2433 info.senders[0].adapt_reason); | |
2434 | |
2435 // No capturer (no adapter). Adapt changes from old adapter should be kept. | |
2436 EXPECT_TRUE(channel_->SetCapturer(kSsrcs3[0], NULL)); | |
2437 info.Clear(); | |
2438 EXPECT_TRUE(channel_->GetStats(&info)); | |
2439 ASSERT_EQ(1U, info.senders.size()); | |
2440 EXPECT_EQ(2, info.senders[0].adapt_changes); | |
2441 EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_NONE, | |
2442 info.senders[0].adapt_reason); | |
2443 | |
2444 // Set new capturer, capture format HD. | |
2445 cricket::FakeVideoCapturer video_capturer_hd; | |
2446 cricket::VideoFormat capture_format_hd = (*formats)[0]; | |
2447 EXPECT_EQ(cricket::CS_RUNNING, video_capturer_hd.Start(capture_format_hd)); | |
2448 EXPECT_TRUE(channel_->SetCapturer(kSsrcs3[0], &video_capturer_hd)); | |
2449 EXPECT_TRUE(video_capturer_hd.CaptureFrame()); | |
2450 | |
2451 // Trigger overuse, HD -> adapt (OnCpuResolutionRequest downgrade) -> HD/2. | |
2452 overuse_callback->OnLoadUpdate(webrtc::LoadObserver::kOveruse); | |
2453 EXPECT_TRUE(video_capturer_hd.CaptureFrame()); | |
2454 info.Clear(); | |
2455 EXPECT_TRUE(channel_->GetStats(&info)); | |
2456 ASSERT_EQ(1U, info.senders.size()); | |
2457 EXPECT_EQ(3, info.senders[0].adapt_changes); | |
2458 EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_CPU, | |
2459 info.senders[0].adapt_reason); | |
2460 | |
2461 EXPECT_TRUE(channel_->SetCapturer(kSsrcs3[0], NULL)); | |
2462 } | |
2463 | |
2464 TEST_F(WebRtcVideoChannel2Test, GetStatsTracksAdaptationAndBandwidthStats) { | |
2465 AddSendStream(cricket::CreateSimStreamParams("cname", MAKE_VECTOR(kSsrcs3))); | |
2466 | |
2467 // Capture format VGA. | |
2468 cricket::FakeVideoCapturer video_capturer_vga; | |
2469 const std::vector<cricket::VideoFormat>* formats = | |
2470 video_capturer_vga.GetSupportedFormats(); | |
2471 cricket::VideoFormat capture_format_vga = (*formats)[1]; | |
2472 EXPECT_EQ(cricket::CS_RUNNING, video_capturer_vga.Start(capture_format_vga)); | |
2473 EXPECT_TRUE(channel_->SetCapturer(kSsrcs3[0], &video_capturer_vga)); | |
2474 EXPECT_TRUE(video_capturer_vga.CaptureFrame()); | |
2475 | |
2476 cricket::VideoCodec send_codec(100, "VP8", 640, 480, 30, 0); | |
2477 cricket::VideoSendParameters parameters; | |
2478 parameters.codecs.push_back(send_codec); | |
2479 EXPECT_TRUE(channel_->SetSendParameters(parameters)); | |
2480 EXPECT_TRUE(channel_->SetSend(true)); | |
2481 | |
2482 // Verify that the CpuOveruseObserver is registered and trigger downgrade. | |
2483 parameters.options.cpu_overuse_detection = rtc::Optional<bool>(true); | |
2484 EXPECT_TRUE(channel_->SetSendParameters(parameters)); | |
2485 | |
2486 // Trigger overuse -> adapt CPU. | |
2487 ASSERT_EQ(1u, fake_call_->GetVideoSendStreams().size()); | |
2488 webrtc::LoadObserver* overuse_callback = | |
2489 fake_call_->GetVideoSendStreams().front()->GetConfig().overuse_callback; | |
2490 ASSERT_TRUE(overuse_callback != NULL); | |
2491 overuse_callback->OnLoadUpdate(webrtc::LoadObserver::kOveruse); | |
2492 EXPECT_TRUE(video_capturer_vga.CaptureFrame()); | |
2493 cricket::VideoMediaInfo info; | |
2494 EXPECT_TRUE(channel_->GetStats(&info)); | |
2495 ASSERT_EQ(1U, info.senders.size()); | |
2496 EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_CPU, | |
2497 info.senders[0].adapt_reason); | |
2498 | |
2499 // Set bandwidth limitation stats for the stream -> adapt CPU + BW. | |
2500 webrtc::VideoSendStream::Stats stats; | |
2501 stats.bw_limited_resolution = true; | |
2502 fake_call_->GetVideoSendStreams().front()->SetStats(stats); | |
2503 info.Clear(); | |
2504 EXPECT_TRUE(channel_->GetStats(&info)); | |
2505 ASSERT_EQ(1U, info.senders.size()); | |
2506 EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_CPU + | |
2507 CoordinatedVideoAdapter::ADAPTREASON_BANDWIDTH, | |
2508 info.senders[0].adapt_reason); | |
2509 | |
2510 // Trigger upgrade -> adapt BW. | |
2511 overuse_callback->OnLoadUpdate(webrtc::LoadObserver::kUnderuse); | |
2512 EXPECT_TRUE(video_capturer_vga.CaptureFrame()); | |
2513 info.Clear(); | |
2514 EXPECT_TRUE(channel_->GetStats(&info)); | |
2515 ASSERT_EQ(1U, info.senders.size()); | |
2516 EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_BANDWIDTH, | |
2517 info.senders[0].adapt_reason); | |
2518 | |
2519 // Reset bandwidth limitation state -> adapt NONE. | |
2520 stats.bw_limited_resolution = false; | |
2521 fake_call_->GetVideoSendStreams().front()->SetStats(stats); | |
2522 info.Clear(); | |
2523 EXPECT_TRUE(channel_->GetStats(&info)); | |
2524 ASSERT_EQ(1U, info.senders.size()); | |
2525 EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_NONE, | |
2526 info.senders[0].adapt_reason); | |
2527 | |
2528 EXPECT_TRUE(channel_->SetCapturer(kSsrcs3[0], NULL)); | |
2529 } | |
2530 | |
2531 TEST_F(WebRtcVideoChannel2Test, | |
2532 GetStatsTranslatesBandwidthLimitedResolutionCorrectly) { | |
2533 FakeVideoSendStream* stream = AddSendStream(); | |
2534 webrtc::VideoSendStream::Stats stats; | |
2535 stats.bw_limited_resolution = true; | |
2536 stream->SetStats(stats); | |
2537 | |
2538 cricket::VideoMediaInfo info; | |
2539 EXPECT_TRUE(channel_->GetStats(&info)); | |
2540 ASSERT_EQ(1U, info.senders.size()); | |
2541 EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_BANDWIDTH, | |
2542 info.senders[0].adapt_reason); | |
2543 } | |
2544 | |
2545 TEST_F(WebRtcVideoChannel2Test, | |
2546 GetStatsTranslatesSendRtcpPacketTypesCorrectly) { | |
2547 FakeVideoSendStream* stream = AddSendStream(); | |
2548 webrtc::VideoSendStream::Stats stats; | |
2549 stats.substreams[17].rtcp_packet_type_counts.fir_packets = 2; | |
2550 stats.substreams[17].rtcp_packet_type_counts.nack_packets = 3; | |
2551 stats.substreams[17].rtcp_packet_type_counts.pli_packets = 4; | |
2552 | |
2553 stats.substreams[42].rtcp_packet_type_counts.fir_packets = 5; | |
2554 stats.substreams[42].rtcp_packet_type_counts.nack_packets = 7; | |
2555 stats.substreams[42].rtcp_packet_type_counts.pli_packets = 9; | |
2556 | |
2557 stream->SetStats(stats); | |
2558 | |
2559 cricket::VideoMediaInfo info; | |
2560 ASSERT_TRUE(channel_->GetStats(&info)); | |
2561 EXPECT_EQ(7, info.senders[0].firs_rcvd); | |
2562 EXPECT_EQ(10, info.senders[0].nacks_rcvd); | |
2563 EXPECT_EQ(13, info.senders[0].plis_rcvd); | |
2564 } | |
2565 | |
2566 TEST_F(WebRtcVideoChannel2Test, | |
2567 GetStatsTranslatesReceiveRtcpPacketTypesCorrectly) { | |
2568 FakeVideoReceiveStream* stream = AddRecvStream(); | |
2569 webrtc::VideoReceiveStream::Stats stats; | |
2570 stats.rtcp_packet_type_counts.fir_packets = 2; | |
2571 stats.rtcp_packet_type_counts.nack_packets = 3; | |
2572 stats.rtcp_packet_type_counts.pli_packets = 4; | |
2573 stream->SetStats(stats); | |
2574 | |
2575 cricket::VideoMediaInfo info; | |
2576 ASSERT_TRUE(channel_->GetStats(&info)); | |
2577 EXPECT_EQ(stats.rtcp_packet_type_counts.fir_packets, | |
2578 info.receivers[0].firs_sent); | |
2579 EXPECT_EQ(stats.rtcp_packet_type_counts.nack_packets, | |
2580 info.receivers[0].nacks_sent); | |
2581 EXPECT_EQ(stats.rtcp_packet_type_counts.pli_packets, | |
2582 info.receivers[0].plis_sent); | |
2583 } | |
2584 | |
2585 TEST_F(WebRtcVideoChannel2Test, GetStatsTranslatesDecodeStatsCorrectly) { | |
2586 FakeVideoReceiveStream* stream = AddRecvStream(); | |
2587 webrtc::VideoReceiveStream::Stats stats; | |
2588 stats.decoder_implementation_name = "decoder_implementation_name"; | |
2589 stats.decode_ms = 2; | |
2590 stats.max_decode_ms = 3; | |
2591 stats.current_delay_ms = 4; | |
2592 stats.target_delay_ms = 5; | |
2593 stats.jitter_buffer_ms = 6; | |
2594 stats.min_playout_delay_ms = 7; | |
2595 stats.render_delay_ms = 8; | |
2596 stream->SetStats(stats); | |
2597 | |
2598 cricket::VideoMediaInfo info; | |
2599 ASSERT_TRUE(channel_->GetStats(&info)); | |
2600 EXPECT_EQ(stats.decoder_implementation_name, | |
2601 info.receivers[0].decoder_implementation_name); | |
2602 EXPECT_EQ(stats.decode_ms, info.receivers[0].decode_ms); | |
2603 EXPECT_EQ(stats.max_decode_ms, info.receivers[0].max_decode_ms); | |
2604 EXPECT_EQ(stats.current_delay_ms, info.receivers[0].current_delay_ms); | |
2605 EXPECT_EQ(stats.target_delay_ms, info.receivers[0].target_delay_ms); | |
2606 EXPECT_EQ(stats.jitter_buffer_ms, info.receivers[0].jitter_buffer_ms); | |
2607 EXPECT_EQ(stats.min_playout_delay_ms, info.receivers[0].min_playout_delay_ms); | |
2608 EXPECT_EQ(stats.render_delay_ms, info.receivers[0].render_delay_ms); | |
2609 } | |
2610 | |
2611 TEST_F(WebRtcVideoChannel2Test, GetStatsTranslatesReceivePacketStatsCorrectly) { | |
2612 FakeVideoReceiveStream* stream = AddRecvStream(); | |
2613 webrtc::VideoReceiveStream::Stats stats; | |
2614 stats.rtp_stats.transmitted.payload_bytes = 2; | |
2615 stats.rtp_stats.transmitted.header_bytes = 3; | |
2616 stats.rtp_stats.transmitted.padding_bytes = 4; | |
2617 stats.rtp_stats.transmitted.packets = 5; | |
2618 stats.rtcp_stats.cumulative_lost = 6; | |
2619 stats.rtcp_stats.fraction_lost = 7; | |
2620 stream->SetStats(stats); | |
2621 | |
2622 cricket::VideoMediaInfo info; | |
2623 ASSERT_TRUE(channel_->GetStats(&info)); | |
2624 EXPECT_EQ(stats.rtp_stats.transmitted.payload_bytes + | |
2625 stats.rtp_stats.transmitted.header_bytes + | |
2626 stats.rtp_stats.transmitted.padding_bytes, | |
2627 info.receivers[0].bytes_rcvd); | |
2628 EXPECT_EQ(stats.rtp_stats.transmitted.packets, | |
2629 info.receivers[0].packets_rcvd); | |
2630 EXPECT_EQ(stats.rtcp_stats.cumulative_lost, info.receivers[0].packets_lost); | |
2631 EXPECT_EQ(static_cast<float>(stats.rtcp_stats.fraction_lost) / (1 << 8), | |
2632 info.receivers[0].fraction_lost); | |
2633 } | |
2634 | |
2635 TEST_F(WebRtcVideoChannel2Test, TranslatesCallStatsCorrectly) { | |
2636 AddSendStream(); | |
2637 AddSendStream(); | |
2638 webrtc::Call::Stats stats; | |
2639 stats.rtt_ms = 123; | |
2640 fake_call_->SetStats(stats); | |
2641 | |
2642 cricket::VideoMediaInfo info; | |
2643 ASSERT_TRUE(channel_->GetStats(&info)); | |
2644 ASSERT_EQ(2u, info.senders.size()); | |
2645 EXPECT_EQ(stats.rtt_ms, info.senders[0].rtt_ms); | |
2646 EXPECT_EQ(stats.rtt_ms, info.senders[1].rtt_ms); | |
2647 } | |
2648 | |
2649 TEST_F(WebRtcVideoChannel2Test, TranslatesSenderBitrateStatsCorrectly) { | |
2650 FakeVideoSendStream* stream = AddSendStream(); | |
2651 webrtc::VideoSendStream::Stats stats; | |
2652 stats.target_media_bitrate_bps = 156; | |
2653 stats.media_bitrate_bps = 123; | |
2654 stats.substreams[17].total_bitrate_bps = 1; | |
2655 stats.substreams[17].retransmit_bitrate_bps = 2; | |
2656 stats.substreams[42].total_bitrate_bps = 3; | |
2657 stats.substreams[42].retransmit_bitrate_bps = 4; | |
2658 stream->SetStats(stats); | |
2659 | |
2660 FakeVideoSendStream* stream2 = AddSendStream(); | |
2661 webrtc::VideoSendStream::Stats stats2; | |
2662 stats2.target_media_bitrate_bps = 200; | |
2663 stats2.media_bitrate_bps = 321; | |
2664 stats2.substreams[13].total_bitrate_bps = 5; | |
2665 stats2.substreams[13].retransmit_bitrate_bps = 6; | |
2666 stats2.substreams[21].total_bitrate_bps = 7; | |
2667 stats2.substreams[21].retransmit_bitrate_bps = 8; | |
2668 stream2->SetStats(stats2); | |
2669 | |
2670 cricket::VideoMediaInfo info; | |
2671 ASSERT_TRUE(channel_->GetStats(&info)); | |
2672 ASSERT_EQ(2u, info.senders.size()); | |
2673 // Assuming stream and stream2 corresponds to senders[0] and [1] respectively | |
2674 // is OK as std::maps are sorted and AddSendStream() gives increasing SSRCs. | |
2675 EXPECT_EQ(stats.media_bitrate_bps, info.senders[0].nominal_bitrate); | |
2676 EXPECT_EQ(stats2.media_bitrate_bps, info.senders[1].nominal_bitrate); | |
2677 EXPECT_EQ(stats.target_media_bitrate_bps + stats2.target_media_bitrate_bps, | |
2678 info.bw_estimations[0].target_enc_bitrate); | |
2679 EXPECT_EQ(stats.media_bitrate_bps + stats2.media_bitrate_bps, | |
2680 info.bw_estimations[0].actual_enc_bitrate); | |
2681 EXPECT_EQ(1 + 3 + 5 + 7, info.bw_estimations[0].transmit_bitrate) | |
2682 << "Bandwidth stats should take all streams into account."; | |
2683 EXPECT_EQ(2 + 4 + 6 + 8, info.bw_estimations[0].retransmit_bitrate) | |
2684 << "Bandwidth stats should take all streams into account."; | |
2685 } | |
2686 | |
2687 TEST_F(WebRtcVideoChannel2Test, DefaultReceiveStreamReconfiguresToUseRtx) { | |
2688 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_)); | |
2689 | |
2690 const std::vector<uint32_t> ssrcs = MAKE_VECTOR(kSsrcs1); | |
2691 const std::vector<uint32_t> rtx_ssrcs = MAKE_VECTOR(kRtxSsrcs1); | |
2692 | |
2693 ASSERT_EQ(0u, fake_call_->GetVideoReceiveStreams().size()); | |
2694 const size_t kDataLength = 12; | |
2695 uint8_t data[kDataLength]; | |
2696 memset(data, 0, sizeof(data)); | |
2697 rtc::SetBE32(&data[8], ssrcs[0]); | |
2698 rtc::Buffer packet(data, kDataLength); | |
2699 rtc::PacketTime packet_time; | |
2700 channel_->OnPacketReceived(&packet, packet_time); | |
2701 | |
2702 ASSERT_EQ(1u, fake_call_->GetVideoReceiveStreams().size()) | |
2703 << "No default receive stream created."; | |
2704 FakeVideoReceiveStream* recv_stream = fake_call_->GetVideoReceiveStreams()[0]; | |
2705 EXPECT_EQ(0u, recv_stream->GetConfig().rtp.rtx.size()) | |
2706 << "Default receive stream should not have configured RTX"; | |
2707 | |
2708 EXPECT_TRUE(channel_->AddRecvStream( | |
2709 cricket::CreateSimWithRtxStreamParams("cname", ssrcs, rtx_ssrcs))); | |
2710 ASSERT_EQ(1u, fake_call_->GetVideoReceiveStreams().size()) | |
2711 << "AddRecvStream should've reconfigured, not added a new receiver."; | |
2712 recv_stream = fake_call_->GetVideoReceiveStreams()[0]; | |
2713 ASSERT_GE(2u, recv_stream->GetConfig().rtp.rtx.size()); | |
2714 EXPECT_EQ(rtx_ssrcs[0], | |
2715 recv_stream->GetConfig().rtp.rtx.begin()->second.ssrc); | |
2716 } | |
2717 | |
2718 TEST_F(WebRtcVideoChannel2Test, RejectsAddingStreamsWithMissingSsrcsForRtx) { | |
2719 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_)); | |
2720 | |
2721 const std::vector<uint32_t> ssrcs = MAKE_VECTOR(kSsrcs1); | |
2722 const std::vector<uint32_t> rtx_ssrcs = MAKE_VECTOR(kRtxSsrcs1); | |
2723 | |
2724 StreamParams sp = | |
2725 cricket::CreateSimWithRtxStreamParams("cname", ssrcs, rtx_ssrcs); | |
2726 sp.ssrcs = ssrcs; // Without RTXs, this is the important part. | |
2727 | |
2728 EXPECT_FALSE(channel_->AddSendStream(sp)); | |
2729 EXPECT_FALSE(channel_->AddRecvStream(sp)); | |
2730 } | |
2731 | |
2732 TEST_F(WebRtcVideoChannel2Test, RejectsAddingStreamsWithOverlappingRtxSsrcs) { | |
2733 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_)); | |
2734 | |
2735 const std::vector<uint32_t> ssrcs = MAKE_VECTOR(kSsrcs1); | |
2736 const std::vector<uint32_t> rtx_ssrcs = MAKE_VECTOR(kRtxSsrcs1); | |
2737 | |
2738 StreamParams sp = | |
2739 cricket::CreateSimWithRtxStreamParams("cname", ssrcs, rtx_ssrcs); | |
2740 | |
2741 EXPECT_TRUE(channel_->AddSendStream(sp)); | |
2742 EXPECT_TRUE(channel_->AddRecvStream(sp)); | |
2743 | |
2744 // The RTX SSRC is already used in previous streams, using it should fail. | |
2745 sp = cricket::StreamParams::CreateLegacy(rtx_ssrcs[0]); | |
2746 EXPECT_FALSE(channel_->AddSendStream(sp)); | |
2747 EXPECT_FALSE(channel_->AddRecvStream(sp)); | |
2748 | |
2749 // After removing the original stream this should be fine to add (makes sure | |
2750 // that RTX ssrcs are not forever taken). | |
2751 EXPECT_TRUE(channel_->RemoveSendStream(ssrcs[0])); | |
2752 EXPECT_TRUE(channel_->RemoveRecvStream(ssrcs[0])); | |
2753 EXPECT_TRUE(channel_->AddSendStream(sp)); | |
2754 EXPECT_TRUE(channel_->AddRecvStream(sp)); | |
2755 } | |
2756 | |
2757 TEST_F(WebRtcVideoChannel2Test, | |
2758 RejectsAddingStreamsWithOverlappingSimulcastSsrcs) { | |
2759 static const uint32_t kFirstStreamSsrcs[] = {1, 2, 3}; | |
2760 static const uint32_t kOverlappingStreamSsrcs[] = {4, 3, 5}; | |
2761 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_)); | |
2762 | |
2763 StreamParams sp = | |
2764 cricket::CreateSimStreamParams("cname", MAKE_VECTOR(kFirstStreamSsrcs)); | |
2765 | |
2766 EXPECT_TRUE(channel_->AddSendStream(sp)); | |
2767 EXPECT_TRUE(channel_->AddRecvStream(sp)); | |
2768 | |
2769 // One of the SSRCs is already used in previous streams, using it should fail. | |
2770 sp = cricket::CreateSimStreamParams("cname", | |
2771 MAKE_VECTOR(kOverlappingStreamSsrcs)); | |
2772 EXPECT_FALSE(channel_->AddSendStream(sp)); | |
2773 EXPECT_FALSE(channel_->AddRecvStream(sp)); | |
2774 | |
2775 // After removing the original stream this should be fine to add (makes sure | |
2776 // that RTX ssrcs are not forever taken). | |
2777 EXPECT_TRUE(channel_->RemoveSendStream(kFirstStreamSsrcs[0])); | |
2778 EXPECT_TRUE(channel_->RemoveRecvStream(kFirstStreamSsrcs[0])); | |
2779 EXPECT_TRUE(channel_->AddSendStream(sp)); | |
2780 EXPECT_TRUE(channel_->AddRecvStream(sp)); | |
2781 } | |
2782 | |
2783 TEST_F(WebRtcVideoChannel2Test, ReportsSsrcGroupsInStats) { | |
2784 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_)); | |
2785 | |
2786 static const uint32_t kSenderSsrcs[] = {4, 7, 10}; | |
2787 static const uint32_t kSenderRtxSsrcs[] = {5, 8, 11}; | |
2788 | |
2789 StreamParams sender_sp = cricket::CreateSimWithRtxStreamParams( | |
2790 "cname", MAKE_VECTOR(kSenderSsrcs), MAKE_VECTOR(kSenderRtxSsrcs)); | |
2791 | |
2792 EXPECT_TRUE(channel_->AddSendStream(sender_sp)); | |
2793 | |
2794 static const uint32_t kReceiverSsrcs[] = {3}; | |
2795 static const uint32_t kReceiverRtxSsrcs[] = {2}; | |
2796 | |
2797 StreamParams receiver_sp = cricket::CreateSimWithRtxStreamParams( | |
2798 "cname", MAKE_VECTOR(kReceiverSsrcs), MAKE_VECTOR(kReceiverRtxSsrcs)); | |
2799 EXPECT_TRUE(channel_->AddRecvStream(receiver_sp)); | |
2800 | |
2801 cricket::VideoMediaInfo info; | |
2802 ASSERT_TRUE(channel_->GetStats(&info)); | |
2803 | |
2804 ASSERT_EQ(1u, info.senders.size()); | |
2805 ASSERT_EQ(1u, info.receivers.size()); | |
2806 | |
2807 EXPECT_NE(sender_sp.ssrc_groups, receiver_sp.ssrc_groups); | |
2808 EXPECT_EQ(sender_sp.ssrc_groups, info.senders[0].ssrc_groups); | |
2809 EXPECT_EQ(receiver_sp.ssrc_groups, info.receivers[0].ssrc_groups); | |
2810 } | |
2811 | |
2812 TEST_F(WebRtcVideoChannel2Test, MapsReceivedPayloadTypeToCodecName) { | |
2813 FakeVideoReceiveStream* stream = AddRecvStream(); | |
2814 webrtc::VideoReceiveStream::Stats stats; | |
2815 cricket::VideoMediaInfo info; | |
2816 | |
2817 // Report no codec name before receiving. | |
2818 stream->SetStats(stats); | |
2819 ASSERT_TRUE(channel_->GetStats(&info)); | |
2820 EXPECT_STREQ("", info.receivers[0].codec_name.c_str()); | |
2821 | |
2822 // Report VP8 if we're receiving it. | |
2823 stats.current_payload_type = kDefaultVp8PlType; | |
2824 stream->SetStats(stats); | |
2825 ASSERT_TRUE(channel_->GetStats(&info)); | |
2826 EXPECT_STREQ(kVp8CodecName, info.receivers[0].codec_name.c_str()); | |
2827 | |
2828 // Report no codec name for unknown playload types. | |
2829 stats.current_payload_type = 3; | |
2830 stream->SetStats(stats); | |
2831 ASSERT_TRUE(channel_->GetStats(&info)); | |
2832 EXPECT_STREQ("", info.receivers[0].codec_name.c_str()); | |
2833 } | |
2834 | |
2835 void WebRtcVideoChannel2Test::TestReceiveUnsignalledSsrcPacket( | |
2836 uint8_t payload_type, | |
2837 bool expect_created_receive_stream) { | |
2838 // Add a RED RTX codec. | |
2839 VideoCodec red_rtx_codec = | |
2840 VideoCodec::CreateRtxCodec(kRedRtxPayloadType, kDefaultRedPlType); | |
2841 recv_parameters_.codecs.push_back(red_rtx_codec); | |
2842 EXPECT_TRUE(channel_->SetRecvParameters(recv_parameters_)); | |
2843 | |
2844 ASSERT_EQ(0u, fake_call_->GetVideoReceiveStreams().size()); | |
2845 const size_t kDataLength = 12; | |
2846 uint8_t data[kDataLength]; | |
2847 memset(data, 0, sizeof(data)); | |
2848 | |
2849 rtc::Set8(data, 1, payload_type); | |
2850 rtc::SetBE32(&data[8], kIncomingUnsignalledSsrc); | |
2851 rtc::Buffer packet(data, kDataLength); | |
2852 rtc::PacketTime packet_time; | |
2853 channel_->OnPacketReceived(&packet, packet_time); | |
2854 | |
2855 if (expect_created_receive_stream) { | |
2856 EXPECT_EQ(1u, fake_call_->GetVideoReceiveStreams().size()) | |
2857 << "Should have created a receive stream for payload type: " | |
2858 << payload_type; | |
2859 } else { | |
2860 EXPECT_EQ(0u, fake_call_->GetVideoReceiveStreams().size()) | |
2861 << "Shouldn't have created a receive stream for payload type: " | |
2862 << payload_type; | |
2863 } | |
2864 } | |
2865 | |
2866 TEST_F(WebRtcVideoChannel2Test, Vp8PacketCreatesUnsignalledStream) { | |
2867 TestReceiveUnsignalledSsrcPacket(kDefaultVp8PlType, true); | |
2868 } | |
2869 | |
2870 TEST_F(WebRtcVideoChannel2Test, Vp9PacketCreatesUnsignalledStream) { | |
2871 TestReceiveUnsignalledSsrcPacket(kDefaultVp9PlType, true); | |
2872 } | |
2873 | |
2874 TEST_F(WebRtcVideoChannel2Test, RtxPacketDoesntCreateUnsignalledStream) { | |
2875 TestReceiveUnsignalledSsrcPacket(kDefaultRtxVp8PlType, false); | |
2876 } | |
2877 | |
2878 TEST_F(WebRtcVideoChannel2Test, UlpfecPacketDoesntCreateUnsignalledStream) { | |
2879 TestReceiveUnsignalledSsrcPacket(kDefaultUlpfecType, false); | |
2880 } | |
2881 | |
2882 TEST_F(WebRtcVideoChannel2Test, RedRtxPacketDoesntCreateUnsignalledStream) { | |
2883 TestReceiveUnsignalledSsrcPacket(kRedRtxPayloadType, false); | |
2884 } | |
2885 | |
2886 void WebRtcVideoChannel2Test::TestReceiverLocalSsrcConfiguration( | |
2887 bool receiver_first) { | |
2888 EXPECT_TRUE(channel_->SetSendParameters(send_parameters_)); | |
2889 | |
2890 const uint32_t kSenderSsrc = 0xC0FFEE; | |
2891 const uint32_t kSecondSenderSsrc = 0xBADCAFE; | |
2892 const uint32_t kReceiverSsrc = 0x4711; | |
2893 const uint32_t kExpectedDefaultReceiverSsrc = 1; | |
2894 | |
2895 if (receiver_first) { | |
2896 AddRecvStream(StreamParams::CreateLegacy(kReceiverSsrc)); | |
2897 std::vector<FakeVideoReceiveStream*> receive_streams = | |
2898 fake_call_->GetVideoReceiveStreams(); | |
2899 ASSERT_EQ(1u, receive_streams.size()); | |
2900 // Default local SSRC when we have no sender. | |
2901 EXPECT_EQ(kExpectedDefaultReceiverSsrc, | |
2902 receive_streams[0]->GetConfig().rtp.local_ssrc); | |
2903 } | |
2904 AddSendStream(StreamParams::CreateLegacy(kSenderSsrc)); | |
2905 if (!receiver_first) | |
2906 AddRecvStream(StreamParams::CreateLegacy(kReceiverSsrc)); | |
2907 std::vector<FakeVideoReceiveStream*> receive_streams = | |
2908 fake_call_->GetVideoReceiveStreams(); | |
2909 ASSERT_EQ(1u, receive_streams.size()); | |
2910 EXPECT_EQ(kSenderSsrc, receive_streams[0]->GetConfig().rtp.local_ssrc); | |
2911 | |
2912 // Removing first sender should fall back to another (in this case the second) | |
2913 // local send stream's SSRC. | |
2914 AddSendStream(StreamParams::CreateLegacy(kSecondSenderSsrc)); | |
2915 ASSERT_TRUE(channel_->RemoveSendStream(kSenderSsrc)); | |
2916 receive_streams = | |
2917 fake_call_->GetVideoReceiveStreams(); | |
2918 ASSERT_EQ(1u, receive_streams.size()); | |
2919 EXPECT_EQ(kSecondSenderSsrc, receive_streams[0]->GetConfig().rtp.local_ssrc); | |
2920 | |
2921 // Removing the last sender should fall back to default local SSRC. | |
2922 ASSERT_TRUE(channel_->RemoveSendStream(kSecondSenderSsrc)); | |
2923 receive_streams = | |
2924 fake_call_->GetVideoReceiveStreams(); | |
2925 ASSERT_EQ(1u, receive_streams.size()); | |
2926 EXPECT_EQ(kExpectedDefaultReceiverSsrc, | |
2927 receive_streams[0]->GetConfig().rtp.local_ssrc); | |
2928 } | |
2929 | |
2930 TEST_F(WebRtcVideoChannel2Test, ConfiguresLocalSsrc) { | |
2931 TestReceiverLocalSsrcConfiguration(false); | |
2932 } | |
2933 | |
2934 TEST_F(WebRtcVideoChannel2Test, ConfiguresLocalSsrcOnExistingReceivers) { | |
2935 TestReceiverLocalSsrcConfiguration(true); | |
2936 } | |
2937 | |
2938 class WebRtcVideoChannel2SimulcastTest : public testing::Test { | |
2939 public: | |
2940 WebRtcVideoChannel2SimulcastTest() : fake_call_(webrtc::Call::Config()) {} | |
2941 | |
2942 void SetUp() override { | |
2943 engine_.Init(); | |
2944 channel_.reset(engine_.CreateChannel(&fake_call_, VideoOptions())); | |
2945 last_ssrc_ = 123; | |
2946 } | |
2947 | |
2948 protected: | |
2949 void VerifySimulcastSettings(const VideoCodec& codec, | |
2950 size_t num_configured_streams, | |
2951 size_t expected_num_streams) { | |
2952 cricket::VideoSendParameters parameters; | |
2953 parameters.codecs.push_back(codec); | |
2954 ASSERT_TRUE(channel_->SetSendParameters(parameters)); | |
2955 | |
2956 std::vector<uint32_t> ssrcs = MAKE_VECTOR(kSsrcs3); | |
2957 RTC_DCHECK(num_configured_streams <= ssrcs.size()); | |
2958 ssrcs.resize(num_configured_streams); | |
2959 | |
2960 FakeVideoSendStream* stream = | |
2961 AddSendStream(CreateSimStreamParams("cname", ssrcs)); | |
2962 // Send a full-size frame to trigger a stream reconfiguration to use all | |
2963 // expected simulcast layers. | |
2964 cricket::FakeVideoCapturer capturer; | |
2965 EXPECT_TRUE(channel_->SetCapturer(ssrcs.front(), &capturer)); | |
2966 EXPECT_EQ(cricket::CS_RUNNING, capturer.Start(cricket::VideoFormat( | |
2967 codec.width, codec.height, | |
2968 cricket::VideoFormat::FpsToInterval(30), | |
2969 cricket::FOURCC_I420))); | |
2970 channel_->SetSend(true); | |
2971 EXPECT_TRUE(capturer.CaptureFrame()); | |
2972 | |
2973 std::vector<webrtc::VideoStream> video_streams = stream->GetVideoStreams(); | |
2974 ASSERT_EQ(expected_num_streams, video_streams.size()); | |
2975 | |
2976 std::vector<webrtc::VideoStream> expected_streams = GetSimulcastConfig( | |
2977 num_configured_streams, codec.width, codec.height, 0, kDefaultQpMax, | |
2978 codec.framerate != 0 ? codec.framerate : kDefaultFramerate); | |
2979 | |
2980 ASSERT_EQ(expected_streams.size(), video_streams.size()); | |
2981 | |
2982 size_t num_streams = video_streams.size(); | |
2983 int total_max_bitrate_bps = 0; | |
2984 for (size_t i = 0; i < num_streams; ++i) { | |
2985 EXPECT_EQ(expected_streams[i].width, video_streams[i].width); | |
2986 EXPECT_EQ(expected_streams[i].height, video_streams[i].height); | |
2987 | |
2988 EXPECT_GT(video_streams[i].max_framerate, 0); | |
2989 EXPECT_EQ(expected_streams[i].max_framerate, | |
2990 video_streams[i].max_framerate); | |
2991 | |
2992 EXPECT_GT(video_streams[i].min_bitrate_bps, 0); | |
2993 EXPECT_EQ(expected_streams[i].min_bitrate_bps, | |
2994 video_streams[i].min_bitrate_bps); | |
2995 | |
2996 EXPECT_GT(video_streams[i].target_bitrate_bps, 0); | |
2997 EXPECT_EQ(expected_streams[i].target_bitrate_bps, | |
2998 video_streams[i].target_bitrate_bps); | |
2999 | |
3000 EXPECT_GT(video_streams[i].max_bitrate_bps, 0); | |
3001 EXPECT_EQ(expected_streams[i].max_bitrate_bps, | |
3002 video_streams[i].max_bitrate_bps); | |
3003 | |
3004 EXPECT_GT(video_streams[i].max_qp, 0); | |
3005 EXPECT_EQ(expected_streams[i].max_qp, video_streams[i].max_qp); | |
3006 | |
3007 EXPECT_FALSE(expected_streams[i].temporal_layer_thresholds_bps.empty()); | |
3008 EXPECT_EQ(expected_streams[i].temporal_layer_thresholds_bps, | |
3009 video_streams[i].temporal_layer_thresholds_bps); | |
3010 | |
3011 if (i == num_streams - 1) { | |
3012 total_max_bitrate_bps += video_streams[i].max_bitrate_bps; | |
3013 } else { | |
3014 total_max_bitrate_bps += video_streams[i].target_bitrate_bps; | |
3015 } | |
3016 } | |
3017 cricket::VideoMediaInfo info; | |
3018 ASSERT_TRUE(channel_->GetStats(&info)); | |
3019 ASSERT_EQ(1u, info.senders.size()); | |
3020 EXPECT_EQ(total_max_bitrate_bps, info.senders[0].preferred_bitrate); | |
3021 | |
3022 EXPECT_TRUE(channel_->SetCapturer(ssrcs.front(), NULL)); | |
3023 } | |
3024 | |
3025 FakeVideoSendStream* AddSendStream() { | |
3026 return AddSendStream(StreamParams::CreateLegacy(last_ssrc_++)); | |
3027 } | |
3028 | |
3029 FakeVideoSendStream* AddSendStream(const StreamParams& sp) { | |
3030 size_t num_streams = | |
3031 fake_call_.GetVideoSendStreams().size(); | |
3032 EXPECT_TRUE(channel_->AddSendStream(sp)); | |
3033 std::vector<FakeVideoSendStream*> streams = | |
3034 fake_call_.GetVideoSendStreams(); | |
3035 EXPECT_EQ(num_streams + 1, streams.size()); | |
3036 return streams[streams.size() - 1]; | |
3037 } | |
3038 | |
3039 std::vector<FakeVideoSendStream*> GetFakeSendStreams() { | |
3040 return fake_call_.GetVideoSendStreams(); | |
3041 } | |
3042 | |
3043 FakeVideoReceiveStream* AddRecvStream() { | |
3044 return AddRecvStream(StreamParams::CreateLegacy(last_ssrc_++)); | |
3045 } | |
3046 | |
3047 FakeVideoReceiveStream* AddRecvStream(const StreamParams& sp) { | |
3048 size_t num_streams = | |
3049 fake_call_.GetVideoReceiveStreams().size(); | |
3050 EXPECT_TRUE(channel_->AddRecvStream(sp)); | |
3051 std::vector<FakeVideoReceiveStream*> streams = | |
3052 fake_call_.GetVideoReceiveStreams(); | |
3053 EXPECT_EQ(num_streams + 1, streams.size()); | |
3054 return streams[streams.size() - 1]; | |
3055 } | |
3056 | |
3057 FakeCall fake_call_; | |
3058 WebRtcVideoEngine2 engine_; | |
3059 rtc::scoped_ptr<VideoMediaChannel> channel_; | |
3060 uint32_t last_ssrc_; | |
3061 }; | |
3062 | |
3063 TEST_F(WebRtcVideoChannel2SimulcastTest, SetSendCodecsWith2SimulcastStreams) { | |
3064 VerifySimulcastSettings(kVp8Codec, 2, 2); | |
3065 } | |
3066 | |
3067 TEST_F(WebRtcVideoChannel2SimulcastTest, SetSendCodecsWith3SimulcastStreams) { | |
3068 VerifySimulcastSettings(kVp8Codec720p, 3, 3); | |
3069 } | |
3070 | |
3071 // Test that we normalize send codec format size in simulcast. | |
3072 TEST_F(WebRtcVideoChannel2SimulcastTest, SetSendCodecsWithOddSizeInSimulcast) { | |
3073 cricket::VideoCodec codec(kVp8Codec270p); | |
3074 codec.width += 1; | |
3075 codec.height += 1; | |
3076 VerifySimulcastSettings(codec, 2, 2); | |
3077 } | |
3078 } // namespace cricket | |
3079 | |
3080 #endif // HAVE_WEBRTC_VIDEO | |
OLD | NEW |