tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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.