From c596dd5eb660b3a3263d9fafb0d21c11cce08d96 Mon Sep 17 00:00:00 2001 From: Qiu Jianlin Date: Mon, 2 Dec 2024 13:08:53 +0800 Subject: [PATCH] Fix setCodecPreference issue with asymmetrical send/recv level MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Henrik Boström Commit-Queue: Sergey Silkin Cr-Commit-Position: refs/heads/main@{#43477} --- pc/media_session.cc | 13 ++++----- pc/media_session_unittest.cc | 55 ++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 8 deletions(-) diff --git a/pc/media_session.cc b/pc/media_session.cc index 3e0d762d10..9cb82347b5 100644 --- a/pc/media_session.cc +++ b/pc/media_session.cc @@ -736,14 +736,11 @@ std::vector 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()) { diff --git a/pc/media_session_unittest.cc b/pc/media_session_unittest.cc index 8b35c41299..fa71feec0c 100644 --- a/pc/media_session_unittest.cc +++ b/pc/media_session_unittest.cc @@ -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 offerer_send_codecs = + MAKE_VECTOR(kVideoCodecsH265Level4); + const std::vector offerer_recv_codecs = + MAKE_VECTOR(kVideoCodecsH265Level6); + const std::vector offerer_sendrecv_codecs = + MAKE_VECTOR(kVideoCodecsH265Level4); + const std::vector answerer_send_codecs = + MAKE_VECTOR(kVideoCodecsH265Level6); + const std::vector 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 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 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 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