videoconduit_unittests.cpp (109656B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #define GTEST_HAS_RTTI 0 6 #include "gtest/gtest.h" 7 8 #include "nss.h" 9 10 #include "Canonicals.h" 11 #include "ImageContainer.h" 12 #include "VideoConduit.h" 13 #include "VideoFrameConverter.h" 14 #include "RtpRtcpConfig.h" 15 16 #include "api/video/i420_buffer.h" 17 #include "api/video/video_sink_interface.h" 18 #include "media/base/media_constants.h" 19 20 #include "MockCall.h" 21 #include "MockConduit.h" 22 23 using namespace mozilla; 24 using namespace mozilla::layers; 25 using namespace testing; 26 using namespace webrtc; 27 28 namespace test { 29 30 class MockVideoSink : public webrtc::VideoSinkInterface<webrtc::VideoFrame> { 31 public: 32 MockVideoSink() : mVideoFrame(nullptr, kVideoRotation_0, 0) {} 33 34 ~MockVideoSink() override = default; 35 36 void OnFrame(const webrtc::VideoFrame& frame) override { 37 mVideoFrame = frame; 38 ++mOnFrameCount; 39 } 40 41 size_t mOnFrameCount = 0; 42 webrtc::VideoFrame mVideoFrame; 43 }; 44 45 struct TestRTCStatsTimestampState : public dom::RTCStatsTimestampState { 46 TestRTCStatsTimestampState() 47 : dom::RTCStatsTimestampState( 48 TimeStamp::Now() + TimeDuration::FromMilliseconds(10), 49 webrtc::Timestamp::Micros(0)) {} 50 }; 51 52 class TestRTCStatsTimestampMaker : public dom::RTCStatsTimestampMaker { 53 public: 54 TestRTCStatsTimestampMaker() 55 : dom::RTCStatsTimestampMaker(TestRTCStatsTimestampState()) {} 56 }; 57 58 class DirectVideoFrameConverter : public VideoFrameConverter { 59 public: 60 explicit DirectVideoFrameConverter(bool aLockScaling) 61 : VideoFrameConverter(do_AddRef(GetMainThreadSerialEventTarget()), 62 TestRTCStatsTimestampMaker(), aLockScaling) {} 63 64 void SendVideoFrame(PlanarYCbCrImage* aImage, TimeStamp aTime) { 65 FrameToProcess frame(aImage, aTime, aImage->GetSize(), false); 66 ProcessVideoFrame(frame); 67 } 68 }; 69 70 static uint32_t sTrackingIdCounter = 0; 71 class VideoConduitTest : public Test { 72 public: 73 VideoConduitTest( 74 VideoSessionConduit::Options aOptions = VideoSessionConduit::Options()) 75 : mCallWrapper(MockCallWrapper::Create()), 76 mTrackingId(TrackingId::Source::Camera, ++sTrackingIdCounter), 77 mImageContainer(MakeRefPtr<ImageContainer>( 78 ImageUsageType::Webrtc, ImageContainer::SYNCHRONOUS)), 79 mVideoFrameConverter( 80 MakeRefPtr<DirectVideoFrameConverter>(aOptions.mLockScaling)), 81 mVideoSink(MakeUnique<MockVideoSink>()), 82 mVideoConduit(MakeRefPtr<WebrtcVideoConduit>( 83 mCallWrapper, GetCurrentSerialEventTarget(), std::move(aOptions), 84 "", mTrackingId)), 85 mControl(GetCurrentSerialEventTarget()) { 86 NSS_NoDB_Init(nullptr); 87 88 EXPECT_EQ(mVideoConduit->Init(), kMediaConduitNoError); 89 mControl.Update([&](auto& aControl) { 90 mVideoConduit->InitControl(&mControl); 91 mVideoConduit->SetTrackSource(mVideoFrameConverter); 92 mVideoFrameConverter->SetTrackingId(mTrackingId); 93 mVideoFrameConverter->AddOrUpdateSink(mVideoSink.get(), {}); 94 aControl.mLocalSsrcs = {42}; 95 aControl.mLocalVideoRtxSsrcs = {43}; 96 }); 97 } 98 99 ~VideoConduitTest() override { 100 mVideoFrameConverter->RemoveSink(mVideoSink.get()); 101 (void)WaitFor(mVideoConduit->Shutdown()); 102 mCallWrapper->Destroy(); 103 } 104 105 MockCall* Call() { return mCallWrapper->GetMockCall(); } 106 107 void SendVideoFrame(unsigned short width, unsigned short height, 108 int64_t capture_time_ms) { 109 webrtc::scoped_refptr<webrtc::I420Buffer> buffer = 110 webrtc::I420Buffer::Create(width, height); 111 memset(buffer->MutableDataY(), 0x10, buffer->StrideY() * buffer->height()); 112 memset(buffer->MutableDataU(), 0x80, 113 buffer->StrideU() * ((buffer->height() + 1) / 2)); 114 memset(buffer->MutableDataV(), 0x80, 115 buffer->StrideV() * ((buffer->height() + 1) / 2)); 116 117 PlanarYCbCrData data; 118 data.mYChannel = buffer->MutableDataY(); 119 data.mYStride = buffer->StrideY(); 120 data.mCbChannel = buffer->MutableDataU(); 121 data.mCrChannel = buffer->MutableDataV(); 122 MOZ_RELEASE_ASSERT(buffer->StrideU() == buffer->StrideV()); 123 data.mCbCrStride = buffer->StrideU(); 124 data.mChromaSubsampling = gfx::ChromaSubsampling::HALF_WIDTH_AND_HEIGHT; 125 data.mPictureRect = {0, 0, width, height}; 126 data.mStereoMode = StereoMode::MONO; 127 data.mYUVColorSpace = gfx::YUVColorSpace::BT601; 128 data.mColorDepth = gfx::ColorDepth::COLOR_8; 129 data.mColorRange = gfx::ColorRange::LIMITED; 130 131 RefPtr image = mImageContainer->CreatePlanarYCbCrImage(); 132 MOZ_ALWAYS_SUCCEEDS(image->CopyData(data)); 133 TimeStamp time = 134 mVideoFrameConverter->mTimestampMaker.mState.mStartDomRealtime + 135 TimeDuration::FromMilliseconds(capture_time_ms); 136 137 mVideoFrameConverter->SendVideoFrame(image, time); 138 } 139 140 const RefPtr<MockCallWrapper> mCallWrapper; 141 const TrackingId mTrackingId; 142 const RefPtr<layers::ImageContainer> mImageContainer; 143 const RefPtr<DirectVideoFrameConverter> mVideoFrameConverter; 144 const UniquePtr<MockVideoSink> mVideoSink; 145 const RefPtr<mozilla::WebrtcVideoConduit> mVideoConduit; 146 ConcreteControl mControl; 147 }; 148 149 class VideoConduitCodecModeTest 150 : public VideoConduitTest, 151 public WithParamInterface<webrtc::VideoCodecMode> {}; 152 153 INSTANTIATE_TEST_SUITE_P(WebRtcCodecModes, VideoConduitCodecModeTest, 154 Values(webrtc::VideoCodecMode::kRealtimeVideo, 155 webrtc::VideoCodecMode::kScreensharing)); 156 157 TEST_F(VideoConduitTest, TestConfigureReceiveMediaCodecs) { 158 // No codecs 159 mControl.Update([&](auto& aControl) { 160 aControl.mReceiving = true; 161 aControl.mVideoRecvCodecs = {}; 162 }); 163 ASSERT_TRUE(Call()->mVideoReceiveConfig); 164 ASSERT_EQ(Call()->mVideoReceiveConfig->decoders.size(), 0U); 165 166 // empty codec name 167 mControl.Update([&](auto& aControl) { 168 VideoCodecConfig codec(120, "", VideoEncodingConstraints()); 169 aControl.mVideoRecvCodecs = {codec}; 170 }); 171 ASSERT_TRUE(Call()->mVideoReceiveConfig); 172 ASSERT_EQ(Call()->mVideoReceiveConfig->decoders.size(), 0U); 173 174 // Defaults 175 mControl.Update([&](auto& aControl) { 176 VideoCodecConfig codec(120, "VP8", VideoEncodingConstraints()); 177 aControl.mVideoRecvCodecs = {codec}; 178 aControl.mVideoRecvRtpRtcpConfig = 179 Some(RtpRtcpConfig(webrtc::RtcpMode::kCompound, true)); 180 }); 181 ASSERT_TRUE(Call()->mVideoReceiveConfig); 182 ASSERT_EQ(Call()->mVideoReceiveConfig->decoders.size(), 1U); 183 ASSERT_EQ(Call()->mVideoReceiveConfig->decoders[0].payload_type, 120); 184 ASSERT_EQ(Call()->mVideoReceiveConfig->decoders[0].video_format.name, "VP8"); 185 ASSERT_NE(Call()->mVideoReceiveConfig->rtp.local_ssrc, 0U); 186 ASSERT_NE(Call()->mVideoReceiveConfig->rtp.remote_ssrc, 0U); 187 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.rtcp_mode, 188 webrtc::RtcpMode::kCompound); 189 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.nack.rtp_history_ms, 0); 190 ASSERT_FALSE(Call()->mVideoReceiveConfig->rtp.remb); 191 ASSERT_FALSE(Call()->mVideoReceiveConfig->rtp.tmmbr); 192 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.keyframe_method, 193 webrtc::KeyFrameReqMethod::kNone); 194 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.ulpfec_payload_type, -1); 195 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.red_payload_type, -1); 196 ASSERT_EQ( 197 Call()->mVideoReceiveConfig->rtp.rtx_associated_payload_types.size(), 0U); 198 } 199 200 TEST_F(VideoConduitTest, TestConfigureReceiveMediaCodecsFEC) { 201 mControl.Update([&](auto& aControl) { 202 VideoCodecConfig codecConfig(120, "VP8", VideoEncodingConstraints()); 203 codecConfig.mFECFbSet = true; 204 aControl.mVideoRecvCodecs = { 205 codecConfig, VideoCodecConfig(1, "ulpfec", VideoEncodingConstraints()), 206 VideoCodecConfig(2, "red", VideoEncodingConstraints())}; 207 aControl.mVideoRecvRtpRtcpConfig = 208 Some(RtpRtcpConfig(webrtc::RtcpMode::kCompound, true)); 209 aControl.mReceiving = true; 210 }); 211 ASSERT_TRUE(Call()->mVideoReceiveConfig); 212 ASSERT_EQ(Call()->mVideoReceiveConfig->decoders.size(), 1U); 213 ASSERT_EQ(Call()->mVideoReceiveConfig->decoders[0].payload_type, 120); 214 ASSERT_EQ(Call()->mVideoReceiveConfig->decoders[0].video_format.name, "VP8"); 215 ASSERT_NE(Call()->mVideoReceiveConfig->rtp.local_ssrc, 0U); 216 ASSERT_NE(Call()->mVideoReceiveConfig->rtp.remote_ssrc, 0U); 217 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.rtcp_mode, 218 webrtc::RtcpMode::kCompound); 219 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.nack.rtp_history_ms, 0); 220 ASSERT_FALSE(Call()->mVideoReceiveConfig->rtp.remb); 221 ASSERT_FALSE(Call()->mVideoReceiveConfig->rtp.tmmbr); 222 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.keyframe_method, 223 webrtc::KeyFrameReqMethod::kNone); 224 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.ulpfec_payload_type, 1); 225 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.red_payload_type, 2); 226 ASSERT_EQ( 227 Call()->mVideoReceiveConfig->rtp.rtx_associated_payload_types.size(), 0U); 228 } 229 230 TEST_F(VideoConduitTest, TestConfigureReceiveMediaCodecsH264) { 231 mControl.Update([&](auto& aControl) { 232 aControl.mReceiving = true; 233 aControl.mVideoRecvCodecs = { 234 VideoCodecConfig(120, "H264", VideoEncodingConstraints())}; 235 aControl.mVideoRecvRtpRtcpConfig = 236 Some(RtpRtcpConfig(webrtc::RtcpMode::kCompound, true)); 237 }); 238 ASSERT_TRUE(Call()->mVideoReceiveConfig); 239 ASSERT_EQ(Call()->mVideoReceiveConfig->decoders.size(), 1U); 240 ASSERT_EQ(Call()->mVideoReceiveConfig->decoders[0].payload_type, 120); 241 ASSERT_EQ(Call()->mVideoReceiveConfig->decoders[0].video_format.name, "H264"); 242 ASSERT_NE(Call()->mVideoReceiveConfig->rtp.local_ssrc, 0U); 243 ASSERT_NE(Call()->mVideoReceiveConfig->rtp.remote_ssrc, 0U); 244 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.rtcp_mode, 245 webrtc::RtcpMode::kCompound); 246 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.nack.rtp_history_ms, 0); 247 ASSERT_FALSE(Call()->mVideoReceiveConfig->rtp.remb); 248 ASSERT_FALSE(Call()->mVideoReceiveConfig->rtp.tmmbr); 249 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.keyframe_method, 250 webrtc::KeyFrameReqMethod::kNone); 251 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.ulpfec_payload_type, -1); 252 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.red_payload_type, -1); 253 ASSERT_EQ( 254 Call()->mVideoReceiveConfig->rtp.rtx_associated_payload_types.size(), 0U); 255 } 256 257 TEST_F(VideoConduitTest, TestConfigureReceiveMediaCodecsMultipleH264) { 258 mControl.Update([&](auto& aControl) { 259 // Insert two H264 codecs to test that the receive stream knows about both. 260 aControl.mReceiving = true; 261 VideoCodecConfig h264_b(126, "H264", VideoEncodingConstraints()); 262 h264_b.mProfile = 0x42; 263 h264_b.mConstraints = 0xE0; 264 h264_b.mLevel = 0x01; 265 VideoCodecConfig h264_h(105, "H264", VideoEncodingConstraints()); 266 h264_h.mProfile = 0x64; 267 h264_h.mConstraints = 0xE0; 268 h264_h.mLevel = 0x01; 269 aControl.mVideoRecvCodecs = {h264_b, h264_h}; 270 aControl.mVideoRecvRtpRtcpConfig = 271 Some(RtpRtcpConfig(webrtc::RtcpMode::kCompound, true)); 272 }); 273 ASSERT_TRUE(Call()->mVideoReceiveConfig); 274 ASSERT_EQ(Call()->mVideoReceiveConfig->decoders.size(), 2U); 275 ASSERT_EQ(Call()->mVideoReceiveConfig->decoders[0].payload_type, 126); 276 ASSERT_EQ(Call()->mVideoReceiveConfig->decoders[0].video_format.name, "H264"); 277 ASSERT_EQ(Call()->mVideoReceiveConfig->decoders[1].payload_type, 105); 278 ASSERT_EQ(Call()->mVideoReceiveConfig->decoders[1].video_format.name, "H264"); 279 ASSERT_NE(Call()->mVideoReceiveConfig->rtp.local_ssrc, 0U); 280 ASSERT_NE(Call()->mVideoReceiveConfig->rtp.remote_ssrc, 0U); 281 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.rtcp_mode, 282 webrtc::RtcpMode::kCompound); 283 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.nack.rtp_history_ms, 0); 284 ASSERT_FALSE(Call()->mVideoReceiveConfig->rtp.remb); 285 ASSERT_FALSE(Call()->mVideoReceiveConfig->rtp.tmmbr); 286 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.keyframe_method, 287 webrtc::KeyFrameReqMethod::kNone); 288 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.ulpfec_payload_type, -1); 289 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.red_payload_type, -1); 290 ASSERT_EQ( 291 Call()->mVideoReceiveConfig->rtp.rtx_associated_payload_types.size(), 0U); 292 } 293 294 TEST_F(VideoConduitTest, TestConfigureReceiveMediaCodecsKeyframeRequestType) { 295 // PLI should be preferred to FIR, same codec. 296 mControl.Update([&](auto& aControl) { 297 VideoCodecConfig codecConfig(120, "VP8", VideoEncodingConstraints()); 298 codecConfig.mNackFbTypes.push_back("pli"); 299 codecConfig.mCcmFbTypes.push_back("fir"); 300 aControl.mReceiving = true; 301 aControl.mVideoRecvCodecs = {codecConfig}; 302 aControl.mVideoRecvRtpRtcpConfig = 303 Some(RtpRtcpConfig(webrtc::RtcpMode::kCompound, true)); 304 }); 305 ASSERT_TRUE(Call()->mVideoReceiveConfig); 306 ASSERT_EQ(Call()->mVideoReceiveConfig->decoders.size(), 1U); 307 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.keyframe_method, 308 webrtc::KeyFrameReqMethod::kPliRtcp); 309 310 // Just FIR 311 mControl.Update([&](auto& aControl) { 312 VideoCodecConfig codecConfig(120, "VP8", VideoEncodingConstraints()); 313 codecConfig.mCcmFbTypes.push_back("fir"); 314 aControl.mVideoRecvCodecs = {codecConfig}; 315 }); 316 ASSERT_TRUE(Call()->mVideoReceiveConfig); 317 ASSERT_EQ(Call()->mVideoReceiveConfig->decoders.size(), 1U); 318 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.keyframe_method, 319 webrtc::KeyFrameReqMethod::kFirRtcp); 320 321 // PLI should be preferred to FIR, multiple codecs. 322 mControl.Update([&](auto& aControl) { 323 VideoCodecConfig pliCodec(120, "VP8", VideoEncodingConstraints()); 324 pliCodec.mNackFbTypes.push_back("pli"); 325 VideoCodecConfig firCodec(120, "VP8", VideoEncodingConstraints()); 326 firCodec.mCcmFbTypes.push_back("fir"); 327 aControl.mVideoRecvCodecs = {pliCodec, firCodec}; 328 }); 329 ASSERT_TRUE(Call()->mVideoReceiveConfig); 330 ASSERT_EQ(Call()->mVideoReceiveConfig->decoders.size(), 2U); 331 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.keyframe_method, 332 webrtc::KeyFrameReqMethod::kPliRtcp); 333 } 334 335 TEST_F(VideoConduitTest, TestConfigureReceiveMediaCodecsNack) { 336 mControl.Update([&](auto& aControl) { 337 aControl.mReceiving = true; 338 VideoCodecConfig codecConfig(120, "VP8", VideoEncodingConstraints()); 339 codecConfig.mNackFbTypes.push_back(""); 340 aControl.mVideoRecvCodecs = {codecConfig}; 341 aControl.mVideoRecvRtpRtcpConfig = 342 Some(RtpRtcpConfig(webrtc::RtcpMode::kCompound, true)); 343 }); 344 ASSERT_TRUE(Call()->mVideoReceiveConfig); 345 ASSERT_EQ(Call()->mVideoReceiveConfig->decoders.size(), 1U); 346 ASSERT_EQ(Call()->mVideoReceiveConfig->decoders[0].payload_type, 120); 347 ASSERT_EQ(Call()->mVideoReceiveConfig->decoders[0].video_format.name, "VP8"); 348 ASSERT_NE(Call()->mVideoReceiveConfig->rtp.local_ssrc, 0U); 349 ASSERT_NE(Call()->mVideoReceiveConfig->rtp.remote_ssrc, 0U); 350 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.rtcp_mode, 351 webrtc::RtcpMode::kCompound); 352 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.nack.rtp_history_ms, 1000); 353 ASSERT_FALSE(Call()->mVideoReceiveConfig->rtp.remb); 354 ASSERT_FALSE(Call()->mVideoReceiveConfig->rtp.tmmbr); 355 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.keyframe_method, 356 webrtc::KeyFrameReqMethod::kNone); 357 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.ulpfec_payload_type, -1); 358 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.red_payload_type, -1); 359 ASSERT_EQ( 360 Call()->mVideoReceiveConfig->rtp.rtx_associated_payload_types.size(), 0U); 361 } 362 363 TEST_F(VideoConduitTest, TestConfigureReceiveMediaCodecsRemb) { 364 mControl.Update([&](auto& aControl) { 365 aControl.mReceiving = true; 366 VideoCodecConfig codecConfig(120, "VP8", VideoEncodingConstraints()); 367 codecConfig.mRembFbSet = true; 368 aControl.mVideoRecvCodecs = {codecConfig}; 369 aControl.mVideoRecvRtpRtcpConfig = 370 Some(RtpRtcpConfig(webrtc::RtcpMode::kCompound, true)); 371 }); 372 ASSERT_TRUE(Call()->mVideoReceiveConfig); 373 ASSERT_EQ(Call()->mVideoReceiveConfig->decoders.size(), 1U); 374 ASSERT_EQ(Call()->mVideoReceiveConfig->decoders[0].payload_type, 120); 375 ASSERT_EQ(Call()->mVideoReceiveConfig->decoders[0].video_format.name, "VP8"); 376 ASSERT_NE(Call()->mVideoReceiveConfig->rtp.local_ssrc, 0U); 377 ASSERT_NE(Call()->mVideoReceiveConfig->rtp.remote_ssrc, 0U); 378 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.rtcp_mode, 379 webrtc::RtcpMode::kCompound); 380 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.nack.rtp_history_ms, 0); 381 ASSERT_TRUE(Call()->mVideoReceiveConfig->rtp.remb); 382 ASSERT_FALSE(Call()->mVideoReceiveConfig->rtp.tmmbr); 383 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.keyframe_method, 384 webrtc::KeyFrameReqMethod::kNone); 385 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.ulpfec_payload_type, -1); 386 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.red_payload_type, -1); 387 ASSERT_EQ( 388 Call()->mVideoReceiveConfig->rtp.rtx_associated_payload_types.size(), 0U); 389 } 390 391 TEST_F(VideoConduitTest, TestConfigureReceiveMediaCodecsTmmbr) { 392 mControl.Update([&](auto& aControl) { 393 aControl.mReceiving = true; 394 VideoCodecConfig codecConfig(120, "VP8", VideoEncodingConstraints()); 395 codecConfig.mCcmFbTypes.push_back("tmmbr"); 396 aControl.mVideoRecvCodecs = {codecConfig}; 397 aControl.mVideoRecvRtpRtcpConfig = 398 Some(RtpRtcpConfig(webrtc::RtcpMode::kCompound, true)); 399 }); 400 ASSERT_TRUE(Call()->mVideoReceiveConfig); 401 ASSERT_EQ(Call()->mVideoReceiveConfig->decoders.size(), 1U); 402 ASSERT_EQ(Call()->mVideoReceiveConfig->decoders[0].payload_type, 120); 403 ASSERT_EQ(Call()->mVideoReceiveConfig->decoders[0].video_format.name, "VP8"); 404 ASSERT_NE(Call()->mVideoReceiveConfig->rtp.local_ssrc, 0U); 405 ASSERT_NE(Call()->mVideoReceiveConfig->rtp.remote_ssrc, 0U); 406 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.rtcp_mode, 407 webrtc::RtcpMode::kCompound); 408 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.nack.rtp_history_ms, 0); 409 ASSERT_FALSE(Call()->mVideoReceiveConfig->rtp.remb); 410 ASSERT_TRUE(Call()->mVideoReceiveConfig->rtp.tmmbr); 411 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.keyframe_method, 412 webrtc::KeyFrameReqMethod::kNone); 413 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.ulpfec_payload_type, -1); 414 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.red_payload_type, -1); 415 ASSERT_EQ( 416 Call()->mVideoReceiveConfig->rtp.rtx_associated_payload_types.size(), 0U); 417 } 418 419 TEST_F(VideoConduitTest, TestConfigureSendMediaCodec) { 420 // defaults 421 mControl.Update([&](auto& aControl) { 422 aControl.mTransmitting = true; 423 VideoCodecConfig codecConfig(120, "VP8", VideoEncodingConstraints()); 424 codecConfig.mEncodings.emplace_back(); 425 aControl.mVideoSendCodec = Some(codecConfig); 426 aControl.mVideoSendRtpRtcpConfig = 427 Some(RtpRtcpConfig(webrtc::RtcpMode::kCompound, true)); 428 }); 429 ASSERT_TRUE(Call()->mVideoSendConfig); 430 ASSERT_EQ(Call()->mVideoSendConfig->rtp.payload_name, "VP8"); 431 ASSERT_EQ(Call()->mVideoSendConfig->rtp.payload_type, 120); 432 ASSERT_EQ(Call()->mVideoSendConfig->rtp.rtcp_mode, 433 webrtc::RtcpMode::kCompound); 434 ASSERT_EQ(Call()->mVideoSendConfig->rtp.max_packet_size, mozilla::kVideoMtu); 435 ASSERT_EQ(Call()->mVideoSendEncoderConfig->content_type, 436 VideoEncoderConfig::ContentType::kRealtimeVideo); 437 ASSERT_EQ(Call()->mVideoSendEncoderConfig->min_transmit_bitrate_bps, 0); 438 ASSERT_EQ(Call()->mVideoSendEncoderConfig->max_bitrate_bps, KBPS(10000)); 439 ASSERT_EQ(Call()->mVideoSendEncoderConfig->number_of_streams, 1U); 440 ASSERT_EQ( 441 Call()->mVideoSendEncoderConfig->simulcast_layers[0].max_bitrate_bps, 442 KBPS(10000)); 443 444 // empty codec name 445 mControl.Update([&](auto& aControl) { 446 aControl.mVideoSendCodec = 447 Some(VideoCodecConfig(120, "", VideoEncodingConstraints())); 448 }); 449 // Bad codec gets ignored 450 ASSERT_EQ(Call()->mVideoSendConfig->rtp.payload_name, "VP8"); 451 } 452 453 TEST_F(VideoConduitTest, TestConfigureSendMediaCodecMaxFps) { 454 mControl.Update([&](auto& aControl) { 455 aControl.mTransmitting = true; 456 VideoEncodingConstraints constraints; 457 VideoCodecConfig codecConfig(120, "VP8", constraints); 458 codecConfig.mEncodings.emplace_back(); 459 aControl.mVideoSendCodec = Some(codecConfig); 460 aControl.mVideoSendRtpRtcpConfig = 461 Some(RtpRtcpConfig(webrtc::RtcpMode::kCompound, true)); 462 }); 463 ASSERT_TRUE(Call()->mVideoSendEncoderConfig); 464 std::vector<webrtc::VideoStream> videoStreams; 465 videoStreams = Call()->CreateEncoderStreams(640, 480); 466 ASSERT_EQ(videoStreams.size(), 1U); 467 ASSERT_EQ(videoStreams[0].max_framerate, 30); // DEFAULT_VIDEO_MAX_FRAMERATE 468 469 mControl.Update([&](auto& aControl) { 470 VideoEncodingConstraints constraints; 471 constraints.maxFps = Some(42); 472 VideoCodecConfig codecConfig(120, "VP8", constraints); 473 codecConfig.mEncodings.emplace_back(); 474 aControl.mVideoSendCodec = Some(codecConfig); 475 }); 476 ASSERT_TRUE(Call()->mVideoSendEncoderConfig); 477 videoStreams = Call()->CreateEncoderStreams(640, 480); 478 ASSERT_EQ(videoStreams.size(), 1U); 479 ASSERT_EQ(videoStreams[0].max_framerate, 42); 480 } 481 482 TEST_F(VideoConduitTest, TestConfigureSendMediaCodecMaxMbps) { 483 mControl.Update([&](auto& aControl) { 484 aControl.mTransmitting = true; 485 VideoEncodingConstraints constraints; 486 constraints.maxMbps = 0; 487 VideoCodecConfig codecConfig(120, "VP8", constraints); 488 codecConfig.mEncodings.emplace_back(); 489 aControl.mVideoSendCodec = Some(codecConfig); 490 aControl.mVideoSendRtpRtcpConfig = 491 Some(RtpRtcpConfig(webrtc::RtcpMode::kCompound, true)); 492 }); 493 ASSERT_TRUE(Call()->mVideoSendEncoderConfig); 494 SendVideoFrame(640, 480, 1); 495 std::vector<webrtc::VideoStream> videoStreams; 496 videoStreams = Call()->CreateEncoderStreams(640, 480); 497 ASSERT_EQ(videoStreams.size(), 1U); 498 ASSERT_EQ(videoStreams[0].max_framerate, 30); // DEFAULT_VIDEO_MAX_FRAMERATE 499 500 mControl.Update([&](auto& aControl) { 501 VideoEncodingConstraints constraints; 502 constraints.maxMbps = 10000; 503 VideoCodecConfig codecConfig(120, "VP8", constraints); 504 codecConfig.mEncodings.emplace_back(); 505 aControl.mVideoSendCodec = Some(codecConfig); 506 }); 507 ASSERT_TRUE(Call()->mVideoSendEncoderConfig); 508 SendVideoFrame(640, 480, 2); 509 videoStreams = Call()->CreateEncoderStreams(640, 480); 510 ASSERT_EQ(videoStreams.size(), 1U); 511 ASSERT_EQ(videoStreams[0].max_framerate, 8); 512 } 513 514 TEST_F(VideoConduitTest, TestConfigureSendMediaCodecDefaults) { 515 mControl.Update([&](auto& aControl) { 516 aControl.mTransmitting = true; 517 VideoCodecConfig codecConfig(120, "VP8", VideoEncodingConstraints()); 518 codecConfig.mEncodings.emplace_back(); 519 aControl.mVideoSendCodec = Some(codecConfig); 520 aControl.mVideoSendRtpRtcpConfig = 521 Some(RtpRtcpConfig(webrtc::RtcpMode::kCompound, true)); 522 }); 523 524 { 525 ASSERT_TRUE(Call()->mVideoSendEncoderConfig); 526 const std::vector<webrtc::VideoStream> videoStreams = 527 Call()->CreateEncoderStreams(640, 480); 528 EXPECT_EQ(videoStreams.size(), 1U); 529 EXPECT_EQ(videoStreams[0].min_bitrate_bps, 150000); 530 EXPECT_EQ(videoStreams[0].target_bitrate_bps, 500000); 531 EXPECT_EQ(videoStreams[0].max_bitrate_bps, 2000000); 532 } 533 534 { 535 // SelectBitrates not called until we send a frame 536 SendVideoFrame(1280, 720, 1); 537 const std::vector<webrtc::VideoStream> videoStreams = 538 Call()->CreateEncoderStreams(1280, 720); 539 EXPECT_EQ(videoStreams.size(), 1U); 540 EXPECT_EQ(videoStreams[0].min_bitrate_bps, 1200000); 541 EXPECT_EQ(videoStreams[0].target_bitrate_bps, 1500000); 542 EXPECT_EQ(videoStreams[0].max_bitrate_bps, 5000000); 543 } 544 } 545 546 TEST_F(VideoConduitTest, TestConfigureSendMediaCodecTias) { 547 // TIAS 548 mControl.Update([&](auto& aControl) { 549 aControl.mTransmitting = true; 550 VideoCodecConfig codecConfigTias(120, "VP8", VideoEncodingConstraints()); 551 codecConfigTias.mEncodings.emplace_back(); 552 codecConfigTias.mTias = 2000000; 553 aControl.mVideoSendCodec = Some(codecConfigTias); 554 aControl.mVideoSendRtpRtcpConfig = 555 Some(RtpRtcpConfig(webrtc::RtcpMode::kCompound, true)); 556 }); 557 { 558 ASSERT_TRUE(Call()->mVideoSendEncoderConfig); 559 ASSERT_EQ(Call()->mVideoSendEncoderConfig->max_bitrate_bps, 2000000); 560 ASSERT_EQ(Call()->mVideoSendEncoderConfig->number_of_streams, 1U); 561 ASSERT_EQ( 562 Call()->mVideoSendEncoderConfig->simulcast_layers[0].max_bitrate_bps, 563 2000000); 564 SendVideoFrame(1280, 720, 1); 565 const std::vector<webrtc::VideoStream> videoStreams = 566 Call()->CreateEncoderStreams(1280, 720); 567 ASSERT_EQ(videoStreams.size(), 1U); 568 ASSERT_EQ(videoStreams[0].min_bitrate_bps, 1200000); 569 ASSERT_EQ(videoStreams[0].target_bitrate_bps, 1500000); 570 ASSERT_EQ(videoStreams[0].max_bitrate_bps, 2000000); 571 } 572 573 // TIAS (too low) 574 mControl.Update([&](auto& aControl) { 575 VideoCodecConfig codecConfigTiasLow(120, "VP8", VideoEncodingConstraints()); 576 codecConfigTiasLow.mEncodings.emplace_back(); 577 codecConfigTiasLow.mTias = 1000; 578 aControl.mVideoSendCodec = Some(codecConfigTiasLow); 579 }); 580 { 581 ASSERT_TRUE(Call()->mVideoSendEncoderConfig); 582 ASSERT_EQ(Call()->mVideoSendEncoderConfig->max_bitrate_bps, 1000); 583 ASSERT_EQ(Call()->mVideoSendEncoderConfig->number_of_streams, 1U); 584 ASSERT_EQ( 585 Call()->mVideoSendEncoderConfig->simulcast_layers[0].max_bitrate_bps, 586 1000); 587 SendVideoFrame(1280, 720, 2); 588 const std::vector<webrtc::VideoStream> videoStreams = 589 Call()->CreateEncoderStreams(1280, 720); 590 ASSERT_EQ(videoStreams.size(), 1U); 591 ASSERT_EQ(videoStreams[0].min_bitrate_bps, 30000); 592 ASSERT_EQ(videoStreams[0].target_bitrate_bps, 30000); 593 ASSERT_EQ(videoStreams[0].max_bitrate_bps, 30000); 594 } 595 } 596 597 TEST_F(VideoConduitTest, TestConfigureSendMediaCodecMaxBr) { 598 mControl.Update([&](auto& aControl) { 599 aControl.mTransmitting = true; 600 VideoCodecConfig codecConfig(120, "VP8", VideoEncodingConstraints()); 601 auto& encoding = codecConfig.mEncodings.emplace_back(); 602 encoding.constraints.maxBr = 50000; 603 aControl.mVideoSendCodec = Some(codecConfig); 604 aControl.mVideoSendRtpRtcpConfig = 605 Some(RtpRtcpConfig(webrtc::RtcpMode::kCompound, true)); 606 }); 607 ASSERT_TRUE(Call()->mVideoSendEncoderConfig); 608 ASSERT_EQ(Call()->mVideoSendEncoderConfig->max_bitrate_bps, 50000); 609 ASSERT_EQ(Call()->mVideoSendEncoderConfig->number_of_streams, 1U); 610 ASSERT_EQ( 611 Call()->mVideoSendEncoderConfig->simulcast_layers[0].max_bitrate_bps, 612 50000); 613 SendVideoFrame(1280, 720, 1); 614 const std::vector<webrtc::VideoStream> videoStreams = 615 Call()->CreateEncoderStreams(1280, 720); 616 ASSERT_EQ(videoStreams.size(), 1U); 617 ASSERT_LE(videoStreams[0].min_bitrate_bps, 50000); 618 ASSERT_LE(videoStreams[0].target_bitrate_bps, 50000); 619 ASSERT_EQ(videoStreams[0].max_bitrate_bps, 50000); 620 } 621 622 TEST_F(VideoConduitTest, TestConfigureSendMediaCodecScaleResolutionBy) { 623 mControl.Update([&](auto& aControl) { 624 aControl.mTransmitting = true; 625 VideoCodecConfig codecConfig(120, "VP8", VideoEncodingConstraints()); 626 { 627 auto& encoding = codecConfig.mEncodings.emplace_back(); 628 encoding.constraints.scaleDownBy = 2; 629 } 630 { 631 auto& encoding = codecConfig.mEncodings.emplace_back(); 632 encoding.constraints.scaleDownBy = 4; 633 } 634 aControl.mVideoSendCodec = Some(codecConfig); 635 aControl.mVideoSendRtpRtcpConfig = 636 Some(RtpRtcpConfig(webrtc::RtcpMode::kCompound, true)); 637 aControl.mLocalSsrcs = {42, 1729}; 638 aControl.mLocalVideoRtxSsrcs = {43, 1730}; 639 }); 640 ASSERT_TRUE(Call()->mVideoSendEncoderConfig); 641 642 SendVideoFrame(640, 360, 1); 643 const std::vector<webrtc::VideoStream> videoStreams = 644 Call()->CreateEncoderStreams(mVideoSink->mVideoFrame.width(), 645 mVideoSink->mVideoFrame.height()); 646 ASSERT_EQ(videoStreams.size(), 2U); 647 ASSERT_EQ(videoStreams[0].width, 320U); 648 ASSERT_EQ(videoStreams[0].height, 180U); 649 ASSERT_EQ(videoStreams[1].width, 160U); 650 ASSERT_EQ(videoStreams[1].height, 90U); 651 } 652 653 TEST_F(VideoConduitTest, TestConfigureSendMediaCodecCodecMode) { 654 mControl.Update([&](auto& aControl) { 655 aControl.mTransmitting = true; 656 VideoCodecConfig codecConfig(120, "VP8", VideoEncodingConstraints()); 657 codecConfig.mEncodings.emplace_back(); 658 aControl.mVideoSendCodec = Some(codecConfig); 659 aControl.mVideoSendRtpRtcpConfig = 660 Some(RtpRtcpConfig(webrtc::RtcpMode::kCompound, true)); 661 aControl.mVideoCodecMode = webrtc::VideoCodecMode::kScreensharing; 662 }); 663 ASSERT_TRUE(Call()->mVideoSendEncoderConfig); 664 ASSERT_EQ(Call()->mVideoSendEncoderConfig->content_type, 665 VideoEncoderConfig::ContentType::kScreen); 666 } 667 668 TEST_F(VideoConduitTest, TestConfigureSendMediaCodecFEC) { 669 { 670 // H264 + FEC 671 mControl.Update([&](auto& aControl) { 672 aControl.mTransmitting = true; 673 VideoCodecConfig codecConfig(120, "H264", VideoEncodingConstraints()); 674 codecConfig.mEncodings.emplace_back(); 675 codecConfig.mFECFbSet = true; 676 codecConfig.mULPFECPayloadType = 1; 677 codecConfig.mREDPayloadType = 2; 678 codecConfig.mREDRTXPayloadType = 3; 679 aControl.mVideoSendCodec = Some(codecConfig); 680 aControl.mVideoSendRtpRtcpConfig = 681 Some(RtpRtcpConfig(webrtc::RtcpMode::kCompound, true)); 682 }); 683 ASSERT_TRUE(Call()->mVideoSendConfig); 684 ASSERT_EQ(Call()->mVideoSendConfig->rtp.ulpfec.ulpfec_payload_type, 1); 685 ASSERT_EQ(Call()->mVideoSendConfig->rtp.ulpfec.red_payload_type, 2); 686 ASSERT_EQ(Call()->mVideoSendConfig->rtp.ulpfec.red_rtx_payload_type, 3); 687 } 688 689 { 690 // H264 + FEC + Nack 691 mControl.Update([&](auto& aControl) { 692 VideoCodecConfig codecConfig(120, "H264", VideoEncodingConstraints()); 693 codecConfig.mEncodings.emplace_back(); 694 codecConfig.mFECFbSet = true; 695 codecConfig.mNackFbTypes.push_back(""); 696 codecConfig.mULPFECPayloadType = 1; 697 codecConfig.mREDPayloadType = 2; 698 codecConfig.mREDRTXPayloadType = 3; 699 aControl.mVideoSendCodec = Some(codecConfig); 700 }); 701 ASSERT_TRUE(Call()->mVideoSendConfig); 702 ASSERT_EQ(Call()->mVideoSendConfig->rtp.ulpfec.ulpfec_payload_type, -1); 703 ASSERT_EQ(Call()->mVideoSendConfig->rtp.ulpfec.red_payload_type, -1); 704 ASSERT_EQ(Call()->mVideoSendConfig->rtp.ulpfec.red_rtx_payload_type, -1); 705 } 706 707 { 708 // VP8 + FEC + Nack 709 mControl.Update([&](auto& aControl) { 710 VideoCodecConfig codecConfig(120, "VP8", VideoEncodingConstraints()); 711 codecConfig.mEncodings.emplace_back(); 712 codecConfig.mFECFbSet = true; 713 codecConfig.mNackFbTypes.push_back(""); 714 codecConfig.mULPFECPayloadType = 1; 715 codecConfig.mREDPayloadType = 2; 716 codecConfig.mREDRTXPayloadType = 3; 717 aControl.mVideoSendCodec = Some(codecConfig); 718 }); 719 ASSERT_TRUE(Call()->mVideoSendConfig); 720 ASSERT_EQ(Call()->mVideoSendConfig->rtp.ulpfec.ulpfec_payload_type, 1); 721 ASSERT_EQ(Call()->mVideoSendConfig->rtp.ulpfec.red_payload_type, 2); 722 ASSERT_EQ(Call()->mVideoSendConfig->rtp.ulpfec.red_rtx_payload_type, 3); 723 } 724 } 725 726 TEST_F(VideoConduitTest, TestConfigureSendMediaCodecNack) { 727 mControl.Update([&](auto& aControl) { 728 aControl.mTransmitting = true; 729 VideoCodecConfig codecConfig(120, "VP8", VideoEncodingConstraints()); 730 codecConfig.mEncodings.emplace_back(); 731 aControl.mVideoSendCodec = Some(codecConfig); 732 aControl.mVideoSendRtpRtcpConfig = 733 Some(RtpRtcpConfig(webrtc::RtcpMode::kCompound, true)); 734 }); 735 ASSERT_TRUE(Call()->mVideoSendConfig); 736 ASSERT_EQ(Call()->mVideoSendConfig->rtp.nack.rtp_history_ms, 0); 737 738 mControl.Update([&](auto& aControl) { 739 VideoCodecConfig codecConfig = *aControl.mVideoSendCodec.Ref(); 740 codecConfig.mNackFbTypes.push_back(""); 741 aControl.mVideoSendCodec = Some(codecConfig); 742 }); 743 ASSERT_TRUE(Call()->mVideoSendConfig); 744 ASSERT_EQ(Call()->mVideoSendConfig->rtp.nack.rtp_history_ms, 1000); 745 } 746 747 TEST_F(VideoConduitTest, TestConfigureSendMediaCodecRids) { 748 mControl.Update([&](auto& aControl) { 749 aControl.mTransmitting = true; 750 VideoCodecConfig codecConfig(120, "VP8", VideoEncodingConstraints()); 751 codecConfig.mEncodings.emplace_back(); 752 aControl.mVideoSendCodec = Some(codecConfig); 753 aControl.mVideoSendRtpRtcpConfig = 754 Some(RtpRtcpConfig(webrtc::RtcpMode::kCompound, true)); 755 }); 756 ASSERT_TRUE(Call()->mVideoSendConfig); 757 ASSERT_EQ(Call()->mVideoSendConfig->rtp.rids.size(), 0U); 758 759 mControl.Update([&](auto& aControl) { 760 VideoCodecConfig codecConfig(120, "VP8", VideoEncodingConstraints()); 761 { 762 auto& encoding = codecConfig.mEncodings.emplace_back(); 763 encoding.rid = "1"; 764 } 765 { 766 auto& encoding = codecConfig.mEncodings.emplace_back(); 767 encoding.rid = "2"; 768 } 769 aControl.mVideoSendCodec = Some(codecConfig); 770 aControl.mLocalSsrcs = {42, 1729}; 771 aControl.mLocalVideoRtxSsrcs = {43, 1730}; 772 }); 773 ASSERT_TRUE(Call()->mVideoSendConfig); 774 ASSERT_EQ(Call()->mVideoSendConfig->rtp.rids.size(), 2U); 775 ASSERT_EQ(Call()->mVideoSendConfig->rtp.rids[0], "1"); 776 ASSERT_EQ(Call()->mVideoSendConfig->rtp.rids[1], "2"); 777 } 778 779 TEST_F(VideoConduitTest, TestOnSinkWantsChanged) { 780 mControl.Update([&](auto& aControl) { 781 aControl.mTransmitting = true; 782 VideoCodecConfig codecConfig(120, "VP8", VideoEncodingConstraints()); 783 codecConfig.mEncodings.emplace_back(); 784 codecConfig.mEncodingConstraints.maxFs = 0; 785 aControl.mVideoSendCodec = Some(codecConfig); 786 aControl.mVideoSendRtpRtcpConfig = 787 Some(RtpRtcpConfig(webrtc::RtcpMode::kCompound, true)); 788 }); 789 ASSERT_TRUE(Call()->mVideoSendEncoderConfig); 790 webrtc::VideoSinkWants wants; 791 wants.max_pixel_count = 256000; 792 mVideoFrameConverter->AddOrUpdateSink(mVideoSink.get(), wants); 793 SendVideoFrame(1920, 1080, 1); 794 { 795 const std::vector<webrtc::VideoStream> videoStreams = 796 Call()->CreateEncoderStreams(mVideoSink->mVideoFrame.width(), 797 mVideoSink->mVideoFrame.height()); 798 EXPECT_LE(videoStreams[0].width * videoStreams[0].height, 256000U); 799 ASSERT_EQ(videoStreams.size(), 1U); 800 EXPECT_EQ(videoStreams[0].width, 640U); 801 EXPECT_EQ(videoStreams[0].height, 360U); 802 } 803 804 mControl.Update([&](auto& aControl) { 805 VideoCodecConfig codecConfig = *aControl.mVideoSendCodec.Ref(); 806 codecConfig.mEncodingConstraints.maxFs = 500; 807 aControl.mVideoSendCodec = Some(codecConfig); 808 }); 809 SendVideoFrame(1920, 1080, 2); 810 { 811 const std::vector<webrtc::VideoStream> videoStreams = 812 Call()->CreateEncoderStreams(mVideoSink->mVideoFrame.width(), 813 mVideoSink->mVideoFrame.height()); 814 EXPECT_LE(videoStreams[0].width * videoStreams[0].height, 500U * 16U * 16U); 815 ASSERT_EQ(videoStreams.size(), 1U); 816 EXPECT_EQ(videoStreams[0].width, 476U); 817 EXPECT_EQ(videoStreams[0].height, 268U); 818 } 819 820 mControl.Update([&](auto& aControl) { 821 VideoCodecConfig codecConfig = *aControl.mVideoSendCodec.Ref(); 822 codecConfig.mEncodingConstraints.maxFs = 1000; 823 aControl.mVideoSendCodec = Some(codecConfig); 824 }); 825 mVideoFrameConverter->AddOrUpdateSink(mVideoSink.get(), wants); 826 SendVideoFrame(1920, 1080, 3); 827 { 828 const std::vector<webrtc::VideoStream> videoStreams = 829 Call()->CreateEncoderStreams(mVideoSink->mVideoFrame.width(), 830 mVideoSink->mVideoFrame.height()); 831 EXPECT_LE(videoStreams[0].width * videoStreams[0].height, 832 1000U * 16U * 16U); 833 ASSERT_EQ(videoStreams.size(), 1U); 834 EXPECT_EQ(videoStreams[0].width, 640U); 835 EXPECT_EQ(videoStreams[0].height, 360U); 836 } 837 838 mControl.Update([&](auto& aControl) { 839 VideoCodecConfig codecConfig = *aControl.mVideoSendCodec.Ref(); 840 codecConfig.mEncodingConstraints.maxFs = 500; 841 aControl.mVideoSendCodec = Some(codecConfig); 842 }); 843 wants.max_pixel_count = 64000; 844 mVideoFrameConverter->AddOrUpdateSink(mVideoSink.get(), wants); 845 SendVideoFrame(1920, 1080, 4); 846 { 847 const std::vector<webrtc::VideoStream> videoStreams = 848 Call()->CreateEncoderStreams(mVideoSink->mVideoFrame.width(), 849 mVideoSink->mVideoFrame.height()); 850 ASSERT_EQ(videoStreams.size(), 1U); 851 EXPECT_EQ(videoStreams[0].width, 320U); 852 EXPECT_EQ(videoStreams[0].height, 180U); 853 EXPECT_LE(videoStreams[0].width * videoStreams[0].height, 64000U); 854 } 855 } 856 857 class VideoConduitTestScalingLocked : public VideoConduitTest { 858 public: 859 static VideoSessionConduit::Options CreateOptions() { 860 VideoSessionConduit::Options options; 861 options.mLockScaling = true; 862 return options; 863 } 864 VideoConduitTestScalingLocked() : VideoConduitTest(CreateOptions()) {} 865 }; 866 867 TEST_F(VideoConduitTestScalingLocked, TestOnSinkWantsChanged) { 868 mControl.Update([&](auto& aControl) { 869 aControl.mTransmitting = true; 870 VideoCodecConfig codecConfig(120, "VP8", VideoEncodingConstraints()); 871 codecConfig.mEncodingConstraints.maxFs = 0; 872 codecConfig.mEncodings.emplace_back(); 873 aControl.mVideoSendCodec = Some(codecConfig); 874 aControl.mVideoSendRtpRtcpConfig = 875 Some(RtpRtcpConfig(webrtc::RtcpMode::kCompound, true)); 876 }); 877 ASSERT_TRUE(Call()->mVideoSendEncoderConfig); 878 webrtc::VideoSinkWants wants; 879 wants.max_pixel_count = 256000; 880 mVideoFrameConverter->AddOrUpdateSink(mVideoSink.get(), wants); 881 SendVideoFrame(1920, 1080, 1); 882 EXPECT_EQ(mVideoSink->mVideoFrame.width(), 1920); 883 EXPECT_EQ(mVideoSink->mVideoFrame.height(), 1080); 884 { 885 const std::vector<webrtc::VideoStream> videoStreams = 886 Call()->CreateEncoderStreams(mVideoSink->mVideoFrame.width(), 887 mVideoSink->mVideoFrame.height()); 888 ASSERT_EQ(videoStreams.size(), 1U); 889 EXPECT_EQ(videoStreams[0].width, 1920U); 890 EXPECT_EQ(videoStreams[0].height, 1080U); 891 } 892 893 mControl.Update([&](auto& aControl) { 894 VideoCodecConfig codecConfig = *aControl.mVideoSendCodec.Ref(); 895 codecConfig.mEncodingConstraints.maxFs = 500; 896 aControl.mVideoSendCodec = Some(codecConfig); 897 }); 898 ASSERT_TRUE(Call()->mVideoSendEncoderConfig); 899 SendVideoFrame(1920, 1080, 2); 900 { 901 const std::vector<webrtc::VideoStream> videoStreams = 902 Call()->CreateEncoderStreams(mVideoSink->mVideoFrame.width(), 903 mVideoSink->mVideoFrame.height()); 904 EXPECT_LE(videoStreams[0].width * videoStreams[0].height, 500U * 16U * 16U); 905 ASSERT_EQ(videoStreams.size(), 1U); 906 EXPECT_EQ(videoStreams[0].width, 476U); 907 EXPECT_EQ(videoStreams[0].height, 268U); 908 } 909 } 910 911 TEST_P(VideoConduitCodecModeTest, 912 TestConfigureSendMediaCodecSimulcastOddResolution) { 913 mControl.Update([&](auto& aControl) { 914 aControl.mTransmitting = true; 915 { 916 VideoCodecConfig codecConfig(120, "VP8", VideoEncodingConstraints()); 917 codecConfig.mEncodings.emplace_back(); 918 { 919 auto& encoding = codecConfig.mEncodings.emplace_back(); 920 encoding.constraints.scaleDownBy = 2; 921 } 922 { 923 auto& encoding = codecConfig.mEncodings.emplace_back(); 924 encoding.constraints.scaleDownBy = 4; 925 } 926 aControl.mVideoSendCodec = Some(codecConfig); 927 } 928 aControl.mVideoSendRtpRtcpConfig = 929 Some(RtpRtcpConfig(webrtc::RtcpMode::kCompound, true)); 930 aControl.mVideoCodecMode = GetParam(); 931 aControl.mLocalSsrcs = {42, 43, 44}; 932 aControl.mLocalVideoRtxSsrcs = {45, 46, 47}; 933 }); 934 ASSERT_TRUE(Call()->mVideoSendEncoderConfig); 935 936 SendVideoFrame(27, 25, 1); 937 { 938 const std::vector<webrtc::VideoStream> videoStreams = 939 Call()->CreateEncoderStreams(mVideoSink->mVideoFrame.width(), 940 mVideoSink->mVideoFrame.height()); 941 ASSERT_EQ(videoStreams.size(), 3U); 942 EXPECT_EQ(videoStreams[0].width, 27U); 943 EXPECT_EQ(videoStreams[0].height, 25U); 944 EXPECT_EQ(videoStreams[1].width, 13U); 945 EXPECT_EQ(videoStreams[1].height, 12U); 946 EXPECT_EQ(videoStreams[2].width, 6U); 947 EXPECT_EQ(videoStreams[2].height, 6U); 948 } 949 950 mControl.Update([&](auto& aControl) { 951 VideoCodecConfig codecConfig = *aControl.mVideoSendCodec.Ref(); 952 codecConfig.mEncodings.clear(); 953 codecConfig.mEncodings.emplace_back(); 954 aControl.mVideoSendCodec = Some(codecConfig); 955 aControl.mLocalSsrcs = {42}; 956 aControl.mLocalVideoRtxSsrcs = {43}; 957 }); 958 ASSERT_TRUE(Call()->mVideoSendEncoderConfig); 959 SendVideoFrame(27, 25, 2); 960 { 961 const std::vector<webrtc::VideoStream> videoStreams = 962 Call()->CreateEncoderStreams(mVideoSink->mVideoFrame.width(), 963 mVideoSink->mVideoFrame.height()); 964 ASSERT_EQ(videoStreams.size(), 1U); 965 EXPECT_EQ(videoStreams[0].width, 27U); 966 EXPECT_EQ(videoStreams[0].height, 25U); 967 } 968 } 969 970 TEST_P(VideoConduitCodecModeTest, 971 TestConfigureSendMediaCodecSimulcastAllScaling) { 972 mControl.Update([&](auto& aControl) { 973 aControl.mTransmitting = true; 974 VideoCodecConfig codecConfig(120, "VP8", VideoEncodingConstraints()); 975 { 976 auto& encoding = codecConfig.mEncodings.emplace_back(); 977 encoding.constraints.scaleDownBy = 2; 978 } 979 { 980 auto& encoding = codecConfig.mEncodings.emplace_back(); 981 encoding.constraints.scaleDownBy = 4; 982 } 983 { 984 auto& encoding = codecConfig.mEncodings.emplace_back(); 985 encoding.constraints.scaleDownBy = 6; 986 } 987 aControl.mVideoSendCodec = Some(codecConfig); 988 aControl.mVideoSendRtpRtcpConfig = 989 Some(RtpRtcpConfig(webrtc::RtcpMode::kCompound, true)); 990 aControl.mVideoCodecMode = GetParam(); 991 aControl.mLocalSsrcs = {42, 43, 44}; 992 aControl.mLocalVideoRtxSsrcs = {45, 46, 47}; 993 }); 994 ASSERT_TRUE(Call()->mVideoSendEncoderConfig); 995 996 SendVideoFrame(1281, 721, 1); 997 { 998 const std::vector<webrtc::VideoStream> videoStreams = 999 Call()->CreateEncoderStreams(mVideoSink->mVideoFrame.width(), 1000 mVideoSink->mVideoFrame.height()); 1001 ASSERT_EQ(videoStreams.size(), 3U); 1002 EXPECT_EQ(videoStreams[0].width, 640U); 1003 EXPECT_EQ(videoStreams[0].height, 360U); 1004 EXPECT_EQ(videoStreams[1].width, 320U); 1005 EXPECT_EQ(videoStreams[1].height, 180U); 1006 EXPECT_EQ(videoStreams[2].width, 213U); 1007 EXPECT_EQ(videoStreams[2].height, 120U); 1008 } 1009 1010 SendVideoFrame(1281, 721, 2); 1011 { 1012 const std::vector<webrtc::VideoStream> videoStreams = 1013 Call()->CreateEncoderStreams(mVideoSink->mVideoFrame.width(), 1014 mVideoSink->mVideoFrame.height()); 1015 ASSERT_EQ(videoStreams.size(), 3U); 1016 EXPECT_EQ(videoStreams[0].width, 640U); 1017 EXPECT_EQ(videoStreams[0].height, 360U); 1018 EXPECT_EQ(videoStreams[1].width, 320U); 1019 EXPECT_EQ(videoStreams[1].height, 180U); 1020 EXPECT_EQ(videoStreams[2].width, 213U); 1021 EXPECT_EQ(videoStreams[2].height, 120U); 1022 } 1023 1024 SendVideoFrame(1280, 720, 3); 1025 { 1026 const std::vector<webrtc::VideoStream> videoStreams = 1027 Call()->CreateEncoderStreams(mVideoSink->mVideoFrame.width(), 1028 mVideoSink->mVideoFrame.height()); 1029 ASSERT_EQ(videoStreams.size(), 3U); 1030 EXPECT_EQ(videoStreams[0].width, 640U); 1031 EXPECT_EQ(videoStreams[0].height, 360U); 1032 EXPECT_EQ(videoStreams[1].width, 320U); 1033 EXPECT_EQ(videoStreams[1].height, 180U); 1034 EXPECT_EQ(videoStreams[2].width, 213U); 1035 EXPECT_EQ(videoStreams[2].height, 120U); 1036 } 1037 1038 mControl.Update([&](auto& aControl) { 1039 VideoCodecConfig codecConfig = *aControl.mVideoSendCodec.Ref(); 1040 codecConfig.mEncodings[0].constraints.scaleDownBy = 1; 1041 codecConfig.mEncodings[1].constraints.scaleDownBy = 2; 1042 codecConfig.mEncodings[2].constraints.scaleDownBy = 4; 1043 aControl.mVideoSendCodec = Some(codecConfig); 1044 }); 1045 ASSERT_TRUE(Call()->mVideoSendEncoderConfig); 1046 SendVideoFrame(1280, 720, 4); 1047 { 1048 const std::vector<webrtc::VideoStream> videoStreams = 1049 Call()->CreateEncoderStreams(mVideoSink->mVideoFrame.width(), 1050 mVideoSink->mVideoFrame.height()); 1051 ASSERT_EQ(videoStreams.size(), 3U); 1052 EXPECT_EQ(videoStreams[0].width, 1280U); 1053 EXPECT_EQ(videoStreams[0].height, 720U); 1054 EXPECT_EQ(videoStreams[1].width, 640U); 1055 EXPECT_EQ(videoStreams[1].height, 360U); 1056 EXPECT_EQ(videoStreams[2].width, 320U); 1057 EXPECT_EQ(videoStreams[2].height, 180U); 1058 } 1059 } 1060 1061 TEST_F(VideoConduitTest, TestReconfigureReceiveMediaCodecs) { 1062 // Defaults 1063 mControl.Update([&](auto& aControl) { 1064 aControl.mReceiving = true; 1065 aControl.mVideoRecvCodecs = { 1066 VideoCodecConfig(120, "VP8", VideoEncodingConstraints())}; 1067 aControl.mVideoRecvRtpRtcpConfig = 1068 Some(RtpRtcpConfig(webrtc::RtcpMode::kCompound, true)); 1069 }); 1070 ASSERT_TRUE(Call()->mVideoReceiveConfig); 1071 ASSERT_EQ(Call()->mVideoReceiveConfig->decoders.size(), 1U); 1072 ASSERT_EQ(Call()->mVideoReceiveConfig->decoders[0].payload_type, 120); 1073 ASSERT_EQ(Call()->mVideoReceiveConfig->decoders[0].video_format.name, "VP8"); 1074 ASSERT_NE(Call()->mVideoReceiveConfig->rtp.local_ssrc, 0U); 1075 ASSERT_NE(Call()->mVideoReceiveConfig->rtp.remote_ssrc, 0U); 1076 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.rtcp_mode, 1077 webrtc::RtcpMode::kCompound); 1078 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.nack.rtp_history_ms, 0); 1079 ASSERT_FALSE(Call()->mVideoReceiveConfig->rtp.remb); 1080 ASSERT_FALSE(Call()->mVideoReceiveConfig->rtp.tmmbr); 1081 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.keyframe_method, 1082 webrtc::KeyFrameReqMethod::kNone); 1083 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.ulpfec_payload_type, -1); 1084 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.red_payload_type, -1); 1085 ASSERT_EQ( 1086 Call()->mVideoReceiveConfig->rtp.rtx_associated_payload_types.size(), 0U); 1087 1088 // FEC 1089 mControl.Update([&](auto& aControl) { 1090 VideoCodecConfig codecConfigFecFb(120, "VP8", VideoEncodingConstraints()); 1091 codecConfigFecFb.mFECFbSet = true; 1092 VideoCodecConfig codecConfigFEC(1, "ulpfec", VideoEncodingConstraints()); 1093 VideoCodecConfig codecConfigRED(2, "red", VideoEncodingConstraints()); 1094 aControl.mVideoRecvCodecs = {codecConfigFecFb, codecConfigFEC, 1095 codecConfigRED}; 1096 }); 1097 ASSERT_TRUE(Call()->mVideoReceiveConfig); 1098 ASSERT_EQ(Call()->mVideoReceiveConfig->decoders.size(), 1U); 1099 ASSERT_EQ(Call()->mVideoReceiveConfig->decoders[0].payload_type, 120); 1100 ASSERT_EQ(Call()->mVideoReceiveConfig->decoders[0].video_format.name, "VP8"); 1101 ASSERT_NE(Call()->mVideoReceiveConfig->rtp.local_ssrc, 0U); 1102 ASSERT_NE(Call()->mVideoReceiveConfig->rtp.remote_ssrc, 0U); 1103 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.rtcp_mode, 1104 webrtc::RtcpMode::kCompound); 1105 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.nack.rtp_history_ms, 0); 1106 ASSERT_FALSE(Call()->mVideoReceiveConfig->rtp.remb); 1107 ASSERT_FALSE(Call()->mVideoReceiveConfig->rtp.tmmbr); 1108 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.keyframe_method, 1109 webrtc::KeyFrameReqMethod::kNone); 1110 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.ulpfec_payload_type, 1); 1111 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.red_payload_type, 2); 1112 ASSERT_EQ( 1113 Call()->mVideoReceiveConfig->rtp.rtx_associated_payload_types.size(), 0U); 1114 1115 // H264 1116 mControl.Update([&](auto& aControl) { 1117 aControl.mVideoRecvCodecs = { 1118 VideoCodecConfig(120, "H264", VideoEncodingConstraints())}; 1119 }); 1120 ASSERT_TRUE(Call()->mVideoReceiveConfig); 1121 ASSERT_EQ(Call()->mVideoReceiveConfig->decoders.size(), 1U); 1122 ASSERT_EQ(Call()->mVideoReceiveConfig->decoders[0].payload_type, 120); 1123 ASSERT_EQ(Call()->mVideoReceiveConfig->decoders[0].video_format.name, "H264"); 1124 ASSERT_NE(Call()->mVideoReceiveConfig->rtp.local_ssrc, 0U); 1125 ASSERT_NE(Call()->mVideoReceiveConfig->rtp.remote_ssrc, 0U); 1126 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.rtcp_mode, 1127 webrtc::RtcpMode::kCompound); 1128 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.nack.rtp_history_ms, 0); 1129 ASSERT_FALSE(Call()->mVideoReceiveConfig->rtp.remb); 1130 ASSERT_FALSE(Call()->mVideoReceiveConfig->rtp.tmmbr); 1131 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.keyframe_method, 1132 webrtc::KeyFrameReqMethod::kNone); 1133 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.ulpfec_payload_type, -1); 1134 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.red_payload_type, -1); 1135 ASSERT_EQ( 1136 Call()->mVideoReceiveConfig->rtp.rtx_associated_payload_types.size(), 0U); 1137 1138 // Nack 1139 mControl.Update([&](auto& aControl) { 1140 VideoCodecConfig codecConfigNack(120, "VP8", VideoEncodingConstraints()); 1141 codecConfigNack.mNackFbTypes.push_back(""); 1142 aControl.mVideoRecvCodecs = {codecConfigNack}; 1143 }); 1144 ASSERT_TRUE(Call()->mVideoReceiveConfig); 1145 ASSERT_EQ(Call()->mVideoReceiveConfig->decoders.size(), 1U); 1146 ASSERT_EQ(Call()->mVideoReceiveConfig->decoders[0].payload_type, 120); 1147 ASSERT_EQ(Call()->mVideoReceiveConfig->decoders[0].video_format.name, "VP8"); 1148 ASSERT_NE(Call()->mVideoReceiveConfig->rtp.local_ssrc, 0U); 1149 ASSERT_NE(Call()->mVideoReceiveConfig->rtp.remote_ssrc, 0U); 1150 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.rtcp_mode, 1151 webrtc::RtcpMode::kCompound); 1152 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.nack.rtp_history_ms, 1000); 1153 ASSERT_FALSE(Call()->mVideoReceiveConfig->rtp.remb); 1154 ASSERT_FALSE(Call()->mVideoReceiveConfig->rtp.tmmbr); 1155 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.keyframe_method, 1156 webrtc::KeyFrameReqMethod::kNone); 1157 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.ulpfec_payload_type, -1); 1158 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.red_payload_type, -1); 1159 ASSERT_EQ( 1160 Call()->mVideoReceiveConfig->rtp.rtx_associated_payload_types.size(), 0U); 1161 1162 // Remb 1163 mControl.Update([&](auto& aControl) { 1164 VideoCodecConfig codecConfigRemb(120, "VP8", VideoEncodingConstraints()); 1165 codecConfigRemb.mRembFbSet = true; 1166 aControl.mVideoRecvCodecs = {codecConfigRemb}; 1167 }); 1168 ASSERT_TRUE(Call()->mVideoReceiveConfig); 1169 ASSERT_EQ(Call()->mVideoReceiveConfig->decoders.size(), 1U); 1170 ASSERT_EQ(Call()->mVideoReceiveConfig->decoders[0].payload_type, 120); 1171 ASSERT_EQ(Call()->mVideoReceiveConfig->decoders[0].video_format.name, "VP8"); 1172 ASSERT_NE(Call()->mVideoReceiveConfig->rtp.local_ssrc, 0U); 1173 ASSERT_NE(Call()->mVideoReceiveConfig->rtp.remote_ssrc, 0U); 1174 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.rtcp_mode, 1175 webrtc::RtcpMode::kCompound); 1176 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.nack.rtp_history_ms, 0); 1177 ASSERT_TRUE(Call()->mVideoReceiveConfig->rtp.remb); 1178 ASSERT_FALSE(Call()->mVideoReceiveConfig->rtp.tmmbr); 1179 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.keyframe_method, 1180 webrtc::KeyFrameReqMethod::kNone); 1181 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.ulpfec_payload_type, -1); 1182 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.red_payload_type, -1); 1183 ASSERT_EQ( 1184 Call()->mVideoReceiveConfig->rtp.rtx_associated_payload_types.size(), 0U); 1185 1186 // Tmmbr 1187 mControl.Update([&](auto& aControl) { 1188 VideoCodecConfig codecConfigTmmbr(120, "VP8", VideoEncodingConstraints()); 1189 codecConfigTmmbr.mCcmFbTypes.push_back("tmmbr"); 1190 aControl.mVideoRecvCodecs = {codecConfigTmmbr}; 1191 }); 1192 ASSERT_TRUE(Call()->mVideoReceiveConfig); 1193 ASSERT_EQ(Call()->mVideoReceiveConfig->decoders.size(), 1U); 1194 ASSERT_EQ(Call()->mVideoReceiveConfig->decoders[0].payload_type, 120); 1195 ASSERT_EQ(Call()->mVideoReceiveConfig->decoders[0].video_format.name, "VP8"); 1196 ASSERT_NE(Call()->mVideoReceiveConfig->rtp.local_ssrc, 0U); 1197 ASSERT_NE(Call()->mVideoReceiveConfig->rtp.remote_ssrc, 0U); 1198 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.rtcp_mode, 1199 webrtc::RtcpMode::kCompound); 1200 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.nack.rtp_history_ms, 0); 1201 ASSERT_FALSE(Call()->mVideoReceiveConfig->rtp.remb); 1202 ASSERT_TRUE(Call()->mVideoReceiveConfig->rtp.tmmbr); 1203 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.keyframe_method, 1204 webrtc::KeyFrameReqMethod::kNone); 1205 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.ulpfec_payload_type, -1); 1206 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.red_payload_type, -1); 1207 ASSERT_EQ( 1208 Call()->mVideoReceiveConfig->rtp.rtx_associated_payload_types.size(), 0U); 1209 } 1210 1211 TEST_P(VideoConduitCodecModeTest, TestReconfigureSendMediaCodec) { 1212 mControl.Update([&](auto& aControl) { 1213 VideoCodecConfig codecConfig(120, "VP8", VideoEncodingConstraints()); 1214 codecConfig.mEncodings.emplace_back(); 1215 aControl.mVideoSendCodec = Some(codecConfig); 1216 aControl.mVideoSendRtpRtcpConfig = 1217 Some(RtpRtcpConfig(webrtc::RtcpMode::kCompound, true)); 1218 aControl.mVideoCodecMode = GetParam(); 1219 }); 1220 ASSERT_FALSE(Call()->mVideoSendConfig); 1221 1222 // Defaults 1223 mControl.Update([&](auto& aControl) { aControl.mTransmitting = true; }); 1224 ASSERT_TRUE(Call()->mVideoSendConfig); 1225 EXPECT_EQ(Call()->mVideoSendConfig->rtp.payload_name, "VP8"); 1226 EXPECT_EQ(Call()->mVideoSendConfig->rtp.payload_type, 120); 1227 EXPECT_EQ(Call()->mVideoSendConfig->rtp.rtcp_mode, 1228 webrtc::RtcpMode::kCompound); 1229 EXPECT_EQ(Call()->mVideoSendConfig->rtp.max_packet_size, mozilla::kVideoMtu); 1230 EXPECT_EQ(Call()->mVideoSendEncoderConfig->content_type, 1231 GetParam() == webrtc::VideoCodecMode::kRealtimeVideo 1232 ? VideoEncoderConfig::ContentType::kRealtimeVideo 1233 : VideoEncoderConfig::ContentType::kScreen); 1234 EXPECT_EQ(Call()->mVideoSendEncoderConfig->min_transmit_bitrate_bps, 0); 1235 EXPECT_EQ(Call()->mVideoSendEncoderConfig->max_bitrate_bps, KBPS(10000)); 1236 EXPECT_EQ(Call()->mVideoSendEncoderConfig->number_of_streams, 1U); 1237 mControl.Update([&](auto& aControl) { aControl.mTransmitting = false; }); 1238 1239 // FEC 1240 mControl.Update([&](auto& aControl) { 1241 aControl.mTransmitting = true; 1242 VideoCodecConfig codecConfigFEC(120, "VP8", VideoEncodingConstraints()); 1243 codecConfigFEC.mEncodings.emplace_back(); 1244 codecConfigFEC.mFECFbSet = true; 1245 codecConfigFEC.mNackFbTypes.push_back(""); 1246 codecConfigFEC.mULPFECPayloadType = 1; 1247 codecConfigFEC.mREDPayloadType = 2; 1248 codecConfigFEC.mREDRTXPayloadType = 3; 1249 aControl.mVideoSendCodec = Some(codecConfigFEC); 1250 }); 1251 ASSERT_TRUE(Call()->mVideoSendConfig); 1252 EXPECT_EQ(Call()->mVideoSendConfig->rtp.ulpfec.ulpfec_payload_type, 1); 1253 EXPECT_EQ(Call()->mVideoSendConfig->rtp.ulpfec.red_payload_type, 2); 1254 EXPECT_EQ(Call()->mVideoSendConfig->rtp.ulpfec.red_rtx_payload_type, 3); 1255 mControl.Update([&](auto& aControl) { aControl.mTransmitting = false; }); 1256 1257 // H264 1258 mControl.Update([&](auto& aControl) { 1259 aControl.mTransmitting = true; 1260 VideoCodecConfig codecConfigH264(120, "H264", VideoEncodingConstraints()); 1261 codecConfigH264.mEncodings.emplace_back(); 1262 aControl.mVideoSendCodec = Some(codecConfigH264); 1263 }); 1264 ASSERT_TRUE(Call()->mVideoSendConfig); 1265 EXPECT_EQ(Call()->mVideoSendConfig->rtp.payload_name, "H264"); 1266 EXPECT_EQ(Call()->mVideoSendConfig->rtp.payload_type, 120); 1267 mControl.Update([&](auto& aControl) { aControl.mTransmitting = false; }); 1268 1269 // TIAS 1270 mControl.Update([&](auto& aControl) { 1271 aControl.mTransmitting = true; 1272 VideoCodecConfig codecConfigTias(120, "VP8", VideoEncodingConstraints()); 1273 codecConfigTias.mEncodings.emplace_back(); 1274 codecConfigTias.mTias = 2000000; 1275 aControl.mVideoSendCodec = Some(codecConfigTias); 1276 }); 1277 ASSERT_TRUE(Call()->mVideoSendEncoderConfig); 1278 EXPECT_EQ(Call()->mVideoSendEncoderConfig->max_bitrate_bps, 2000000); 1279 ASSERT_EQ(Call()->mVideoSendEncoderConfig->number_of_streams, 1U); 1280 EXPECT_EQ( 1281 Call()->mVideoSendEncoderConfig->simulcast_layers[0].max_bitrate_bps, 1282 2000000); 1283 SendVideoFrame(1280, 720, 1); 1284 1285 { 1286 const std::vector<webrtc::VideoStream> videoStreams = 1287 Call()->CreateEncoderStreams(1280, 720); 1288 ASSERT_EQ(videoStreams.size(), 1U); 1289 EXPECT_EQ(videoStreams[0].min_bitrate_bps, 1200000); 1290 EXPECT_EQ(videoStreams[0].target_bitrate_bps, 1500000); 1291 EXPECT_EQ(videoStreams[0].max_bitrate_bps, 2000000); 1292 } 1293 mControl.Update([&](auto& aControl) { aControl.mTransmitting = false; }); 1294 1295 // MaxBr 1296 mControl.Update([&](auto& aControl) { 1297 aControl.mTransmitting = true; 1298 VideoCodecConfig codecConfig(120, "VP8", VideoEncodingConstraints()); 1299 VideoCodecConfig::Encoding encoding; 1300 { 1301 auto& encoding = codecConfig.mEncodings.emplace_back(); 1302 encoding.constraints.maxBr = 50000; 1303 } 1304 aControl.mVideoSendCodec = Some(codecConfig); 1305 }); 1306 ASSERT_TRUE(Call()->mVideoSendEncoderConfig); 1307 EXPECT_EQ(Call()->mVideoSendEncoderConfig->max_bitrate_bps, 50000); 1308 ASSERT_EQ(Call()->mVideoSendEncoderConfig->number_of_streams, 1U); 1309 EXPECT_EQ( 1310 Call()->mVideoSendEncoderConfig->simulcast_layers[0].max_bitrate_bps, 1311 50000); 1312 SendVideoFrame(1280, 720, 2); 1313 { 1314 const std::vector<webrtc::VideoStream> videoStreams = 1315 Call()->CreateEncoderStreams(1280, 720); 1316 ASSERT_EQ(videoStreams.size(), 1U); 1317 EXPECT_LE(videoStreams[0].min_bitrate_bps, 50000); 1318 EXPECT_LE(videoStreams[0].target_bitrate_bps, 50000); 1319 EXPECT_EQ(videoStreams[0].max_bitrate_bps, 50000); 1320 } 1321 mControl.Update([&](auto& aControl) { aControl.mTransmitting = false; }); 1322 1323 // MaxFs 1324 mControl.Update([&](auto& aControl) { 1325 aControl.mTransmitting = true; 1326 VideoCodecConfig codecConfigMaxFs(120, "VP8", VideoEncodingConstraints()); 1327 codecConfigMaxFs.mEncodingConstraints.maxFs = 3600; 1328 VideoCodecConfig::Encoding encoding; 1329 encoding.constraints.maxBr = 0; 1330 codecConfigMaxFs.mEncodings.push_back(encoding); 1331 aControl.mVideoSendCodec = Some(codecConfigMaxFs); 1332 }); 1333 ASSERT_TRUE(Call()->mVideoSendEncoderConfig); 1334 1335 { 1336 SendVideoFrame(1280, 720, 3); 1337 const std::vector<webrtc::VideoStream> videoStreams = 1338 Call()->CreateEncoderStreams(mVideoSink->mVideoFrame.width(), 1339 mVideoSink->mVideoFrame.height()); 1340 EXPECT_EQ(videoStreams[0].width, 1280U); 1341 EXPECT_EQ(videoStreams[0].height, 720U); 1342 EXPECT_EQ(mVideoSink->mVideoFrame.timestamp_us(), 3000U); 1343 EXPECT_EQ(mVideoSink->mOnFrameCount, 3U); 1344 } 1345 1346 { 1347 SendVideoFrame(640, 360, 4); 1348 const std::vector<webrtc::VideoStream> videoStreams = 1349 Call()->CreateEncoderStreams(mVideoSink->mVideoFrame.width(), 1350 mVideoSink->mVideoFrame.height()); 1351 EXPECT_EQ(videoStreams[0].width, 640U); 1352 EXPECT_EQ(videoStreams[0].height, 360U); 1353 EXPECT_EQ(mVideoSink->mVideoFrame.timestamp_us(), 4000U); 1354 EXPECT_EQ(mVideoSink->mOnFrameCount, 4U); 1355 } 1356 1357 { 1358 SendVideoFrame(1920, 1280, 5); 1359 const std::vector<webrtc::VideoStream> videoStreams = 1360 Call()->CreateEncoderStreams(mVideoSink->mVideoFrame.width(), 1361 mVideoSink->mVideoFrame.height()); 1362 EXPECT_EQ(videoStreams[0].width, 1174U); 1363 EXPECT_EQ(videoStreams[0].height, 783U); 1364 EXPECT_EQ(mVideoSink->mVideoFrame.timestamp_us(), 5000U); 1365 EXPECT_EQ(mVideoSink->mOnFrameCount, 5U); 1366 } 1367 } 1368 1369 TEST_P(VideoConduitCodecModeTest, 1370 TestReconfigureSendMediaCodecWhileTransmitting) { 1371 mControl.Update([&](auto& aControl) { 1372 VideoCodecConfig codecConfig(120, "VP8", VideoEncodingConstraints()); 1373 codecConfig.mEncodings.emplace_back(); 1374 aControl.mVideoSendCodec = Some(codecConfig); 1375 aControl.mVideoSendRtpRtcpConfig = 1376 Some(RtpRtcpConfig(webrtc::RtcpMode::kCompound, true)); 1377 aControl.mVideoCodecMode = GetParam(); 1378 }); 1379 ASSERT_FALSE(Call()->mVideoSendConfig); 1380 1381 // Defaults 1382 mControl.Update([&](auto& aControl) { aControl.mTransmitting = true; }); 1383 ASSERT_TRUE(Call()->mVideoSendConfig); 1384 EXPECT_EQ(Call()->mVideoSendConfig->rtp.payload_name, "VP8"); 1385 EXPECT_EQ(Call()->mVideoSendConfig->rtp.payload_type, 120); 1386 EXPECT_EQ(Call()->mVideoSendConfig->rtp.rtcp_mode, 1387 webrtc::RtcpMode::kCompound); 1388 EXPECT_EQ(Call()->mVideoSendConfig->rtp.max_packet_size, mozilla::kVideoMtu); 1389 EXPECT_EQ(Call()->mVideoSendEncoderConfig->content_type, 1390 GetParam() == webrtc::VideoCodecMode::kRealtimeVideo 1391 ? VideoEncoderConfig::ContentType::kRealtimeVideo 1392 : VideoEncoderConfig::ContentType::kScreen); 1393 EXPECT_EQ(Call()->mVideoSendEncoderConfig->min_transmit_bitrate_bps, 0); 1394 EXPECT_EQ(Call()->mVideoSendEncoderConfig->max_bitrate_bps, KBPS(10000)); 1395 EXPECT_EQ(Call()->mVideoSendEncoderConfig->number_of_streams, 1U); 1396 1397 // Changing these parameters should not require flipping mTransmitting for the 1398 // changes to take effect. 1399 1400 // TIAS 1401 mControl.Update([&](auto& aControl) { 1402 VideoCodecConfig codecConfigTias(120, "VP8", VideoEncodingConstraints()); 1403 codecConfigTias.mEncodings.emplace_back(); 1404 codecConfigTias.mTias = 2000000; 1405 aControl.mVideoSendCodec = Some(codecConfigTias); 1406 }); 1407 ASSERT_TRUE(Call()->mVideoSendEncoderConfig); 1408 ASSERT_EQ(Call()->mVideoSendEncoderConfig->max_bitrate_bps, 2000000); 1409 ASSERT_EQ(Call()->mVideoSendEncoderConfig->number_of_streams, 1U); 1410 EXPECT_EQ( 1411 Call()->mVideoSendEncoderConfig->simulcast_layers[0].max_bitrate_bps, 1412 2000000); 1413 SendVideoFrame(1280, 720, 1); 1414 1415 { 1416 const std::vector<webrtc::VideoStream> videoStreams = 1417 Call()->CreateEncoderStreams(1280, 720); 1418 ASSERT_EQ(videoStreams.size(), 1U); 1419 EXPECT_EQ(videoStreams[0].min_bitrate_bps, 1200000); 1420 EXPECT_EQ(videoStreams[0].target_bitrate_bps, 1500000); 1421 EXPECT_EQ(videoStreams[0].max_bitrate_bps, 2000000); 1422 } 1423 1424 // MaxBr 1425 mControl.Update([&](auto& aControl) { 1426 VideoCodecConfig codecConfig(120, "VP8", VideoEncodingConstraints()); 1427 { 1428 auto& encoding = codecConfig.mEncodings.emplace_back(); 1429 encoding.constraints.maxBr = 50000; 1430 } 1431 aControl.mVideoSendCodec = Some(codecConfig); 1432 }); 1433 ASSERT_TRUE(Call()->mVideoSendEncoderConfig); 1434 ASSERT_EQ(Call()->mVideoSendEncoderConfig->number_of_streams, 1U); 1435 EXPECT_EQ( 1436 Call()->mVideoSendEncoderConfig->simulcast_layers[0].max_bitrate_bps, 1437 50000); 1438 SendVideoFrame(1280, 720, 2); 1439 { 1440 const std::vector<webrtc::VideoStream> videoStreams = 1441 Call()->CreateEncoderStreams(1280, 720); 1442 ASSERT_EQ(videoStreams.size(), 1U); 1443 EXPECT_LE(videoStreams[0].min_bitrate_bps, 50000); 1444 EXPECT_LE(videoStreams[0].target_bitrate_bps, 50000); 1445 EXPECT_EQ(videoStreams[0].max_bitrate_bps, 50000); 1446 } 1447 1448 // MaxFs 1449 mControl.Update([&](auto& aControl) { 1450 VideoCodecConfig codecConfig(120, "VP8", VideoEncodingConstraints()); 1451 codecConfig.mEncodingConstraints.maxFs = 3600; 1452 { 1453 auto& encoding = codecConfig.mEncodings.emplace_back(); 1454 encoding.constraints.maxBr = 0; 1455 } 1456 aControl.mVideoSendCodec = Some(codecConfig); 1457 }); 1458 ASSERT_TRUE(Call()->mVideoSendEncoderConfig); 1459 1460 { 1461 SendVideoFrame(1280, 720, 3); 1462 const std::vector<webrtc::VideoStream> videoStreams = 1463 Call()->CreateEncoderStreams(mVideoSink->mVideoFrame.width(), 1464 mVideoSink->mVideoFrame.height()); 1465 EXPECT_EQ(videoStreams[0].width, 1280U); 1466 EXPECT_EQ(videoStreams[0].height, 720U); 1467 EXPECT_EQ(mVideoSink->mVideoFrame.timestamp_us(), 3000U); 1468 EXPECT_EQ(mVideoSink->mOnFrameCount, 3U); 1469 } 1470 1471 { 1472 SendVideoFrame(641, 360, 4); 1473 const std::vector<webrtc::VideoStream> videoStreams = 1474 Call()->CreateEncoderStreams(mVideoSink->mVideoFrame.width(), 1475 mVideoSink->mVideoFrame.height()); 1476 EXPECT_EQ(videoStreams[0].width, 641U); 1477 EXPECT_EQ(videoStreams[0].height, 360U); 1478 EXPECT_EQ(mVideoSink->mVideoFrame.timestamp_us(), 4000U); 1479 EXPECT_EQ(mVideoSink->mOnFrameCount, 4U); 1480 } 1481 1482 { 1483 SendVideoFrame(1920, 1280, 5); 1484 const std::vector<webrtc::VideoStream> videoStreams = 1485 Call()->CreateEncoderStreams(mVideoSink->mVideoFrame.width(), 1486 mVideoSink->mVideoFrame.height()); 1487 EXPECT_EQ(videoStreams[0].width, 1174U); 1488 EXPECT_EQ(videoStreams[0].height, 783U); 1489 EXPECT_EQ(mVideoSink->mVideoFrame.timestamp_us(), 5000U); 1490 EXPECT_EQ(mVideoSink->mOnFrameCount, 5U); 1491 } 1492 1493 // ScaleResolutionDownBy 1494 mControl.Update([&](auto& aControl) { 1495 VideoCodecConfig codecConfig(120, "VP8", VideoEncodingConstraints()); 1496 { 1497 auto& encoding = codecConfig.mEncodings.emplace_back(); 1498 encoding.constraints.maxFs = 0; 1499 encoding.constraints.scaleDownBy = 3.7; 1500 } 1501 aControl.mVideoSendCodec = Some(codecConfig); 1502 }); 1503 ASSERT_TRUE(Call()->mVideoSendEncoderConfig); 1504 1505 { 1506 SendVideoFrame(1280, 720, 6); 1507 const std::vector<webrtc::VideoStream> videoStreams = 1508 Call()->CreateEncoderStreams(mVideoSink->mVideoFrame.width(), 1509 mVideoSink->mVideoFrame.height()); 1510 EXPECT_EQ(videoStreams[0].width, 345U); 1511 EXPECT_EQ(videoStreams[0].height, 194U); 1512 EXPECT_EQ(mVideoSink->mVideoFrame.timestamp_us(), 6000U); 1513 EXPECT_EQ(mVideoSink->mOnFrameCount, 6U); 1514 } 1515 1516 mControl.Update([&](auto& aControl) { 1517 VideoCodecConfig codecConfigScaleDownBy = *aControl.mVideoSendCodec.Ref(); 1518 codecConfigScaleDownBy.mEncodings[0].constraints.scaleDownBy = 1.3; 1519 aControl.mVideoSendCodec = Some(codecConfigScaleDownBy); 1520 }); 1521 ASSERT_TRUE(Call()->mVideoSendEncoderConfig); 1522 1523 { 1524 SendVideoFrame(641, 359, 7); 1525 const std::vector<webrtc::VideoStream> videoStreams = 1526 Call()->CreateEncoderStreams(mVideoSink->mVideoFrame.width(), 1527 mVideoSink->mVideoFrame.height()); 1528 EXPECT_EQ(videoStreams[0].width, 493U); 1529 EXPECT_EQ(videoStreams[0].height, 276U); 1530 EXPECT_EQ(mVideoSink->mVideoFrame.timestamp_us(), 7000U); 1531 EXPECT_EQ(mVideoSink->mOnFrameCount, 7U); 1532 } 1533 } 1534 1535 TEST_P(VideoConduitCodecModeTest, TestVideoEncode) { 1536 mControl.Update([&](auto& aControl) { 1537 aControl.mTransmitting = true; 1538 VideoCodecConfig codecConfig(120, "VP8", VideoEncodingConstraints()); 1539 codecConfig.mEncodings.emplace_back(); 1540 aControl.mVideoSendCodec = Some(codecConfig); 1541 aControl.mVideoSendRtpRtcpConfig = 1542 Some(RtpRtcpConfig(webrtc::RtcpMode::kCompound, true)); 1543 aControl.mVideoCodecMode = GetParam(); 1544 }); 1545 ASSERT_TRUE(Call()->mVideoSendEncoderConfig); 1546 1547 SendVideoFrame(1280, 720, 1); 1548 ASSERT_EQ(mVideoSink->mVideoFrame.width(), 1280); 1549 ASSERT_EQ(mVideoSink->mVideoFrame.height(), 720); 1550 ASSERT_EQ(mVideoSink->mVideoFrame.timestamp_us(), 1000U); 1551 ASSERT_EQ(mVideoSink->mOnFrameCount, 1U); 1552 1553 SendVideoFrame(640, 360, 2); 1554 ASSERT_EQ(mVideoSink->mVideoFrame.width(), 640); 1555 ASSERT_EQ(mVideoSink->mVideoFrame.height(), 360); 1556 ASSERT_EQ(mVideoSink->mVideoFrame.timestamp_us(), 2000U); 1557 ASSERT_EQ(mVideoSink->mOnFrameCount, 2U); 1558 1559 SendVideoFrame(1920, 1280, 3); 1560 ASSERT_EQ(mVideoSink->mVideoFrame.width(), 1920); 1561 ASSERT_EQ(mVideoSink->mVideoFrame.height(), 1280); 1562 ASSERT_EQ(mVideoSink->mVideoFrame.timestamp_us(), 3000U); 1563 ASSERT_EQ(mVideoSink->mOnFrameCount, 3U); 1564 } 1565 1566 TEST_P(VideoConduitCodecModeTest, TestVideoEncodeMaxFs) { 1567 mControl.Update([&](auto& aControl) { 1568 aControl.mTransmitting = true; 1569 VideoCodecConfig codecConfig(120, "VP8", VideoEncodingConstraints()); 1570 codecConfig.mEncodingConstraints.maxFs = 3600; 1571 codecConfig.mEncodings.emplace_back(); 1572 aControl.mVideoSendCodec = Some(codecConfig); 1573 aControl.mVideoSendRtpRtcpConfig = 1574 Some(RtpRtcpConfig(webrtc::RtcpMode::kCompound, true)); 1575 aControl.mVideoCodecMode = GetParam(); 1576 }); 1577 ASSERT_TRUE(Call()->mVideoSendEncoderConfig); 1578 1579 { 1580 SendVideoFrame(1280, 720, 1); 1581 const std::vector<webrtc::VideoStream> videoStreams = 1582 Call()->CreateEncoderStreams(mVideoSink->mVideoFrame.width(), 1583 mVideoSink->mVideoFrame.height()); 1584 ASSERT_EQ(videoStreams[0].width, 1280U); 1585 ASSERT_EQ(videoStreams[0].height, 720U); 1586 ASSERT_EQ(mVideoSink->mVideoFrame.timestamp_us(), 1000U); 1587 ASSERT_EQ(mVideoSink->mOnFrameCount, 1U); 1588 } 1589 1590 { 1591 SendVideoFrame(640, 360, 2); 1592 const std::vector<webrtc::VideoStream> videoStreams = 1593 Call()->CreateEncoderStreams(mVideoSink->mVideoFrame.width(), 1594 mVideoSink->mVideoFrame.height()); 1595 ASSERT_EQ(videoStreams[0].width, 640U); 1596 ASSERT_EQ(videoStreams[0].height, 360U); 1597 ASSERT_EQ(mVideoSink->mVideoFrame.timestamp_us(), 2000U); 1598 ASSERT_EQ(mVideoSink->mOnFrameCount, 2U); 1599 } 1600 1601 { 1602 SendVideoFrame(1920, 1280, 3); 1603 const std::vector<webrtc::VideoStream> videoStreams = 1604 Call()->CreateEncoderStreams(mVideoSink->mVideoFrame.width(), 1605 mVideoSink->mVideoFrame.height()); 1606 ASSERT_EQ(videoStreams[0].width, 1174U); 1607 ASSERT_EQ(videoStreams[0].height, 783U); 1608 ASSERT_EQ(mVideoSink->mVideoFrame.timestamp_us(), 3000U); 1609 ASSERT_EQ(mVideoSink->mOnFrameCount, 3U); 1610 } 1611 1612 // maxFs should not force pixel count above what a mVideoSink has requested. 1613 // We set 3600 macroblocks (16x16 pixels), so we request 3500 here. 1614 webrtc::VideoSinkWants wants; 1615 wants.max_pixel_count = 3500 * 16 * 16; 1616 mVideoFrameConverter->AddOrUpdateSink(mVideoSink.get(), wants); 1617 1618 { 1619 SendVideoFrame(1280, 720, 4); 1620 const std::vector<webrtc::VideoStream> videoStreams = 1621 Call()->CreateEncoderStreams(mVideoSink->mVideoFrame.width(), 1622 mVideoSink->mVideoFrame.height()); 1623 ASSERT_EQ(videoStreams[0].width, 960U); 1624 ASSERT_EQ(videoStreams[0].height, 540U); 1625 ASSERT_EQ(mVideoSink->mVideoFrame.timestamp_us(), 4000U); 1626 ASSERT_EQ(mVideoSink->mOnFrameCount, 4U); 1627 } 1628 1629 { 1630 SendVideoFrame(640, 360, 5); 1631 const std::vector<webrtc::VideoStream> videoStreams = 1632 Call()->CreateEncoderStreams(mVideoSink->mVideoFrame.width(), 1633 mVideoSink->mVideoFrame.height()); 1634 ASSERT_EQ(videoStreams[0].width, 640U); 1635 ASSERT_EQ(videoStreams[0].height, 360U); 1636 ASSERT_EQ(mVideoSink->mVideoFrame.timestamp_us(), 5000U); 1637 ASSERT_EQ(mVideoSink->mOnFrameCount, 5U); 1638 } 1639 1640 { 1641 SendVideoFrame(1920, 1280, 6); 1642 const std::vector<webrtc::VideoStream> videoStreams = 1643 Call()->CreateEncoderStreams(mVideoSink->mVideoFrame.width(), 1644 mVideoSink->mVideoFrame.height()); 1645 ASSERT_EQ(videoStreams[0].width, 960U); 1646 ASSERT_EQ(videoStreams[0].height, 640U); 1647 ASSERT_EQ(mVideoSink->mVideoFrame.timestamp_us(), 6000U); 1648 ASSERT_EQ(mVideoSink->mOnFrameCount, 6U); 1649 } 1650 } 1651 1652 TEST_P(VideoConduitCodecModeTest, TestVideoEncodeMaxFsNegotiatedThenSinkWants) { 1653 mControl.Update([&](auto& aControl) { 1654 aControl.mTransmitting = true; 1655 VideoCodecConfig codecConfig(120, "VP8", VideoEncodingConstraints()); 1656 codecConfig.mEncodings.emplace_back(); 1657 codecConfig.mEncodingConstraints.maxFs = 3500; 1658 aControl.mVideoSendCodec = Some(codecConfig); 1659 aControl.mVideoSendRtpRtcpConfig = 1660 Some(RtpRtcpConfig(webrtc::RtcpMode::kCompound, true)); 1661 aControl.mVideoCodecMode = GetParam(); 1662 }); 1663 ASSERT_TRUE(Call()->mVideoSendEncoderConfig); 1664 1665 unsigned int frame = 0; 1666 1667 { 1668 SendVideoFrame(1280, 720, frame++); 1669 const std::vector<webrtc::VideoStream> videoStreams = 1670 Call()->CreateEncoderStreams(mVideoSink->mVideoFrame.width(), 1671 mVideoSink->mVideoFrame.height()); 1672 ASSERT_EQ(videoStreams[0].width, 1260U); 1673 ASSERT_EQ(videoStreams[0].height, 709U); 1674 ASSERT_EQ(mVideoSink->mVideoFrame.timestamp_us(), (frame - 1) * 1000); 1675 ASSERT_EQ(mVideoSink->mOnFrameCount, frame); 1676 } 1677 1678 webrtc::VideoSinkWants wants; 1679 wants.max_pixel_count = 3600 * 16 * 16; 1680 mVideoFrameConverter->AddOrUpdateSink(mVideoSink.get(), wants); 1681 1682 { 1683 SendVideoFrame(1280, 720, frame++); 1684 const std::vector<webrtc::VideoStream> videoStreams = 1685 Call()->CreateEncoderStreams(mVideoSink->mVideoFrame.width(), 1686 mVideoSink->mVideoFrame.height()); 1687 ASSERT_EQ(videoStreams[0].width, 1260U); 1688 ASSERT_EQ(videoStreams[0].height, 709U); 1689 ASSERT_EQ(mVideoSink->mVideoFrame.timestamp_us(), (frame - 1) * 1000); 1690 ASSERT_EQ(mVideoSink->mOnFrameCount, frame); 1691 } 1692 } 1693 1694 TEST_P(VideoConduitCodecModeTest, TestVideoEncodeMaxFsCodecChange) { 1695 mControl.Update([&](auto& aControl) { 1696 aControl.mTransmitting = true; 1697 VideoCodecConfig codecConfig(120, "VP8", VideoEncodingConstraints()); 1698 codecConfig.mEncodings.emplace_back(); 1699 codecConfig.mEncodingConstraints.maxFs = 3500; 1700 aControl.mVideoSendCodec = Some(codecConfig); 1701 aControl.mVideoSendRtpRtcpConfig = 1702 Some(RtpRtcpConfig(webrtc::RtcpMode::kCompound, true)); 1703 aControl.mVideoCodecMode = GetParam(); 1704 }); 1705 ASSERT_TRUE(Call()->mVideoSendEncoderConfig); 1706 1707 unsigned int frame = 0; 1708 1709 { 1710 SendVideoFrame(1280, 720, frame++); 1711 const std::vector<webrtc::VideoStream> videoStreams = 1712 Call()->CreateEncoderStreams(mVideoSink->mVideoFrame.width(), 1713 mVideoSink->mVideoFrame.height()); 1714 ASSERT_EQ(videoStreams[0].width, 1260U); 1715 ASSERT_EQ(videoStreams[0].height, 709U); 1716 ASSERT_EQ(mVideoSink->mVideoFrame.timestamp_us(), (frame - 1) * 1000); 1717 ASSERT_EQ(mVideoSink->mOnFrameCount, frame); 1718 } 1719 1720 mControl.Update([&](auto& aControl) { 1721 VideoCodecConfig codecConfig(121, "VP9", VideoEncodingConstraints()); 1722 codecConfig.mEncodings.emplace_back(); 1723 codecConfig.mEncodingConstraints.maxFs = 3500; 1724 aControl.mVideoSendCodec = Some(codecConfig); 1725 }); 1726 ASSERT_TRUE(Call()->mVideoSendEncoderConfig); 1727 1728 { 1729 SendVideoFrame(1280, 720, frame++); 1730 const std::vector<webrtc::VideoStream> videoStreams = 1731 Call()->CreateEncoderStreams(mVideoSink->mVideoFrame.width(), 1732 mVideoSink->mVideoFrame.height()); 1733 ASSERT_EQ(videoStreams[0].width, 1260U); 1734 ASSERT_EQ(videoStreams[0].height, 709U); 1735 ASSERT_EQ(mVideoSink->mVideoFrame.timestamp_us(), (frame - 1) * 1000); 1736 ASSERT_EQ(mVideoSink->mOnFrameCount, frame); 1737 } 1738 } 1739 1740 TEST_P(VideoConduitCodecModeTest, 1741 TestVideoEncodeMaxFsSinkWantsThenCodecChange) { 1742 mControl.Update([&](auto& aControl) { 1743 aControl.mTransmitting = true; 1744 VideoCodecConfig codecConfig(120, "VP8", VideoEncodingConstraints()); 1745 codecConfig.mEncodings.emplace_back(); 1746 aControl.mVideoSendCodec = Some(codecConfig); 1747 aControl.mVideoSendRtpRtcpConfig = 1748 Some(RtpRtcpConfig(webrtc::RtcpMode::kCompound, true)); 1749 aControl.mVideoCodecMode = GetParam(); 1750 }); 1751 ASSERT_TRUE(Call()->mVideoSendEncoderConfig); 1752 1753 webrtc::VideoSinkWants wants; 1754 wants.max_pixel_count = 3500 * 16 * 16; 1755 mVideoFrameConverter->AddOrUpdateSink(mVideoSink.get(), wants); 1756 1757 unsigned int frame = 0; 1758 1759 SendVideoFrame(1280, 720, frame++); 1760 const std::vector<webrtc::VideoStream> videoStreams = 1761 Call()->CreateEncoderStreams(mVideoSink->mVideoFrame.width(), 1762 mVideoSink->mVideoFrame.height()); 1763 ASSERT_EQ(videoStreams[0].width, 960U); 1764 ASSERT_EQ(videoStreams[0].height, 540U); 1765 ASSERT_EQ(mVideoSink->mVideoFrame.timestamp_us(), (frame - 1) * 1000); 1766 ASSERT_EQ(mVideoSink->mOnFrameCount, frame); 1767 1768 mControl.Update([&](auto& aControl) { 1769 VideoCodecConfig codecConfig(121, "VP9", VideoEncodingConstraints()); 1770 codecConfig.mEncodings.emplace_back(); 1771 aControl.mVideoSendCodec = Some(codecConfig); 1772 }); 1773 ASSERT_TRUE(Call()->mVideoSendEncoderConfig); 1774 1775 { 1776 SendVideoFrame(1280, 720, frame++); 1777 const std::vector<webrtc::VideoStream> videoStreams = 1778 Call()->CreateEncoderStreams(mVideoSink->mVideoFrame.width(), 1779 mVideoSink->mVideoFrame.height()); 1780 ASSERT_EQ(videoStreams[0].width, 960U); 1781 ASSERT_EQ(videoStreams[0].height, 540U); 1782 ASSERT_EQ(mVideoSink->mVideoFrame.timestamp_us(), (frame - 1) * 1000); 1783 ASSERT_EQ(mVideoSink->mOnFrameCount, frame); 1784 } 1785 } 1786 1787 TEST_P(VideoConduitCodecModeTest, TestVideoEncodeMaxFsNegotiated) { 1788 mControl.Update([&](auto& aControl) { 1789 aControl.mTransmitting = true; 1790 VideoCodecConfig codecConfig(120, "VP8", VideoEncodingConstraints()); 1791 codecConfig.mEncodings.emplace_back(); 1792 aControl.mVideoSendCodec = Some(codecConfig); 1793 aControl.mVideoSendRtpRtcpConfig = 1794 Some(RtpRtcpConfig(webrtc::RtcpMode::kCompound, true)); 1795 aControl.mVideoCodecMode = GetParam(); 1796 }); 1797 ASSERT_TRUE(Call()->mVideoSendEncoderConfig); 1798 1799 unsigned int frame = 0; 1800 SendVideoFrame(1280, 720, frame++); 1801 ASSERT_EQ(mVideoSink->mVideoFrame.width(), 1280); 1802 ASSERT_EQ(mVideoSink->mVideoFrame.height(), 720); 1803 ASSERT_EQ(mVideoSink->mVideoFrame.timestamp_us(), (frame - 1) * 1000); 1804 ASSERT_EQ(mVideoSink->mOnFrameCount, frame); 1805 1806 // Ensure that negotiating a new max-fs works 1807 mControl.Update([&](auto& aControl) { 1808 VideoCodecConfig codecConfig = *aControl.mVideoSendCodec.Ref(); 1809 codecConfig.mEncodingConstraints.maxFs = 3500; 1810 aControl.mVideoSendCodec = Some(codecConfig); 1811 }); 1812 ASSERT_TRUE(Call()->mVideoSendEncoderConfig); 1813 1814 { 1815 SendVideoFrame(1280, 720, frame++); 1816 const std::vector<webrtc::VideoStream> videoStreams = 1817 Call()->CreateEncoderStreams(mVideoSink->mVideoFrame.width(), 1818 mVideoSink->mVideoFrame.height()); 1819 ASSERT_EQ(videoStreams[0].width, 1260U); 1820 ASSERT_EQ(videoStreams[0].height, 709U); 1821 ASSERT_EQ(mVideoSink->mVideoFrame.timestamp_us(), (frame - 1) * 1000); 1822 ASSERT_EQ(mVideoSink->mOnFrameCount, frame); 1823 } 1824 1825 // Ensure that negotiating max-fs away works 1826 mControl.Update([&](auto& aControl) { 1827 VideoCodecConfig codecConfig = *aControl.mVideoSendCodec.Ref(); 1828 codecConfig.mEncodingConstraints.maxFs = 0; 1829 aControl.mVideoSendCodec = Some(codecConfig); 1830 }); 1831 ASSERT_TRUE(Call()->mVideoSendEncoderConfig); 1832 1833 SendVideoFrame(1280, 720, frame++); 1834 ASSERT_EQ(mVideoSink->mVideoFrame.width(), 1280); 1835 ASSERT_EQ(mVideoSink->mVideoFrame.height(), 720); 1836 ASSERT_EQ(mVideoSink->mVideoFrame.timestamp_us(), (frame - 1) * 1000); 1837 ASSERT_EQ(mVideoSink->mOnFrameCount, frame); 1838 } 1839 1840 TEST_P(VideoConduitCodecModeTest, TestVideoEncodeMaxWidthAndHeight) { 1841 mControl.Update([&](auto& aControl) { 1842 aControl.mTransmitting = true; 1843 VideoCodecConfig codecConfig(120, "VP8", VideoEncodingConstraints()); 1844 codecConfig.mEncodingConstraints.maxWidth = 1280; 1845 codecConfig.mEncodingConstraints.maxHeight = 720; 1846 codecConfig.mEncodings.emplace_back(); 1847 aControl.mVideoSendCodec = Some(codecConfig); 1848 aControl.mVideoSendRtpRtcpConfig = 1849 Some(RtpRtcpConfig(webrtc::RtcpMode::kCompound, true)); 1850 aControl.mVideoCodecMode = GetParam(); 1851 }); 1852 ASSERT_TRUE(Call()->mVideoSendEncoderConfig); 1853 1854 SendVideoFrame(1280, 720, 1); 1855 ASSERT_EQ(mVideoSink->mVideoFrame.width(), 1280); 1856 ASSERT_EQ(mVideoSink->mVideoFrame.height(), 720); 1857 ASSERT_EQ(mVideoSink->mVideoFrame.timestamp_us(), 1000U); 1858 ASSERT_EQ(mVideoSink->mOnFrameCount, 1U); 1859 1860 SendVideoFrame(640, 360, 2); 1861 ASSERT_EQ(mVideoSink->mVideoFrame.width(), 640); 1862 ASSERT_EQ(mVideoSink->mVideoFrame.height(), 360); 1863 ASSERT_EQ(mVideoSink->mVideoFrame.timestamp_us(), 2000U); 1864 ASSERT_EQ(mVideoSink->mOnFrameCount, 2U); 1865 1866 { 1867 SendVideoFrame(1920, 1280, 3); 1868 const std::vector<webrtc::VideoStream> videoStreams = 1869 Call()->CreateEncoderStreams(mVideoSink->mVideoFrame.width(), 1870 mVideoSink->mVideoFrame.height()); 1871 ASSERT_EQ(videoStreams[0].width, 1080U); 1872 ASSERT_EQ(videoStreams[0].height, 720U); 1873 ASSERT_EQ(mVideoSink->mVideoFrame.timestamp_us(), 3000U); 1874 ASSERT_EQ(mVideoSink->mOnFrameCount, 3U); 1875 } 1876 } 1877 1878 TEST_P(VideoConduitCodecModeTest, TestVideoEncodeScaleResolutionBy) { 1879 mControl.Update([&](auto& aControl) { 1880 aControl.mTransmitting = true; 1881 VideoCodecConfig codecConfig(120, "VP8", VideoEncodingConstraints()); 1882 codecConfig.mEncodingConstraints.maxFs = 3600; 1883 auto& encoding = codecConfig.mEncodings.emplace_back(); 1884 encoding.constraints.scaleDownBy = 2; 1885 aControl.mVideoSendCodec = Some(codecConfig); 1886 aControl.mVideoSendRtpRtcpConfig = 1887 Some(RtpRtcpConfig(webrtc::RtcpMode::kCompound, true)); 1888 aControl.mVideoCodecMode = GetParam(); 1889 }); 1890 ASSERT_TRUE(Call()->mVideoSendEncoderConfig); 1891 1892 { 1893 SendVideoFrame(1280, 720, 1); 1894 const std::vector<webrtc::VideoStream> videoStreams = 1895 Call()->CreateEncoderStreams(mVideoSink->mVideoFrame.width(), 1896 mVideoSink->mVideoFrame.height()); 1897 ASSERT_EQ(videoStreams[0].width, 640U); 1898 ASSERT_EQ(videoStreams[0].height, 360U); 1899 ASSERT_EQ(mVideoSink->mVideoFrame.timestamp_us(), 1000U); 1900 ASSERT_EQ(mVideoSink->mOnFrameCount, 1U); 1901 } 1902 1903 { 1904 SendVideoFrame(640, 360, 2); 1905 const std::vector<webrtc::VideoStream> videoStreams = 1906 Call()->CreateEncoderStreams(mVideoSink->mVideoFrame.width(), 1907 mVideoSink->mVideoFrame.height()); 1908 ASSERT_EQ(videoStreams[0].width, 320U); 1909 ASSERT_EQ(videoStreams[0].height, 180U); 1910 ASSERT_EQ(mVideoSink->mVideoFrame.timestamp_us(), 2000U); 1911 ASSERT_EQ(mVideoSink->mOnFrameCount, 2U); 1912 } 1913 } 1914 1915 TEST_P(VideoConduitCodecModeTest, TestVideoEncodeSimulcastScaleResolutionBy) { 1916 mControl.Update([&](auto& aControl) { 1917 VideoCodecConfig codecConfig(120, "VP8", VideoEncodingConstraints()); 1918 { 1919 auto& encoding = codecConfig.mEncodings.emplace_back(); 1920 encoding.constraints.scaleDownBy = 2; 1921 } 1922 { 1923 auto& encoding = codecConfig.mEncodings.emplace_back(); 1924 encoding.constraints.scaleDownBy = 3; 1925 } 1926 { 1927 auto& encoding = codecConfig.mEncodings.emplace_back(); 1928 encoding.constraints.scaleDownBy = 4; 1929 } 1930 1931 aControl.mTransmitting = true; 1932 aControl.mVideoSendCodec = Some(codecConfig); 1933 aControl.mVideoSendRtpRtcpConfig = 1934 Some(RtpRtcpConfig(webrtc::RtcpMode::kCompound, true)); 1935 aControl.mVideoCodecMode = GetParam(); 1936 aControl.mLocalSsrcs = {42, 43, 44}; 1937 aControl.mLocalVideoRtxSsrcs = {45, 46, 47}; 1938 }); 1939 ASSERT_TRUE(Call()->mVideoSendEncoderConfig); 1940 1941 { 1942 SendVideoFrame(640, 480, 1); 1943 const std::vector<webrtc::VideoStream> videoStreams = 1944 Call()->CreateEncoderStreams(mVideoSink->mVideoFrame.width(), 1945 mVideoSink->mVideoFrame.height()); 1946 ASSERT_EQ(videoStreams[0].width, 320U); 1947 ASSERT_EQ(videoStreams[0].height, 240U); 1948 ASSERT_EQ(mVideoSink->mVideoFrame.timestamp_us(), 1000U); 1949 ASSERT_EQ(mVideoSink->mOnFrameCount, 1U); 1950 } 1951 1952 { 1953 SendVideoFrame(1280, 720, 2); 1954 const std::vector<webrtc::VideoStream> videoStreams = 1955 Call()->CreateEncoderStreams(mVideoSink->mVideoFrame.width(), 1956 mVideoSink->mVideoFrame.height()); 1957 ASSERT_EQ(videoStreams[0].width, 640U); 1958 ASSERT_EQ(videoStreams[0].height, 360U); 1959 ASSERT_EQ(mVideoSink->mVideoFrame.timestamp_us(), 2000U); 1960 ASSERT_EQ(mVideoSink->mOnFrameCount, 2U); 1961 } 1962 } 1963 1964 TEST_P(VideoConduitCodecModeTest, 1965 TestVideoEncodeLargeScaleResolutionByFrameDropping) { 1966 const std::vector<std::vector<uint32_t>> scalesList = { 1967 {200U}, {200U, 300U}, {300U, 200U}}; 1968 int64_t capture_time_ms = 0; 1969 for (size_t i = 0; i < scalesList.size(); ++i) { 1970 const auto& scales = scalesList[i]; 1971 mControl.Update([&](auto& aControl) { 1972 aControl.mTransmitting = true; 1973 VideoCodecConfig codecConfig(120, "VP8", VideoEncodingConstraints()); 1974 for (const auto& scale : scales) { 1975 auto& encoding = codecConfig.mEncodings.emplace_back(); 1976 encoding.constraints.scaleDownBy = scale; 1977 } 1978 aControl.mVideoSendCodec = Some(codecConfig); 1979 aControl.mVideoSendRtpRtcpConfig = 1980 Some(RtpRtcpConfig(webrtc::RtcpMode::kCompound, true)); 1981 aControl.mVideoCodecMode = GetParam(); 1982 aControl.mLocalSsrcs = scales; 1983 }); 1984 ASSERT_TRUE(Call()->mVideoSendEncoderConfig); 1985 1986 { 1987 // If all layers' scaleDownBy is larger than any input dimension, that 1988 // dimension becomes zero. 1989 SendVideoFrame(199, 199, ++capture_time_ms); 1990 const std::vector<webrtc::VideoStream> videoStreams = 1991 Call()->CreateEncoderStreams(mVideoSink->mVideoFrame.width(), 1992 mVideoSink->mVideoFrame.height()); 1993 ASSERT_EQ(videoStreams.size(), scales.size()); 1994 for (size_t j = 0; j < scales.size(); ++j) { 1995 EXPECT_EQ(videoStreams[j].width, 0U) 1996 << " for scalesList[" << i << "][" << j << "]"; 1997 EXPECT_EQ(videoStreams[j].height, 0U) 1998 << " for scalesList[" << i << "][" << j << "]"; 1999 } 2000 } 2001 2002 { 2003 // If only width becomes zero, height is also set to zero. 2004 SendVideoFrame(199, 200, ++capture_time_ms); 2005 const std::vector<webrtc::VideoStream> videoStreams = 2006 Call()->CreateEncoderStreams(mVideoSink->mVideoFrame.width(), 2007 mVideoSink->mVideoFrame.height()); 2008 ASSERT_EQ(videoStreams.size(), scales.size()); 2009 for (size_t j = 0; j < scales.size(); ++j) { 2010 EXPECT_EQ(videoStreams[j].width, 0U) 2011 << " for scalesList[" << i << "][" << j << "]"; 2012 EXPECT_EQ(videoStreams[j].height, 0U) 2013 << " for scalesList[" << i << "][" << j << "]"; 2014 } 2015 } 2016 2017 { 2018 // If only height becomes zero, width is also set to zero. 2019 SendVideoFrame(200, 199, ++capture_time_ms); 2020 const std::vector<webrtc::VideoStream> videoStreams = 2021 Call()->CreateEncoderStreams(mVideoSink->mVideoFrame.width(), 2022 mVideoSink->mVideoFrame.height()); 2023 ASSERT_EQ(videoStreams.size(), scales.size()); 2024 for (size_t j = 0; j < scales.size(); ++j) { 2025 EXPECT_EQ(videoStreams[j].width, 0U) 2026 << " for scalesList[" << i << "][" << j << "]"; 2027 EXPECT_EQ(videoStreams[j].height, 0U) 2028 << " for scalesList[" << i << "][" << j << "]"; 2029 } 2030 } 2031 2032 { 2033 // If dimensions are non-zero, we pass through. 2034 SendVideoFrame(200, 200, ++capture_time_ms); 2035 const std::vector<webrtc::VideoStream> videoStreams = 2036 Call()->CreateEncoderStreams(mVideoSink->mVideoFrame.width(), 2037 mVideoSink->mVideoFrame.height()); 2038 ASSERT_EQ(videoStreams.size(), scales.size()); 2039 for (size_t j = 0; j < scales.size(); ++j) { 2040 EXPECT_EQ(videoStreams[j].width, scales[j] <= 200U ? 1U : 0U) 2041 << " for scalesList[" << i << "][" << j << "]"; 2042 EXPECT_EQ(videoStreams[j].height, scales[j] <= 200U ? 1U : 0U) 2043 << " for scalesList[" << i << "][" << j << "]"; 2044 } 2045 } 2046 } 2047 } 2048 2049 TEST_P(VideoConduitCodecModeTest, 2050 TestVideoEncodeLargeScaleResolutionByStreamCreation) { 2051 for (const auto& scales : 2052 {std::vector{200U}, std::vector{200U, 300U}, std::vector{300U, 200U}}) { 2053 mControl.Update([&](auto& aControl) { 2054 aControl.mTransmitting = true; 2055 VideoCodecConfig codecConfig(120, "VP8", VideoEncodingConstraints()); 2056 for (const auto& scale : scales) { 2057 auto& encoding = codecConfig.mEncodings.emplace_back(); 2058 encoding.constraints.scaleDownBy = scale; 2059 } 2060 aControl.mVideoSendCodec = Some(codecConfig); 2061 aControl.mVideoSendRtpRtcpConfig = 2062 Some(RtpRtcpConfig(webrtc::RtcpMode::kCompound, true)); 2063 aControl.mVideoCodecMode = GetParam(); 2064 aControl.mLocalSsrcs = scales; 2065 }); 2066 ASSERT_TRUE(Call()->mVideoSendEncoderConfig); 2067 2068 { 2069 // If dimensions scale to <1, we create a 0x0 stream. 2070 const std::vector<webrtc::VideoStream> videoStreams = 2071 Call()->CreateEncoderStreams(199, 199); 2072 ASSERT_EQ(videoStreams.size(), scales.size()); 2073 for (const auto& stream : videoStreams) { 2074 EXPECT_EQ(stream.width, 0U); 2075 EXPECT_EQ(stream.height, 0U); 2076 } 2077 } 2078 2079 { 2080 // If width scales to <1, we create a 0x0 stream. 2081 const std::vector<webrtc::VideoStream> videoStreams = 2082 Call()->CreateEncoderStreams(199, 200); 2083 ASSERT_EQ(videoStreams.size(), scales.size()); 2084 for (const auto& stream : videoStreams) { 2085 EXPECT_EQ(stream.width, 0U); 2086 EXPECT_EQ(stream.height, 0U); 2087 } 2088 } 2089 2090 { 2091 // If height scales to <1, we create a 0x0 stream. 2092 const std::vector<webrtc::VideoStream> videoStreams = 2093 Call()->CreateEncoderStreams(200, 199); 2094 ASSERT_EQ(videoStreams.size(), scales.size()); 2095 for (const auto& stream : videoStreams) { 2096 EXPECT_EQ(stream.width, 0U); 2097 EXPECT_EQ(stream.height, 0U); 2098 } 2099 } 2100 2101 { 2102 // If dimensions scale to 1, we create a 1x1 stream. 2103 const std::vector<webrtc::VideoStream> videoStreams = 2104 Call()->CreateEncoderStreams(200, 200); 2105 ASSERT_EQ(videoStreams.size(), scales.size()); 2106 for (size_t i = 0; i < scales.size(); ++i) { 2107 const auto& stream = videoStreams[i]; 2108 const auto scale = scales[i]; 2109 EXPECT_EQ(stream.width, scale <= 200U ? 1U : 0U); 2110 EXPECT_EQ(stream.height, scale <= 200U ? 1U : 0U); 2111 } 2112 } 2113 2114 { 2115 // If one dimension scales to 0 and the other >1, we create a 0x0 stream. 2116 const std::vector<webrtc::VideoStream> videoStreams = 2117 Call()->CreateEncoderStreams(400, 199); 2118 ASSERT_EQ(videoStreams.size(), scales.size()); 2119 for (const auto& stream : videoStreams) { 2120 EXPECT_EQ(stream.width, 0U); 2121 EXPECT_EQ(stream.height, 0U); 2122 } 2123 } 2124 2125 { 2126 // Legit case scaling down to more than 1x1. 2127 const std::vector<webrtc::VideoStream> videoStreams = 2128 Call()->CreateEncoderStreams(600, 400); 2129 ASSERT_EQ(videoStreams.size(), scales.size()); 2130 for (size_t i = 0; i < scales.size(); ++i) { 2131 // Streams are backwards for some reason 2132 const auto& stream = videoStreams[i]; 2133 const auto& scale = scales[i]; 2134 if (scale == 200U) { 2135 EXPECT_EQ(stream.width, 3U); 2136 EXPECT_EQ(stream.height, 2U); 2137 } else { 2138 EXPECT_EQ(stream.width, 2U); 2139 EXPECT_EQ(stream.height, 1U); 2140 } 2141 } 2142 } 2143 } 2144 } 2145 2146 TEST_P(VideoConduitCodecModeTest, TestVideoEncodeResolutionAlignment) { 2147 for (const auto& scales : {std::vector{1U}, std::vector{1U, 9U}}) { 2148 mControl.Update([&](auto& aControl) { 2149 aControl.mTransmitting = true; 2150 VideoCodecConfig codecConfig(120, "VP8", VideoEncodingConstraints()); 2151 for (const auto& scale : scales) { 2152 auto& encoding = codecConfig.mEncodings.emplace_back(); 2153 encoding.constraints.scaleDownBy = scale; 2154 } 2155 aControl.mVideoSendCodec = Some(codecConfig); 2156 aControl.mVideoSendRtpRtcpConfig = 2157 Some(RtpRtcpConfig(webrtc::RtcpMode::kCompound, true)); 2158 aControl.mVideoCodecMode = GetParam(); 2159 aControl.mLocalSsrcs = scales; 2160 }); 2161 ASSERT_TRUE(Call()->mVideoSendEncoderConfig); 2162 2163 for (const auto& alignment : {2, 16, 39, 400, 1000}) { 2164 // Test that requesting specific alignment always results in the expected 2165 // number of layers and valid alignment. 2166 2167 // Mimic what libwebrtc would do for a given alignment. 2168 webrtc::VideoEncoder::EncoderInfo info; 2169 info.requested_resolution_alignment = alignment; 2170 Call()->SetEncoderInfo(info); 2171 2172 const std::vector<webrtc::VideoStream> videoStreams = 2173 Call()->CreateEncoderStreams(640, 480); 2174 ASSERT_EQ(videoStreams.size(), scales.size()); 2175 for (size_t i = 0; i < videoStreams.size(); ++i) { 2176 // videoStreams is backwards 2177 const auto& stream = videoStreams[i]; 2178 const auto& scale = scales[i]; 2179 EXPECT_EQ(stream.width % alignment, 0U) 2180 << " for scale " << scale << " and alignment " << alignment; 2181 EXPECT_EQ(stream.height % alignment, 0U); 2182 } 2183 } 2184 } 2185 } 2186 2187 TEST_F(VideoConduitTest, TestSettingRtpRtcpRsize) { 2188 mControl.Update([&](auto& aControl) { 2189 VideoCodecConfig codecConfig(120, "VP8", VideoEncodingConstraints()); 2190 codecConfig.mEncodings.emplace_back(); 2191 RtpRtcpConfig rtcpConf(webrtc::RtcpMode::kReducedSize, true); 2192 2193 aControl.mReceiving = true; 2194 aControl.mVideoRecvCodecs = {codecConfig}; 2195 aControl.mVideoRecvRtpRtcpConfig = Some(rtcpConf); 2196 aControl.mTransmitting = true; 2197 aControl.mVideoSendCodec = Some(codecConfig); 2198 aControl.mVideoSendRtpRtcpConfig = Some(rtcpConf); 2199 }); 2200 ASSERT_TRUE(Call()->mVideoReceiveConfig); 2201 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.rtcp_mode, 2202 webrtc::RtcpMode::kReducedSize); 2203 ASSERT_TRUE(Call()->mVideoSendConfig); 2204 ASSERT_EQ(Call()->mVideoSendConfig->rtp.rtcp_mode, 2205 webrtc::RtcpMode::kReducedSize); 2206 } 2207 2208 TEST_F(VideoConduitTest, TestRemoteSsrcDefault) { 2209 mControl.Update([&](auto& aControl) { 2210 aControl.mRemoteSsrc = 0; 2211 aControl.mLocalSsrcs = {1}; 2212 VideoCodecConfig codecConfig(120, "VP8", VideoEncodingConstraints()); 2213 codecConfig.mEncodings.emplace_back(); 2214 aControl.mVideoSendCodec = Some(codecConfig); 2215 aControl.mVideoSendRtpRtcpConfig = 2216 Some(RtpRtcpConfig(webrtc::RtcpMode::kCompound, true)); 2217 aControl.mReceiving = true; 2218 aControl.mTransmitting = true; 2219 }); 2220 ASSERT_TRUE(Call()->mVideoReceiveConfig); 2221 ASSERT_THAT(Call()->mVideoReceiveConfig->rtp.remote_ssrc, 2222 Not(testing::AnyOf(0U, 1U))); 2223 ASSERT_TRUE(Call()->mVideoSendConfig); 2224 ASSERT_THAT(Call()->mVideoSendConfig->rtp.ssrcs, ElementsAre(1U)); 2225 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.local_ssrc, 2226 Call()->mVideoSendConfig->rtp.ssrcs[0]); 2227 } 2228 2229 TEST_F(VideoConduitTest, TestRemoteSsrcCollision) { 2230 mControl.Update([&](auto& aControl) { 2231 aControl.mRemoteSsrc = 1; 2232 aControl.mLocalSsrcs = {1}; 2233 VideoCodecConfig codecConfig(120, "VP8", VideoEncodingConstraints()); 2234 codecConfig.mEncodings.emplace_back(); 2235 aControl.mVideoSendCodec = Some(codecConfig); 2236 aControl.mVideoSendRtpRtcpConfig = 2237 Some(RtpRtcpConfig(webrtc::RtcpMode::kCompound, true)); 2238 aControl.mReceiving = true; 2239 aControl.mTransmitting = true; 2240 }); 2241 EXPECT_TRUE(Call()->mVideoReceiveConfig); 2242 EXPECT_EQ(Call()->mVideoReceiveConfig->rtp.remote_ssrc, 1U); 2243 EXPECT_TRUE(Call()->mVideoSendConfig); 2244 EXPECT_THAT(Call()->mVideoSendConfig->rtp.ssrcs, 2245 ElementsAre(Not(testing::AnyOf(0U, 1U)))); 2246 EXPECT_EQ(Call()->mVideoReceiveConfig->rtp.local_ssrc, 2247 Call()->mVideoSendConfig->rtp.ssrcs[0]); 2248 } 2249 2250 TEST_F(VideoConduitTest, TestLocalSsrcDefault) { 2251 mControl.Update([&](auto& aControl) { 2252 aControl.mRemoteSsrc = 1; 2253 aControl.mLocalSsrcs = {}; 2254 VideoCodecConfig codecConfig(120, "VP8", VideoEncodingConstraints()); 2255 codecConfig.mEncodings.emplace_back(); 2256 aControl.mVideoSendCodec = Some(codecConfig); 2257 aControl.mVideoSendRtpRtcpConfig = 2258 Some(RtpRtcpConfig(webrtc::RtcpMode::kCompound, true)); 2259 aControl.mReceiving = true; 2260 aControl.mTransmitting = true; 2261 }); 2262 ASSERT_TRUE(Call()->mVideoReceiveConfig); 2263 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.remote_ssrc, 1U); 2264 ASSERT_TRUE(Call()->mVideoSendConfig); 2265 ASSERT_THAT(Call()->mVideoSendConfig->rtp.ssrcs, 2266 ElementsAre(Not(testing::AnyOf(0U, 1U)))); 2267 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.local_ssrc, 2268 Call()->mVideoSendConfig->rtp.ssrcs[0]); 2269 } 2270 2271 TEST_F(VideoConduitTest, TestLocalSsrcCollision) { 2272 mControl.Update([&](auto& aControl) { 2273 aControl.mRemoteSsrc = 1; 2274 aControl.mLocalSsrcs = {2, 2}; 2275 VideoCodecConfig codecConfig(120, "VP8", VideoEncodingConstraints()); 2276 codecConfig.mEncodings.emplace_back(); 2277 codecConfig.mEncodings.emplace_back(); 2278 aControl.mVideoSendCodec = Some(codecConfig); 2279 aControl.mVideoSendRtpRtcpConfig = 2280 Some(RtpRtcpConfig(webrtc::RtcpMode::kCompound, true)); 2281 aControl.mReceiving = true; 2282 aControl.mTransmitting = true; 2283 }); 2284 ASSERT_TRUE(Call()->mVideoReceiveConfig); 2285 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.remote_ssrc, 1U); 2286 ASSERT_TRUE(Call()->mVideoSendConfig); 2287 ASSERT_THAT(Call()->mVideoSendConfig->rtp.ssrcs, 2288 ElementsAre(2U, Not(testing::AnyOf(0U, 2U)))); 2289 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.local_ssrc, 2290 Call()->mVideoSendConfig->rtp.ssrcs[0]); 2291 } 2292 2293 TEST_F(VideoConduitTest, TestLocalSsrcUnorderedCollision) { 2294 mControl.Update([&](auto& aControl) { 2295 aControl.mRemoteSsrc = 1; 2296 aControl.mLocalSsrcs = {2, 3, 2}; 2297 VideoCodecConfig codecConfig(120, "VP8", VideoEncodingConstraints()); 2298 for (int i = 0; i < 3; ++i) { 2299 codecConfig.mEncodings.emplace_back(); 2300 } 2301 aControl.mVideoSendCodec = Some(codecConfig); 2302 aControl.mVideoSendRtpRtcpConfig = 2303 Some(RtpRtcpConfig(webrtc::RtcpMode::kCompound, true)); 2304 aControl.mReceiving = true; 2305 aControl.mTransmitting = true; 2306 }); 2307 ASSERT_TRUE(Call()->mVideoReceiveConfig); 2308 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.remote_ssrc, 1U); 2309 ASSERT_TRUE(Call()->mVideoSendConfig); 2310 ASSERT_THAT(Call()->mVideoSendConfig->rtp.ssrcs, 2311 ElementsAre(2U, 3U, Not(testing::AnyOf(0U, 2U)))); 2312 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.local_ssrc, 2313 Call()->mVideoSendConfig->rtp.ssrcs[0]); 2314 } 2315 2316 TEST_F(VideoConduitTest, TestLocalAndRemoteSsrcCollision) { 2317 mControl.Update([&](auto& aControl) { 2318 aControl.mRemoteSsrc = 1; 2319 aControl.mLocalSsrcs = {1, 2, 2}; 2320 VideoCodecConfig codecConfig(120, "VP8", VideoEncodingConstraints()); 2321 for (int i = 0; i < 3; ++i) { 2322 codecConfig.mEncodings.emplace_back(); 2323 } 2324 aControl.mVideoSendCodec = Some(codecConfig); 2325 aControl.mVideoSendRtpRtcpConfig = 2326 Some(RtpRtcpConfig(webrtc::RtcpMode::kCompound, true)); 2327 aControl.mReceiving = true; 2328 aControl.mTransmitting = true; 2329 }); 2330 ASSERT_TRUE(Call()->mVideoReceiveConfig); 2331 ASSERT_THAT(Call()->mVideoReceiveConfig->rtp.remote_ssrc, 1U); 2332 ASSERT_TRUE(Call()->mVideoSendConfig); 2333 ASSERT_THAT(Call()->mVideoSendConfig->rtp.ssrcs, 2334 ElementsAre(Not(testing::AnyOf(0U, 1U, 2U)), 2U, 2335 Not(testing::AnyOf( 2336 0U, 1U, 2U, 2337 Call()->mVideoReceiveConfig->rtp.remote_ssrc)))); 2338 ASSERT_EQ(Call()->mVideoReceiveConfig->rtp.local_ssrc, 2339 Call()->mVideoSendConfig->rtp.ssrcs[0]); 2340 } 2341 2342 TEST_F(VideoConduitTest, TestExternalRemoteSsrcCollision) { 2343 auto other = MakeRefPtr<MockConduit>(); 2344 mCallWrapper->RegisterConduit(other); 2345 2346 // First the mControl update should trigger an UnsetRemoteSSRC(1) from us. 2347 // Then we simulate another conduit using that same ssrc, which should trigger 2348 // us to generate a fresh ssrc that is not 0 and not 1. 2349 { 2350 InSequence s; 2351 EXPECT_CALL(*other, UnsetRemoteSSRC(1U)).Times(2); 2352 EXPECT_CALL(*other, UnsetRemoteSSRC(Not(testing::AnyOf(0U, 1U)))); 2353 } 2354 2355 mControl.Update([&](auto& aControl) { 2356 aControl.mRemoteSsrc = 1; 2357 aControl.mReceiving = true; 2358 }); 2359 EXPECT_TRUE(Call()->mVideoReceiveConfig); 2360 EXPECT_EQ(Call()->mVideoReceiveConfig->rtp.remote_ssrc, 1U); 2361 2362 (void)WaitFor(InvokeAsync( 2363 GetCurrentSerialEventTarget(), __func__, [wrapper = mCallWrapper] { 2364 wrapper->UnsetRemoteSSRC(1); 2365 return GenericPromise::CreateAndResolve(true, __func__); 2366 })); 2367 2368 EXPECT_TRUE(Call()->mVideoReceiveConfig); 2369 EXPECT_THAT(Call()->mVideoReceiveConfig->rtp.remote_ssrc, 2370 Not(testing::AnyOf(0U, 1U))); 2371 } 2372 2373 TEST_F(VideoConduitTest, TestVideoConfigurationH264) { 2374 const int profileLevelId1 = 0x42E01F; 2375 const int profileLevelId2 = 0x64000C; 2376 const char* sprop1 = "foo bar"; 2377 const char* sprop2 = "baz"; 2378 2379 // Test that VideoConduit propagates H264 configuration data properly. 2380 // We do two tests: 2381 // - Test valid data in packetization mode 0 (SingleNALU) 2382 // - Test different valid data in packetization mode 1 (NonInterleaved) 2383 2384 { 2385 mControl.Update([&](auto& aControl) { 2386 aControl.mTransmitting = true; 2387 VideoCodecConfigH264 h264{}; 2388 h264.packetization_mode = 0; 2389 h264.profile_level_id = profileLevelId1; 2390 strncpy(h264.sprop_parameter_sets, sprop1, 2391 sizeof(h264.sprop_parameter_sets) - 1); 2392 auto codecConfig = VideoCodecConfig::CreateH264Config( 2393 97, VideoEncodingConstraints(), h264); 2394 codecConfig.mEncodings.emplace_back(); 2395 aControl.mVideoSendCodec = Some(codecConfig); 2396 aControl.mVideoSendRtpRtcpConfig = 2397 Some(RtpRtcpConfig(webrtc::RtcpMode::kCompound, true)); 2398 }); 2399 2400 ASSERT_TRUE(Call()->mVideoSendEncoderConfig); 2401 auto& params = Call()->mVideoSendEncoderConfig->video_format.parameters; 2402 EXPECT_EQ(params[webrtc::kH264FmtpPacketizationMode], "0"); 2403 EXPECT_EQ(params[webrtc::kH264FmtpProfileLevelId], "42e01f"); 2404 EXPECT_EQ(params[webrtc::kH264FmtpSpropParameterSets], sprop1); 2405 } 2406 2407 { 2408 mControl.Update([&](auto& aControl) { 2409 VideoCodecConfigH264 h264{}; 2410 h264.packetization_mode = 1; 2411 h264.profile_level_id = profileLevelId2; 2412 strncpy(h264.sprop_parameter_sets, sprop2, 2413 sizeof(h264.sprop_parameter_sets) - 1); 2414 auto codecConfig = VideoCodecConfig::CreateH264Config( 2415 126, VideoEncodingConstraints(), h264); 2416 codecConfig.mEncodings.emplace_back(); 2417 aControl.mVideoSendCodec = Some(codecConfig); 2418 }); 2419 2420 ASSERT_TRUE(Call()->mVideoSendEncoderConfig); 2421 auto& params = Call()->mVideoSendEncoderConfig->video_format.parameters; 2422 EXPECT_EQ(params[webrtc::kH264FmtpPacketizationMode], "1"); 2423 EXPECT_EQ(params[webrtc::kH264FmtpProfileLevelId], "64000c"); 2424 EXPECT_EQ(params[webrtc::kH264FmtpSpropParameterSets], sprop2); 2425 } 2426 } 2427 2428 TEST_F(VideoConduitTest, TestVideoConfigurationAV1) { 2429 // Test that VideoConduit propagates AV1 configuration data properly. 2430 { 2431 mControl.Update([&](auto& aControl) { 2432 aControl.mTransmitting = true; 2433 auto av1Config = JsepVideoCodecDescription::Av1Config(); 2434 2435 av1Config.mProfile = Some(2); 2436 av1Config.mLevelIdx = Some(4); 2437 av1Config.mTier = Some(1); 2438 auto codecConfig = VideoCodecConfig::CreateAv1Config( 2439 99, VideoEncodingConstraints(), av1Config); 2440 codecConfig.mEncodings.emplace_back(); 2441 aControl.mVideoSendCodec = Some(codecConfig); 2442 aControl.mVideoSendRtpRtcpConfig = 2443 Some(RtpRtcpConfig(webrtc::RtcpMode::kCompound, true)); 2444 }); 2445 2446 ASSERT_TRUE(Call()->mVideoSendEncoderConfig); 2447 auto& params = Call()->mVideoSendEncoderConfig->video_format.parameters; 2448 EXPECT_EQ(params[webrtc::kAv1FmtpProfile], "2"); 2449 EXPECT_EQ(params[webrtc::kAv1FmtpLevelIdx], "4"); 2450 EXPECT_EQ(params[webrtc::kAv1FmtpTier], "1"); 2451 } 2452 } 2453 2454 TEST_F(VideoConduitTest, TestDegradationPreferences) { 2455 // Verify default value returned is MAINTAIN_FRAMERATE. 2456 ASSERT_EQ(mVideoConduit->DegradationPreference(), 2457 webrtc::DegradationPreference::MAINTAIN_FRAMERATE); 2458 2459 // Verify that setting a degradation preference overrides default behavior. 2460 mControl.Update([&](auto& aControl) { 2461 aControl.mVideoDegradationPreference = 2462 webrtc::DegradationPreference::MAINTAIN_RESOLUTION; 2463 VideoCodecConfig codecConfig(120, "VP8", VideoEncodingConstraints()); 2464 codecConfig.mEncodings.emplace_back(); 2465 aControl.mVideoSendCodec = Some(codecConfig); 2466 aControl.mVideoSendRtpRtcpConfig = 2467 Some(RtpRtcpConfig(webrtc::RtcpMode::kCompound, true)); 2468 aControl.mReceiving = true; 2469 aControl.mTransmitting = true; 2470 }); 2471 ASSERT_EQ(mVideoConduit->DegradationPreference(), 2472 webrtc::DegradationPreference::MAINTAIN_RESOLUTION); 2473 ASSERT_EQ(Call()->mConfiguredDegradationPreference, 2474 webrtc::DegradationPreference::MAINTAIN_RESOLUTION); 2475 2476 mControl.Update([&](auto& aControl) { 2477 aControl.mVideoDegradationPreference = 2478 webrtc::DegradationPreference::BALANCED; 2479 }); 2480 ASSERT_EQ(mVideoConduit->DegradationPreference(), 2481 webrtc::DegradationPreference::BALANCED); 2482 ASSERT_EQ(Call()->mConfiguredDegradationPreference, 2483 webrtc::DegradationPreference::BALANCED); 2484 2485 // Verify removing degradation preference returns default. 2486 mControl.Update([&](auto& aControl) { 2487 aControl.mVideoDegradationPreference = 2488 webrtc::DegradationPreference::DISABLED; 2489 }); 2490 ASSERT_EQ(mVideoConduit->DegradationPreference(), 2491 webrtc::DegradationPreference::MAINTAIN_FRAMERATE); 2492 ASSERT_EQ(Call()->mConfiguredDegradationPreference, 2493 webrtc::DegradationPreference::MAINTAIN_FRAMERATE); 2494 2495 // Verify with no degradation preference set changing codec mode to screen 2496 // sharing changes degradation to MAINTAIN_RESOLUTION. 2497 mControl.Update([&](auto& aControl) { 2498 aControl.mVideoCodecMode = webrtc::VideoCodecMode::kScreensharing; 2499 }); 2500 ASSERT_EQ(Call()->mVideoSendEncoderConfig->content_type, 2501 VideoEncoderConfig::ContentType::kScreen); 2502 ASSERT_EQ(mVideoConduit->DegradationPreference(), 2503 webrtc::DegradationPreference::MAINTAIN_RESOLUTION); 2504 ASSERT_EQ(Call()->mConfiguredDegradationPreference, 2505 webrtc::DegradationPreference::MAINTAIN_RESOLUTION); 2506 2507 // Verify that setting a degradation preference overrides screen share 2508 // degradation value. 2509 mControl.Update([&](auto& aControl) { 2510 aControl.mVideoDegradationPreference = 2511 webrtc::DegradationPreference::MAINTAIN_FRAMERATE; 2512 }); 2513 ASSERT_EQ(mVideoConduit->DegradationPreference(), 2514 webrtc::DegradationPreference::MAINTAIN_FRAMERATE); 2515 ASSERT_EQ(Call()->mConfiguredDegradationPreference, 2516 webrtc::DegradationPreference::MAINTAIN_FRAMERATE); 2517 2518 mControl.Update([&](auto& aControl) { 2519 aControl.mVideoDegradationPreference = 2520 webrtc::DegradationPreference::BALANCED; 2521 }); 2522 ASSERT_EQ(mVideoConduit->DegradationPreference(), 2523 webrtc::DegradationPreference::BALANCED); 2524 ASSERT_EQ(Call()->mConfiguredDegradationPreference, 2525 webrtc::DegradationPreference::BALANCED); 2526 2527 // Verify removing degradation preference returns to screen sharing 2528 // degradation value. 2529 mControl.Update([&](auto& aControl) { 2530 aControl.mVideoDegradationPreference = 2531 webrtc::DegradationPreference::DISABLED; 2532 }); 2533 ASSERT_EQ(mVideoConduit->DegradationPreference(), 2534 webrtc::DegradationPreference::MAINTAIN_RESOLUTION); 2535 ASSERT_EQ(Call()->mConfiguredDegradationPreference, 2536 webrtc::DegradationPreference::MAINTAIN_RESOLUTION); 2537 2538 // Verify changing codec mode back to real time with no degradation 2539 // preference set returns degradation to MAINTAIN_FRAMERATE. 2540 mControl.Update([&](auto& aControl) { 2541 aControl.mVideoCodecMode = webrtc::VideoCodecMode::kRealtimeVideo; 2542 }); 2543 ASSERT_EQ(Call()->mVideoSendEncoderConfig->content_type, 2544 VideoEncoderConfig::ContentType::kRealtimeVideo); 2545 ASSERT_EQ(mVideoConduit->DegradationPreference(), 2546 webrtc::DegradationPreference::MAINTAIN_FRAMERATE); 2547 ASSERT_EQ(Call()->mConfiguredDegradationPreference, 2548 webrtc::DegradationPreference::MAINTAIN_FRAMERATE); 2549 2550 // Verify that if a degradation preference was set changing mode does not 2551 // override the set preference. 2552 mControl.Update([&](auto& aControl) { 2553 aControl.mVideoDegradationPreference = 2554 webrtc::DegradationPreference::BALANCED; 2555 }); 2556 ASSERT_EQ(mVideoConduit->DegradationPreference(), 2557 webrtc::DegradationPreference::BALANCED); 2558 ASSERT_EQ(Call()->mConfiguredDegradationPreference, 2559 webrtc::DegradationPreference::BALANCED); 2560 2561 mControl.Update([&](auto& aControl) { 2562 aControl.mVideoCodecMode = webrtc::VideoCodecMode::kScreensharing; 2563 }); 2564 ASSERT_EQ(Call()->mVideoSendEncoderConfig->content_type, 2565 VideoEncoderConfig::ContentType::kScreen); 2566 ASSERT_EQ(mVideoConduit->DegradationPreference(), 2567 webrtc::DegradationPreference::BALANCED); 2568 ASSERT_EQ(Call()->mConfiguredDegradationPreference, 2569 webrtc::DegradationPreference::BALANCED); 2570 2571 mControl.Update([&](auto& aControl) { 2572 aControl.mVideoCodecMode = webrtc::VideoCodecMode::kRealtimeVideo; 2573 }); 2574 ASSERT_EQ(Call()->mVideoSendEncoderConfig->content_type, 2575 VideoEncoderConfig::ContentType::kRealtimeVideo); 2576 ASSERT_EQ(mVideoConduit->DegradationPreference(), 2577 webrtc::DegradationPreference::BALANCED); 2578 ASSERT_EQ(Call()->mConfiguredDegradationPreference, 2579 webrtc::DegradationPreference::BALANCED); 2580 } 2581 2582 TEST_F(VideoConduitTest, TestRemoteRtxSsrc) { 2583 // Verify RTX is configured. 2584 mControl.Update([&](auto& aControl) { 2585 VideoCodecConfig codecConfig(120, "VP8", VideoEncodingConstraints()); 2586 codecConfig.mEncodings.emplace_back(); 2587 codecConfig.mRTXPayloadType = 121; 2588 aControl.mVideoRecvCodecs = {codecConfig}; 2589 aControl.mVideoRecvRtpRtcpConfig = 2590 Some(RtpRtcpConfig(webrtc::RtcpMode::kCompound, true)); 2591 aControl.mReceiving = true; 2592 aControl.mRemoteSsrc = 2; 2593 aControl.mRemoteVideoRtxSsrc = 43; 2594 }); 2595 2596 EXPECT_THAT(Call()->mVideoReceiveConfig->rtp.rtx_associated_payload_types, 2597 UnorderedElementsAre(Pair(121, 120))); 2598 EXPECT_EQ(Call()->mVideoReceiveConfig->rtp.remote_ssrc, 2U); 2599 EXPECT_EQ(Call()->mVideoReceiveConfig->rtp.rtx_ssrc, 43U); 2600 2601 // Bug 1956426 verify, if the recv codecs change but signaled SSRC has not, 2602 // that RTX is still configured. 2603 mControl.Update([&](auto& aControl) { 2604 VideoCodecConfig codecConfig(120, "VP8", VideoEncodingConstraints()); 2605 VideoCodecConfig codecConfig264(96, "H264", VideoEncodingConstraints()); 2606 codecConfig.mEncodings.emplace_back(); 2607 codecConfig.mRTXPayloadType = 121; 2608 codecConfig264.mRTXPayloadType = 97; 2609 aControl.mVideoRecvCodecs = {codecConfig, codecConfig264}; 2610 aControl.mVideoRecvRtpRtcpConfig = 2611 Some(RtpRtcpConfig(webrtc::RtcpMode::kCompound, true)); 2612 aControl.mReceiving = true; 2613 aControl.mRemoteSsrc = 2; 2614 aControl.mRemoteVideoRtxSsrc = 43; 2615 }); 2616 2617 EXPECT_THAT(Call()->mVideoReceiveConfig->rtp.rtx_associated_payload_types, 2618 UnorderedElementsAre(Pair(121, 120), Pair(97, 96))); 2619 EXPECT_EQ(Call()->mVideoReceiveConfig->rtp.remote_ssrc, 2U); 2620 EXPECT_EQ(Call()->mVideoReceiveConfig->rtp.rtx_ssrc, 43U); 2621 2622 // Verify, if there is no RTX PT, we will unset the SSRC. 2623 mControl.Update([&](auto& aControl) { 2624 VideoCodecConfig codecConfig(120, "VP8", VideoEncodingConstraints()); 2625 VideoCodecConfig codecConfig264(96, "H264", VideoEncodingConstraints()); 2626 codecConfig.mEncodings.emplace_back(); 2627 aControl.mVideoRecvCodecs = {codecConfig, codecConfig264}; 2628 aControl.mVideoRecvRtpRtcpConfig = 2629 Some(RtpRtcpConfig(webrtc::RtcpMode::kCompound, true)); 2630 aControl.mReceiving = true; 2631 aControl.mRemoteSsrc = 2; 2632 aControl.mRemoteVideoRtxSsrc = 43; 2633 }); 2634 2635 EXPECT_EQ( 2636 Call()->mVideoReceiveConfig->rtp.rtx_associated_payload_types.size(), 0U); 2637 EXPECT_EQ(Call()->mVideoReceiveConfig->rtp.remote_ssrc, 2U); 2638 EXPECT_EQ(Call()->mVideoReceiveConfig->rtp.rtx_ssrc, 0U); 2639 } 2640 2641 } // End namespace test.