setParameters should not throw when only level mismatch.
According to latest requirement, when the level reported by RtpSender.getCapabilities() for H.265 is different from that was negotiated, we should not throw when setParameters() is called with level-id set to that reported by RtpSender.getCapabilities(). Underlingly negotiated codec level should remain unchanged. Bug: chromium:41480904 Change-Id: I28bbdb5f0a0ab0d98315f56c80004601afc91a63 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/368781 Reviewed-by: Harald Alvestrand <hta@webrtc.org> Reviewed-by: Henrik Boström <hbos@webrtc.org> Commit-Queue: Henrik Boström <hbos@webrtc.org> Cr-Commit-Position: refs/heads/main@{#43434}
This commit is contained in:
parent
00e86b3cb0
commit
5ad1daeed9
@ -377,4 +377,31 @@ bool IsSameRtpCodec(const Codec& codec, const RtpCodec& rtp_codec) {
|
||||
InsertDefaultParams(rtp_codec2.name, rtp_codec2.parameters);
|
||||
}
|
||||
|
||||
bool IsSameRtpCodecIgnoringLevel(const Codec& codec,
|
||||
const RtpCodec& rtp_codec) {
|
||||
RtpCodecParameters rtp_codec2 = codec.ToCodecParameters();
|
||||
|
||||
if (!absl::EqualsIgnoreCase(rtp_codec.name, rtp_codec2.name) ||
|
||||
rtp_codec.kind != rtp_codec2.kind ||
|
||||
rtp_codec.num_channels != rtp_codec2.num_channels ||
|
||||
rtp_codec.clock_rate != rtp_codec2.clock_rate) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CodecParameterMap params1 =
|
||||
InsertDefaultParams(rtp_codec.name, rtp_codec.parameters);
|
||||
CodecParameterMap params2 =
|
||||
InsertDefaultParams(rtp_codec2.name, rtp_codec2.parameters);
|
||||
|
||||
// Currently we only ignore H.265 level-id parameter.
|
||||
#ifdef RTC_ENABLE_H265
|
||||
if (absl::EqualsIgnoreCase(rtp_codec.name, cricket::kH265CodecName)) {
|
||||
params1.erase(cricket::kH265FmtpLevelId);
|
||||
params2.erase(cricket::kH265FmtpLevelId);
|
||||
}
|
||||
#endif
|
||||
|
||||
return params1 == params2;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
@ -43,6 +43,9 @@ std::optional<cricket::Codec> FindMatchingCodec(
|
||||
// Unspecified parameters are treated as default.
|
||||
bool IsSameRtpCodec(const cricket::Codec& codec, const RtpCodec& rtp_codec);
|
||||
|
||||
// Similar to `IsSameRtpCodec` but ignoring the level related parameter.
|
||||
bool IsSameRtpCodecIgnoringLevel(const cricket::Codec& codec,
|
||||
const RtpCodec& rtp_codec);
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // MEDIA_BASE_CODEC_COMPARATORS_H_
|
||||
|
||||
@ -1435,10 +1435,12 @@ webrtc::RTCError WebRtcVideoSendChannel::SetRtpSendParameters(
|
||||
!IsSameRtpCodec(send_codec_->codec, *parameters.encodings[0].codec)) {
|
||||
RTC_LOG(LS_VERBOSE) << "Trying to change codec to "
|
||||
<< parameters.encodings[0].codec->name;
|
||||
// Ignore level when matching negotiated codecs against the requested
|
||||
// codec.
|
||||
auto matched_codec =
|
||||
absl::c_find_if(negotiated_codecs_, [&](auto negotiated_codec) {
|
||||
return IsSameRtpCodec(negotiated_codec.codec,
|
||||
*parameters.encodings[0].codec);
|
||||
return IsSameRtpCodecIgnoringLevel(negotiated_codec.codec,
|
||||
*parameters.encodings[0].codec);
|
||||
});
|
||||
if (matched_codec == negotiated_codecs_.end()) {
|
||||
return webrtc::InvokeSetParametersCallback(
|
||||
|
||||
@ -8554,6 +8554,215 @@ TEST_F(
|
||||
|
||||
EXPECT_TRUE(send_channel_->SetVideoSend(last_ssrc_, nullptr, nullptr));
|
||||
}
|
||||
|
||||
TEST_F(WebRtcVideoChannelTest,
|
||||
SetRtpParametersForH265ShouldSucceedIgnoreLowerLevelId) {
|
||||
encoder_factory_->AddSupportedVideoCodec(
|
||||
webrtc::SdpVideoFormat("H265",
|
||||
{{"profile-id", "1"},
|
||||
{"tier-flag", "0"},
|
||||
{"level-id", "156"},
|
||||
{"tx-mode", "SRST"}},
|
||||
{ScalabilityMode::kL1T1}));
|
||||
cricket::VideoSenderParameters send_parameters;
|
||||
send_parameters.codecs.push_back(GetEngineCodec("H265"));
|
||||
for (auto& codec : send_parameters.codecs) {
|
||||
if (absl::EqualsIgnoreCase(codec.name, "H265")) {
|
||||
codec.params["level-id"] = "156";
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_TRUE(send_channel_->SetSenderParameters(send_parameters));
|
||||
FakeVideoSendStream* stream = AddSendStream();
|
||||
ASSERT_TRUE(stream);
|
||||
|
||||
webrtc::test::FrameForwarder frame_forwarder;
|
||||
VideoOptions options;
|
||||
EXPECT_TRUE(
|
||||
send_channel_->SetVideoSend(last_ssrc_, &options, &frame_forwarder));
|
||||
send_channel_->SetSend(true);
|
||||
frame_forwarder.IncomingCapturedFrame(frame_source_.GetFrame());
|
||||
|
||||
webrtc::RtpParameters parameters =
|
||||
send_channel_->GetRtpSendParameters(last_ssrc_);
|
||||
|
||||
webrtc::RtpCodecParameters matched_codec;
|
||||
for (const auto& codec : parameters.codecs) {
|
||||
if (absl::EqualsIgnoreCase(codec.name, "H265")) {
|
||||
EXPECT_EQ(codec.parameters.at("level-id"), "156");
|
||||
matched_codec = codec;
|
||||
}
|
||||
}
|
||||
|
||||
FakeVideoSendStream* send_stream = fake_call_->GetVideoSendStreams().front();
|
||||
ASSERT_TRUE(send_stream);
|
||||
webrtc::VideoEncoderConfig encoder_config =
|
||||
send_stream->GetEncoderConfig().Copy();
|
||||
EXPECT_EQ(encoder_config.video_format.parameters.at("level-id"), "156");
|
||||
|
||||
// Set the level-id parameter to lower than the negotiated codec level-id.
|
||||
EXPECT_EQ(1u, parameters.encodings.size());
|
||||
matched_codec.parameters["level-id"] = "120";
|
||||
parameters.encodings[0].codec = matched_codec;
|
||||
|
||||
EXPECT_TRUE(send_channel_->SetRtpSendParameters(last_ssrc_, parameters).ok());
|
||||
webrtc::RtpParameters parameters2 =
|
||||
send_channel_->GetRtpSendParameters(last_ssrc_);
|
||||
|
||||
for (const auto& codec : parameters2.codecs) {
|
||||
if (absl::EqualsIgnoreCase(codec.name, "H265")) {
|
||||
EXPECT_EQ(codec.parameters.at("level-id"), "156");
|
||||
}
|
||||
}
|
||||
|
||||
FakeVideoSendStream* send_stream2 = fake_call_->GetVideoSendStreams().front();
|
||||
ASSERT_TRUE(send_stream2);
|
||||
webrtc::VideoEncoderConfig encoder_config2 =
|
||||
send_stream2->GetEncoderConfig().Copy();
|
||||
EXPECT_EQ(encoder_config2.video_format.parameters.at("level-id"), "156");
|
||||
|
||||
EXPECT_TRUE(send_channel_->SetVideoSend(last_ssrc_, nullptr, nullptr));
|
||||
}
|
||||
|
||||
TEST_F(WebRtcVideoChannelTest,
|
||||
SetRtpParametersForH265WithSameLevelIdShouldSucceed) {
|
||||
encoder_factory_->AddSupportedVideoCodec(
|
||||
webrtc::SdpVideoFormat("H265",
|
||||
{{"profile-id", "1"},
|
||||
{"tier-flag", "0"},
|
||||
{"level-id", "156"},
|
||||
{"tx-mode", "SRST"}},
|
||||
{ScalabilityMode::kL1T1}));
|
||||
cricket::VideoSenderParameters send_parameters;
|
||||
send_parameters.codecs.push_back(GetEngineCodec("H265"));
|
||||
for (auto& codec : send_parameters.codecs) {
|
||||
if (absl::EqualsIgnoreCase(codec.name, "H265")) {
|
||||
codec.params["level-id"] = "156";
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_TRUE(send_channel_->SetSenderParameters(send_parameters));
|
||||
FakeVideoSendStream* stream = AddSendStream();
|
||||
ASSERT_TRUE(stream);
|
||||
|
||||
webrtc::test::FrameForwarder frame_forwarder;
|
||||
VideoOptions options;
|
||||
EXPECT_TRUE(
|
||||
send_channel_->SetVideoSend(last_ssrc_, &options, &frame_forwarder));
|
||||
send_channel_->SetSend(true);
|
||||
frame_forwarder.IncomingCapturedFrame(frame_source_.GetFrame());
|
||||
|
||||
webrtc::RtpParameters parameters =
|
||||
send_channel_->GetRtpSendParameters(last_ssrc_);
|
||||
|
||||
webrtc::RtpCodecParameters matched_codec;
|
||||
for (const auto& codec : parameters.codecs) {
|
||||
if (absl::EqualsIgnoreCase(codec.name, "H265")) {
|
||||
EXPECT_EQ(codec.parameters.at("level-id"), "156");
|
||||
matched_codec = codec;
|
||||
}
|
||||
}
|
||||
|
||||
FakeVideoSendStream* send_stream = fake_call_->GetVideoSendStreams().front();
|
||||
ASSERT_TRUE(send_stream);
|
||||
webrtc::VideoEncoderConfig encoder_config =
|
||||
send_stream->GetEncoderConfig().Copy();
|
||||
EXPECT_EQ(encoder_config.video_format.parameters.at("level-id"), "156");
|
||||
|
||||
// Set the level-id parameter to the same as the negotiated codec level-id.
|
||||
EXPECT_EQ(1u, parameters.encodings.size());
|
||||
matched_codec.parameters["level-id"] = "156";
|
||||
parameters.encodings[0].codec = matched_codec;
|
||||
|
||||
EXPECT_TRUE(send_channel_->SetRtpSendParameters(last_ssrc_, parameters).ok());
|
||||
|
||||
webrtc::RtpParameters parameters2 =
|
||||
send_channel_->GetRtpSendParameters(last_ssrc_);
|
||||
|
||||
for (const auto& codec : parameters2.codecs) {
|
||||
if (absl::EqualsIgnoreCase(codec.name, "H265")) {
|
||||
EXPECT_EQ(codec.parameters.at("level-id"), "156");
|
||||
matched_codec = codec;
|
||||
}
|
||||
}
|
||||
|
||||
FakeVideoSendStream* send_stream2 = fake_call_->GetVideoSendStreams().front();
|
||||
ASSERT_TRUE(send_stream2);
|
||||
webrtc::VideoEncoderConfig encoder_config2 =
|
||||
send_stream2->GetEncoderConfig().Copy();
|
||||
EXPECT_EQ(encoder_config2.video_format.parameters.at("level-id"), "156");
|
||||
|
||||
EXPECT_TRUE(send_channel_->SetVideoSend(last_ssrc_, nullptr, nullptr));
|
||||
}
|
||||
|
||||
TEST_F(WebRtcVideoChannelTest,
|
||||
SetRtpParametersForH265ShouldSucceedIgnoreHigherLevelId) {
|
||||
encoder_factory_->AddSupportedVideoCodec(
|
||||
webrtc::SdpVideoFormat("H265",
|
||||
{{"profile-id", "1"},
|
||||
{"tier-flag", "0"},
|
||||
{"level-id", "156"},
|
||||
{"tx-mode", "SRST"}},
|
||||
{ScalabilityMode::kL1T1}));
|
||||
cricket::VideoSenderParameters send_parameters;
|
||||
send_parameters.codecs.push_back(GetEngineCodec("H265"));
|
||||
for (auto& codec : send_parameters.codecs) {
|
||||
if (absl::EqualsIgnoreCase(codec.name, "H265")) {
|
||||
codec.params["level-id"] = "156";
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_TRUE(send_channel_->SetSenderParameters(send_parameters));
|
||||
FakeVideoSendStream* stream = AddSendStream();
|
||||
ASSERT_TRUE(stream);
|
||||
|
||||
webrtc::test::FrameForwarder frame_forwarder;
|
||||
VideoOptions options;
|
||||
EXPECT_TRUE(
|
||||
send_channel_->SetVideoSend(last_ssrc_, &options, &frame_forwarder));
|
||||
send_channel_->SetSend(true);
|
||||
frame_forwarder.IncomingCapturedFrame(frame_source_.GetFrame());
|
||||
|
||||
webrtc::RtpParameters parameters =
|
||||
send_channel_->GetRtpSendParameters(last_ssrc_);
|
||||
|
||||
webrtc::RtpCodecParameters matched_codec;
|
||||
for (const auto& codec : parameters.codecs) {
|
||||
if (absl::EqualsIgnoreCase(codec.name, "H265")) {
|
||||
EXPECT_EQ(codec.parameters.at("level-id"), "156");
|
||||
matched_codec = codec;
|
||||
}
|
||||
}
|
||||
|
||||
FakeVideoSendStream* send_stream = fake_call_->GetVideoSendStreams().front();
|
||||
ASSERT_TRUE(send_stream);
|
||||
webrtc::VideoEncoderConfig encoder_config =
|
||||
send_stream->GetEncoderConfig().Copy();
|
||||
EXPECT_EQ(encoder_config.video_format.parameters.at("level-id"), "156");
|
||||
|
||||
// Set the level-id parameter to higher than the negotiated codec level-id.
|
||||
EXPECT_EQ(1u, parameters.encodings.size());
|
||||
matched_codec.parameters["level-id"] = "180";
|
||||
parameters.encodings[0].codec = matched_codec;
|
||||
|
||||
EXPECT_TRUE(send_channel_->SetRtpSendParameters(last_ssrc_, parameters).ok());
|
||||
|
||||
webrtc::RtpParameters parameters2 =
|
||||
send_channel_->GetRtpSendParameters(last_ssrc_);
|
||||
|
||||
for (const auto& codec : parameters2.codecs) {
|
||||
if (absl::EqualsIgnoreCase(codec.name, "H265")) {
|
||||
EXPECT_EQ(codec.parameters.at("level-id"), "156");
|
||||
}
|
||||
}
|
||||
FakeVideoSendStream* send_stream2 = fake_call_->GetVideoSendStreams().front();
|
||||
ASSERT_TRUE(send_stream2);
|
||||
webrtc::VideoEncoderConfig encoder_config2 =
|
||||
send_stream2->GetEncoderConfig().Copy();
|
||||
EXPECT_EQ(encoder_config2.video_format.parameters.at("level-id"), "156");
|
||||
|
||||
EXPECT_TRUE(send_channel_->SetVideoSend(last_ssrc_, nullptr, nullptr));
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST_F(WebRtcVideoChannelTest,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user