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