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