Fix setCodecPreference issue with asymmetrical send/recv level

For an offer in sendrecv direction, if for example it can send H.265
level 5.2 while receiving 6.0, setCodecPreferences on offerer's transceiver will currently remove H.265 from the offer SDP, since currently we do a precise level match on send_recv_codecs with the codecs from setCodecPreferences.
Update the matching logic to ignore the level when matching.

Bug: chromium:41480904
Change-Id: Id0f89cbf117ce62249a99257dcce18b35f407cb9
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/369960
Reviewed-by: Sergey Silkin <ssilkin@webrtc.org>
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Commit-Queue: Sergey Silkin <ssilkin@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#43477}
This commit is contained in:
Qiu Jianlin 2024-12-02 13:08:53 +08:00 committed by WebRTC LUCI CQ
parent 230e5a211c
commit c596dd5eb6
2 changed files with 60 additions and 8 deletions

View File

@ -736,14 +736,11 @@ std::vector<Codec> MatchCodecPreference(
for (const auto& codec_preference : codec_preferences) {
auto found_codec = absl::c_find_if(
supported_codecs, [&codec_preference](const Codec& codec) {
webrtc::RtpCodecParameters codec_parameters =
codec.ToCodecParameters();
return codec_parameters.name == codec_preference.name &&
codec_parameters.kind == codec_preference.kind &&
codec_parameters.num_channels ==
codec_preference.num_channels &&
codec_parameters.clock_rate == codec_preference.clock_rate &&
codec_parameters.parameters == codec_preference.parameters;
// We should not filter out the codec in |codec_preferences| if it
// has a higher level than the codec in |supported_codecs|, as the
// codec in |supported_codecs| may be only with lower level in
// |send_codecs_| and |recv_codecs_| for the same codec.
return IsSameRtpCodecIgnoringLevel(codec, codec_preference);
});
if (found_codec != supported_codecs.end()) {

View File

@ -5923,6 +5923,61 @@ TEST_F(VideoCodecsOfferH265LevelIdTest,
EXPECT_TRUE(CodecsMatch(MAKE_VECTOR(kVideoCodecsH265Level4), acd->codecs()));
CheckH265Level(acd->codecs(), kVideoCodecsH265Level4LevelId);
}
TEST_F(VideoCodecsOfferH265LevelIdTest,
SendOnlyOffererEncode40Decode60AnswererEncode60Decode52WithPreference) {
const std::vector<Codec> offerer_send_codecs =
MAKE_VECTOR(kVideoCodecsH265Level4);
const std::vector<Codec> offerer_recv_codecs =
MAKE_VECTOR(kVideoCodecsH265Level6);
const std::vector<Codec> offerer_sendrecv_codecs =
MAKE_VECTOR(kVideoCodecsH265Level4);
const std::vector<Codec> answerer_send_codecs =
MAKE_VECTOR(kVideoCodecsH265Level6);
const std::vector<Codec> answerer_recv_codecs =
MAKE_VECTOR(kVideoCodecsH265Level52);
sf_offerer_.set_video_codecs(offerer_send_codecs, offerer_recv_codecs);
sf_answerer_.set_video_codecs(answerer_send_codecs, answerer_recv_codecs);
EXPECT_EQ(offerer_sendrecv_codecs, sf_offerer_.video_sendrecv_codecs());
MediaSessionOptions opts;
AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video",
RtpTransceiverDirection::kSendRecv, kActive,
&opts);
AttachSenderToMediaDescriptionOptions("video", MEDIA_TYPE_VIDEO, kVideoTrack1,
{kMediaStream1}, 1, &opts);
std::vector<webrtc::RtpCodecCapability> preferences;
for (const auto& codec : sf_offerer_.video_recv_codecs()) {
preferences.push_back(webrtc::ToRtpCodecCapability(codec));
}
opts.media_description_options[0].codec_preferences = preferences;
std::unique_ptr<SessionDescription> offer =
sf_offerer_.CreateOfferOrError(opts, nullptr).MoveValue();
ASSERT_TRUE(offer.get());
const ContentInfo* oc = offer->GetContentByName("video");
ASSERT_TRUE(oc);
const MediaContentDescription* ocd = oc->media_description();
EXPECT_TRUE(CodecsMatch(MAKE_VECTOR(kVideoCodecsH265Level4), ocd->codecs()));
CheckH265Level(ocd->codecs(), kVideoCodecsH265Level4LevelId);
MediaSessionOptions answer_opts;
AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video",
RtpTransceiverDirection::kRecvOnly, kActive,
&answer_opts);
std::unique_ptr<SessionDescription> answer =
sf_answerer_.CreateAnswerOrError(offer.get(), answer_opts, nullptr)
.MoveValue();
ASSERT_TRUE(answer.get());
const ContentInfo* ac = answer->GetContentByName("video");
ASSERT_TRUE(ac);
const MediaContentDescription* acd = ac->media_description();
EXPECT_TRUE(CodecsMatch(MAKE_VECTOR(kVideoCodecsH265Level4), acd->codecs()));
CheckH265Level(acd->codecs(), kVideoCodecsH265Level4LevelId);
}
#endif
} // namespace