diff --git a/talk/media/webrtc/webrtcvideoengine2.cc b/talk/media/webrtc/webrtcvideoengine2.cc index ba96504a77..e7701a1655 100644 --- a/talk/media/webrtc/webrtcvideoengine2.cc +++ b/talk/media/webrtc/webrtcvideoengine2.cc @@ -303,6 +303,12 @@ static void MergeFecConfig(const webrtc::FecConfig& other, output->red_rtx_payload_type = other.red_rtx_payload_type; } } + +// Returns true if the given codec is disallowed from doing simulcast. +bool IsCodecBlacklistedForSimulcast(const std::string& codec_name) { + return CodecNamesEq(codec_name, kH264CodecName); +} + } // namespace // Constants defined in talk/media/webrtc/constants.h @@ -2095,9 +2101,17 @@ WebRtcVideoChannel2::WebRtcVideoSendStream::CreateVideoEncoderConfig( clamped_codec.width = width; clamped_codec.height = height; - encoder_config.streams = CreateVideoStreams( - clamped_codec, parameters_.options, parameters_.max_bitrate_bps, - dimensions.is_screencast ? 1 : parameters_.config.rtp.ssrcs.size()); + // By default, the stream count for the codec configuration should match the + // number of negotiated ssrcs. But if the codec is blacklisted for simulcast + // or a screencast, only configure a single stream. + size_t stream_count = parameters_.config.rtp.ssrcs.size(); + if (IsCodecBlacklistedForSimulcast(codec.name) || dimensions.is_screencast) { + stream_count = 1; + } + + encoder_config.streams = + CreateVideoStreams(clamped_codec, parameters_.options, + parameters_.max_bitrate_bps, stream_count); // Conference mode screencast uses 2 temporal layers split at 100kbit. if (parameters_.options.conference_mode.GetWithDefaultIfUnset(false) && diff --git a/talk/media/webrtc/webrtcvideoengine2_unittest.cc b/talk/media/webrtc/webrtcvideoengine2_unittest.cc index 2f873796fe..fd87703eab 100644 --- a/talk/media/webrtc/webrtcvideoengine2_unittest.cc +++ b/talk/media/webrtc/webrtcvideoengine2_unittest.cc @@ -644,6 +644,29 @@ TEST_F(WebRtcVideoEngine2Test, ASSERT_EQ(0u, encoder_factory.encoders().size()); } +TEST_F(WebRtcVideoEngine2Test, SimulcastDisabledForH264) { + cricket::FakeWebRtcVideoEncoderFactory encoder_factory; + encoder_factory.AddSupportedVideoCodecType(webrtc::kVideoCodecH264, "H264"); + std::vector codecs; + codecs.push_back(kH264Codec); + + rtc::scoped_ptr channel( + SetUpForExternalEncoderFactory(&encoder_factory, codecs)); + + const std::vector ssrcs = MAKE_VECTOR(kSsrcs3); + EXPECT_TRUE( + channel->AddSendStream(cricket::CreateSimStreamParams("cname", ssrcs))); + // Set the stream to 720p. This should trigger a "real" encoder + // initialization. + cricket::VideoFormat format( + 1280, 720, cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420); + EXPECT_TRUE(channel->SetSendStreamFormat(ssrcs[0], format)); + ASSERT_EQ(1u, encoder_factory.encoders().size()); + FakeWebRtcVideoEncoder* encoder = encoder_factory.encoders()[0]; + EXPECT_EQ(webrtc::kVideoCodecH264, encoder->GetCodecSettings().codecType); + EXPECT_EQ(1u, encoder->GetCodecSettings().numberOfSimulcastStreams); +} + // Test external codec with be added to the end of the supported codec list. TEST_F(WebRtcVideoEngine2Test, ReportSupportedExternalCodecs) { cricket::FakeWebRtcVideoEncoderFactory encoder_factory;