diff --git a/api/video_codecs/sdp_video_format.cc b/api/video_codecs/sdp_video_format.cc index 5abde8fbb0..08dfed4ce5 100644 --- a/api/video_codecs/sdp_video_format.cc +++ b/api/video_codecs/sdp_video_format.cc @@ -29,6 +29,8 @@ namespace webrtc { namespace { +// TODO(bugs.webrtc.org/15847): remove code duplication of IsSameCodecSpecific +// in media/base/codec.cc std::string GetFmtpParameterOrDefault(const CodecParameterMap& params, const std::string& name, const std::string& default_value) { @@ -74,29 +76,45 @@ bool AV1IsSameLevelIdx(const CodecParameterMap& left, return AV1GetLevelIdxOrDefault(left) == AV1GetLevelIdxOrDefault(right); } +#ifdef RTC_ENABLE_H265 +std::string GetH265TxModeOrDefault(const CodecParameterMap& params) { + // If TxMode is not present, a value of "SRST" must be inferred. + // https://tools.ietf.org/html/rfc7798@section-7.1 + return GetFmtpParameterOrDefault(params, cricket::kH265FmtpTxMode, "SRST"); +} + +bool IsSameH265TxMode(const CodecParameterMap& left, + const CodecParameterMap& right) { + return absl::EqualsIgnoreCase(GetH265TxModeOrDefault(left), + GetH265TxModeOrDefault(right)); +} +#endif + // Some (video) codecs are actually families of codecs and rely on parameters // to distinguish different incompatible family members. -bool IsSameCodecSpecific(const SdpVideoFormat& format1, - const SdpVideoFormat& format2) { +bool IsSameCodecSpecific(const std::string& name1, + const CodecParameterMap& params1, + const std::string& name2, + const CodecParameterMap& params2) { // The assumption when calling this function is that the two formats have the // same name. - RTC_DCHECK(absl::EqualsIgnoreCase(format1.name, format2.name)); + RTC_DCHECK(absl::EqualsIgnoreCase(name1, name2)); - VideoCodecType codec_type = PayloadStringToCodecType(format1.name); + VideoCodecType codec_type = PayloadStringToCodecType(name1); switch (codec_type) { case kVideoCodecH264: - return H264IsSameProfile(format1.parameters, format2.parameters) && - H264IsSamePacketizationMode(format1.parameters, - format2.parameters); + return H264IsSameProfile(params1, params2) && + H264IsSamePacketizationMode(params1, params2); case kVideoCodecVP9: - return VP9IsSameProfile(format1.parameters, format2.parameters); + return VP9IsSameProfile(params1, params2); case kVideoCodecAV1: - return AV1IsSameProfile(format1.parameters, format2.parameters) && - AV1IsSameTier(format1.parameters, format2.parameters) && - AV1IsSameLevelIdx(format1.parameters, format2.parameters); + return AV1IsSameProfile(params1, params2) && + AV1IsSameTier(params1, params2) && + AV1IsSameLevelIdx(params1, params2); #ifdef RTC_ENABLE_H265 case kVideoCodecH265: - return H265IsSameProfileTierLevel(format1.parameters, format2.parameters); + return H265IsSameProfileTierLevel(params1, params2) && + IsSameH265TxMode(params1, params2); #endif default: return true; @@ -156,7 +174,7 @@ bool SdpVideoFormat::IsSameCodec(const SdpVideoFormat& other) const { // Two codecs are considered the same if the name matches (case insensitive) // and certain codec-specific parameters match. return absl::EqualsIgnoreCase(name, other.name) && - IsSameCodecSpecific(*this, other); + IsSameCodecSpecific(name, parameters, other.name, other.parameters); } bool SdpVideoFormat::IsCodecInList( diff --git a/media/base/codec.cc b/media/base/codec.cc index 8abc865976..2e7cc6ac8c 100644 --- a/media/base/codec.cc +++ b/media/base/codec.cc @@ -28,32 +28,59 @@ namespace cricket { namespace { -std::string GetH264PacketizationModeOrDefault( - const webrtc::CodecParameterMap& params) { - auto it = params.find(kH264FmtpPacketizationMode); +// TODO(bugs.webrtc.org/15847): remove code duplication of IsSameCodecSpecific +// in api/video_codecs/sdp_video_format.cc +std::string GetFmtpParameterOrDefault(const webrtc::CodecParameterMap& params, + const std::string& name, + const std::string& default_value) { + const auto it = params.find(name); if (it != params.end()) { return it->second; } - // If packetization-mode is not present, default to "0". - // https://tools.ietf.org/html/rfc6184#section-6.2 - return "0"; + return default_value; } -bool IsSameH264PacketizationMode(const webrtc::CodecParameterMap& left, +std::string H264GetPacketizationModeOrDefault( + const webrtc::CodecParameterMap& params) { + // If packetization-mode is not present, default to "0". + // https://tools.ietf.org/html/rfc6184#section-6.2 + return GetFmtpParameterOrDefault(params, cricket::kH264FmtpPacketizationMode, + "0"); +} + +bool H264IsSamePacketizationMode(const webrtc::CodecParameterMap& left, const webrtc::CodecParameterMap& right) { - return GetH264PacketizationModeOrDefault(left) == - GetH264PacketizationModeOrDefault(right); + return H264GetPacketizationModeOrDefault(left) == + H264GetPacketizationModeOrDefault(right); +} + +std::string AV1GetTierOrDefault(const webrtc::CodecParameterMap& params) { + // If the parameter is not present, the tier MUST be inferred to be 0. + // https://aomediacodec.github.io/av1-rtp-spec/#72-sdp-parameters + return GetFmtpParameterOrDefault(params, cricket::kAv1FmtpTier, "0"); +} + +bool AV1IsSameTier(const webrtc::CodecParameterMap& left, + const webrtc::CodecParameterMap& right) { + return AV1GetTierOrDefault(left) == AV1GetTierOrDefault(right); +} + +std::string AV1GetLevelIdxOrDefault(const webrtc::CodecParameterMap& params) { + // If the parameter is not present, it MUST be inferred to be 5 (level 3.1). + // https://aomediacodec.github.io/av1-rtp-spec/#72-sdp-parameters + return GetFmtpParameterOrDefault(params, cricket::kAv1FmtpLevelIdx, "5"); +} + +bool AV1IsSameLevelIdx(const webrtc::CodecParameterMap& left, + const webrtc::CodecParameterMap& right) { + return AV1GetLevelIdxOrDefault(left) == AV1GetLevelIdxOrDefault(right); } #ifdef RTC_ENABLE_H265 std::string GetH265TxModeOrDefault(const webrtc::CodecParameterMap& params) { - auto it = params.find(kH265FmtpTxMode); - if (it != params.end()) { - return it->second; - } // If TxMode is not present, a value of "SRST" must be inferred. // https://tools.ietf.org/html/rfc7798@section-7.1 - return "SRST"; + return GetFmtpParameterOrDefault(params, kH265FmtpTxMode, "SRST"); } bool IsSameH265TxMode(const webrtc::CodecParameterMap& left, @@ -76,11 +103,13 @@ bool IsSameCodecSpecific(const std::string& name1, }; if (either_name_matches(kH264CodecName)) return webrtc::H264IsSameProfile(params1, params2) && - IsSameH264PacketizationMode(params1, params2); + H264IsSamePacketizationMode(params1, params2); if (either_name_matches(kVp9CodecName)) return webrtc::VP9IsSameProfile(params1, params2); if (either_name_matches(kAv1CodecName)) - return webrtc::AV1IsSameProfile(params1, params2); + return webrtc::AV1IsSameProfile(params1, params2) && + AV1IsSameTier(params1, params2) && + AV1IsSameLevelIdx(params1, params2); #ifdef RTC_ENABLE_H265 if (either_name_matches(kH265CodecName)) { return webrtc::H265IsSameProfileTierLevel(params1, params2) &&