Compare only profile & tier when matching HEVC codec.
Level asymmetry is implicitly enabled for HEVC. When comparing two codec params to see if they match, we only compare profile & tier, similar as H.264. Bug: chromium:41480904 Change-Id: I9e9debdf1b34f33986da9344b9fee14071b1ed60 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/363205 Reviewed-by: Harald Alvestrand <hta@webrtc.org> Reviewed-by: Sergey Silkin <ssilkin@webrtc.org> Commit-Queue: Jianlin Qiu <jianlin.qiu@intel.com> Cr-Commit-Position: refs/heads/main@{#43069}
This commit is contained in:
parent
93ec3434a5
commit
6f90609fca
@ -285,6 +285,24 @@ bool H265IsSameProfileTierLevel(const CodecParameterMap& params1,
|
||||
ptl1->tier == ptl2->tier && ptl1->level == ptl2->level;
|
||||
}
|
||||
|
||||
bool H265IsSameProfile(const CodecParameterMap& params1,
|
||||
const CodecParameterMap& params2) {
|
||||
const std::optional<H265ProfileTierLevel> ptl1 =
|
||||
ParseSdpForH265ProfileTierLevel(params1);
|
||||
const std::optional<H265ProfileTierLevel> ptl2 =
|
||||
ParseSdpForH265ProfileTierLevel(params2);
|
||||
return ptl1 && ptl2 && ptl1->profile == ptl2->profile;
|
||||
}
|
||||
|
||||
bool H265IsSameTier(const CodecParameterMap& params1,
|
||||
const CodecParameterMap& params2) {
|
||||
const std::optional<H265ProfileTierLevel> ptl1 =
|
||||
ParseSdpForH265ProfileTierLevel(params1);
|
||||
const std::optional<H265ProfileTierLevel> ptl2 =
|
||||
ParseSdpForH265ProfileTierLevel(params2);
|
||||
return ptl1 && ptl2 && ptl1->tier == ptl2->tier;
|
||||
}
|
||||
|
||||
std::optional<H265Level> GetSupportedH265Level(const Resolution& resolution,
|
||||
float max_fps) {
|
||||
int aligned_width =
|
||||
|
||||
@ -107,11 +107,21 @@ RTC_EXPORT std::optional<H265Level> GetSupportedH265Level(
|
||||
RTC_EXPORT std::optional<H265ProfileTierLevel> ParseSdpForH265ProfileTierLevel(
|
||||
const CodecParameterMap& params);
|
||||
|
||||
// Returns true if the parameters have the same H265 profile or neither contains
|
||||
// an H265 profile, otherwise false.
|
||||
// Returns true if the parameters have the same H265 profile/tier/level or
|
||||
// neither contains an H265 profile/tier/level, otherwise false.
|
||||
RTC_EXPORT bool H265IsSameProfileTierLevel(const CodecParameterMap& params1,
|
||||
const CodecParameterMap& params2);
|
||||
|
||||
// Returns true if the parameters have the same H265 profile, or neither
|
||||
// contains an H265 profile, otherwise false.
|
||||
RTC_EXPORT bool H265IsSameProfile(const CodecParameterMap& params1,
|
||||
const CodecParameterMap& params2);
|
||||
|
||||
// Returns true if the parameters have the same H265 tier, or neither
|
||||
// contains an H265 tier, otherwise false.
|
||||
RTC_EXPORT bool H265IsSameTier(const CodecParameterMap& params1,
|
||||
const CodecParameterMap& params2);
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_VIDEO_CODECS_H265_PROFILE_TIER_LEVEL_H_
|
||||
|
||||
@ -119,7 +119,8 @@ bool IsSameCodecSpecific(const std::string& name1,
|
||||
AV1IsSameLevelIdx(params1, params2);
|
||||
#ifdef RTC_ENABLE_H265
|
||||
case kVideoCodecH265:
|
||||
return H265IsSameProfileTierLevel(params1, params2) &&
|
||||
return H265IsSameProfile(params1, params2) &&
|
||||
H265IsSameTier(params1, params2) &&
|
||||
IsSameH265TxMode(params1, params2);
|
||||
#endif
|
||||
default:
|
||||
|
||||
@ -231,8 +231,9 @@ TEST(H265ProfileTierLevel, TestProfileTierLevelCompare) {
|
||||
params2.clear();
|
||||
params1["profile-id"] = "1";
|
||||
params2["profile-id"] = "1";
|
||||
params1["level-id"] = "93";
|
||||
params2["level-id"] = "93";
|
||||
params1["level-id"] = "180";
|
||||
// Level 3.1 is not allowed for tier 1.
|
||||
params2["level-id"] = "180";
|
||||
params1["tier-flag"] = "0";
|
||||
params2["tier-flag"] = "1";
|
||||
EXPECT_FALSE(H265IsSameProfileTierLevel(params1, params2));
|
||||
@ -247,6 +248,114 @@ TEST(H265ProfileTierLevel, TestProfileTierLevelCompare) {
|
||||
EXPECT_FALSE(H265IsSameProfileTierLevel(params1, params2));
|
||||
}
|
||||
|
||||
TEST(H265ProfileTierLevel, TestProfileCompare) {
|
||||
CodecParameterMap params1;
|
||||
CodecParameterMap params2;
|
||||
|
||||
// None of profile-id/tier-flag/level-id is specified,
|
||||
EXPECT_TRUE(H265IsSameProfile(params1, params2));
|
||||
|
||||
// Same non-empty PTL
|
||||
params1["profile-id"] = "1";
|
||||
params1["tier-flag"] = "0";
|
||||
params1["level-id"] = "120";
|
||||
params2["profile-id"] = "1";
|
||||
params2["tier-flag"] = "0";
|
||||
params2["level-id"] = "120";
|
||||
EXPECT_TRUE(H265IsSameProfile(params1, params2));
|
||||
|
||||
// Different profiles.
|
||||
params1.clear();
|
||||
params2.clear();
|
||||
params1["profile-id"] = "1";
|
||||
params2["profile-id"] = "2";
|
||||
EXPECT_FALSE(H265IsSameProfile(params1, params2));
|
||||
|
||||
// Different levels. We do not compare HEVC levels.
|
||||
params1.clear();
|
||||
params2.clear();
|
||||
params1["profile-id"] = "1";
|
||||
params2["profile-id"] = "1";
|
||||
params1["level-id"] = "93";
|
||||
params2["level-id"] = "183";
|
||||
EXPECT_TRUE(H265IsSameProfile(params1, params2));
|
||||
|
||||
// Different tiers.
|
||||
params1.clear();
|
||||
params2.clear();
|
||||
params1["profile-id"] = "1";
|
||||
params2["profile-id"] = "1";
|
||||
params1["level-id"] = "180";
|
||||
// level 3.1 is not allowed for tier 1.
|
||||
params2["level-id"] = "180";
|
||||
params1["tier-flag"] = "0";
|
||||
params2["tier-flag"] = "1";
|
||||
EXPECT_TRUE(H265IsSameProfile(params1, params2));
|
||||
|
||||
// One of the CodecParameterMap is invalid.
|
||||
params1.clear();
|
||||
params2.clear();
|
||||
params1["profile-id"] = "1";
|
||||
params2["profile-id"] = "1";
|
||||
params1["tier-flag"] = "0";
|
||||
params2["tier-flag"] = "4";
|
||||
EXPECT_FALSE(H265IsSameProfile(params1, params2));
|
||||
}
|
||||
|
||||
TEST(H265ProfileTierLevel, TestTierCompare) {
|
||||
CodecParameterMap params1;
|
||||
CodecParameterMap params2;
|
||||
|
||||
// None of profile-id/tier-flag/level-id is specified,
|
||||
EXPECT_TRUE(H265IsSameTier(params1, params2));
|
||||
|
||||
// Same non-empty PTL
|
||||
params1["profile-id"] = "1";
|
||||
params1["tier-flag"] = "0";
|
||||
params1["level-id"] = "120";
|
||||
params2["profile-id"] = "1";
|
||||
params2["tier-flag"] = "0";
|
||||
params2["level-id"] = "120";
|
||||
EXPECT_TRUE(H265IsSameTier(params1, params2));
|
||||
|
||||
// Different profiles.
|
||||
params1.clear();
|
||||
params2.clear();
|
||||
params1["profile-id"] = "1";
|
||||
params2["profile-id"] = "2";
|
||||
EXPECT_TRUE(H265IsSameTier(params1, params2));
|
||||
|
||||
// Different levels. We do not compare HEVC levels.
|
||||
params1.clear();
|
||||
params2.clear();
|
||||
params1["profile-id"] = "1";
|
||||
params2["profile-id"] = "1";
|
||||
params1["level-id"] = "93";
|
||||
params2["level-id"] = "183";
|
||||
EXPECT_TRUE(H265IsSameTier(params1, params2));
|
||||
|
||||
// Different tiers.
|
||||
params1.clear();
|
||||
params2.clear();
|
||||
params1["profile-id"] = "1";
|
||||
params2["profile-id"] = "1";
|
||||
params1["level-id"] = "180";
|
||||
// level 3.1 is not allowed for tier 1.
|
||||
params2["level-id"] = "180";
|
||||
params1["tier-flag"] = "0";
|
||||
params2["tier-flag"] = "1";
|
||||
EXPECT_FALSE(H265IsSameTier(params1, params2));
|
||||
|
||||
// One of the CodecParameterMap is invalid.
|
||||
params1.clear();
|
||||
params2.clear();
|
||||
params1["profile-id"] = "1";
|
||||
params2["profile-id"] = "1";
|
||||
params1["tier-flag"] = "0";
|
||||
params2["tier-flag"] = "4";
|
||||
EXPECT_FALSE(H265IsSameTier(params1, params2));
|
||||
}
|
||||
|
||||
TEST(H265ProfileTierLevel, TestGetSupportedH265Level) {
|
||||
// Test with 720p at 30fps
|
||||
Resolution r{.width = 1280, .height = 720};
|
||||
|
||||
@ -92,7 +92,7 @@ TEST(SdpVideoFormatTest, SameCodecNameDifferentParameters) {
|
||||
EXPECT_FALSE(Sdp("H265").IsSameCodec(Sdp(
|
||||
"H265",
|
||||
Params{{"profile-id", "1"}, {"tier-flag", "1"}, {"level-id", "93"}})));
|
||||
EXPECT_FALSE(Sdp("H265").IsSameCodec(Sdp(
|
||||
EXPECT_TRUE(Sdp("H265").IsSameCodec(Sdp(
|
||||
"H265",
|
||||
Params{{"profile-id", "1"}, {"tier-flag", "0"}, {"level-id", "90"}})));
|
||||
EXPECT_FALSE(
|
||||
@ -107,7 +107,7 @@ TEST(SdpVideoFormatTest, SameCodecNameDifferentParameters) {
|
||||
.IsSameCodec(Sdp("H265", Params{{"profile-id", "1"},
|
||||
{"tier-flag", "0"},
|
||||
{"level-id", "120"}})));
|
||||
EXPECT_FALSE(
|
||||
EXPECT_TRUE(
|
||||
Sdp("H265",
|
||||
Params{{"profile-id", "1"}, {"tier-flag", "0"}, {"level-id", "93"}})
|
||||
.IsSameCodec(Sdp("H265", Params{{"profile-id", "1"},
|
||||
|
||||
@ -122,7 +122,8 @@ bool IsSameCodecSpecific(const std::string& name1,
|
||||
AV1IsSameLevelIdx(params1, params2);
|
||||
#ifdef RTC_ENABLE_H265
|
||||
if (either_name_matches(kH265CodecName)) {
|
||||
return webrtc::H265IsSameProfileTierLevel(params1, params2) &&
|
||||
return webrtc::H265IsSameProfile(params1, params2) &&
|
||||
webrtc::H265IsSameTier(params1, params2) &&
|
||||
IsSameH265TxMode(params1, params2);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -420,8 +420,8 @@ TEST(CodecTest, TestH265CodecMatches) {
|
||||
Codec c_level_id_4 = cricket::CreateVideoCodec(95, cricket::kH265CodecName);
|
||||
c_level_id_4.params[cricket::kH265FmtpLevelId] = kLevel4;
|
||||
|
||||
// Does not match since different level-ids are specified.
|
||||
EXPECT_FALSE(c_ptl_blank.Matches(c_level_id_4));
|
||||
// Matches since we ignore level-id when matching H.265 codecs.
|
||||
EXPECT_TRUE(c_ptl_blank.Matches(c_level_id_4));
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
@ -1031,6 +1031,8 @@ std::vector<VideoCodecSettings> WebRtcVideoSendChannel::SelectSendVideoCodecs(
|
||||
// following the spec in https://tools.ietf.org/html/rfc6184#section-8.2.2
|
||||
// since we should limit the encode level to the lower of local and remote
|
||||
// level when level asymmetry is not allowed.
|
||||
// For H.265, the level asymmetry is implicitly allowed. We need to make
|
||||
// sure the encode level is set to the remote offered level.
|
||||
if (format_it->IsSameCodec(
|
||||
{remote_codec.codec.name, remote_codec.codec.params})) {
|
||||
encoders.push_back(remote_codec);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user