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;
|
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,
|
std::optional<H265Level> GetSupportedH265Level(const Resolution& resolution,
|
||||||
float max_fps) {
|
float max_fps) {
|
||||||
int aligned_width =
|
int aligned_width =
|
||||||
|
|||||||
@ -107,11 +107,21 @@ RTC_EXPORT std::optional<H265Level> GetSupportedH265Level(
|
|||||||
RTC_EXPORT std::optional<H265ProfileTierLevel> ParseSdpForH265ProfileTierLevel(
|
RTC_EXPORT std::optional<H265ProfileTierLevel> ParseSdpForH265ProfileTierLevel(
|
||||||
const CodecParameterMap& params);
|
const CodecParameterMap& params);
|
||||||
|
|
||||||
// Returns true if the parameters have the same H265 profile or neither contains
|
// Returns true if the parameters have the same H265 profile/tier/level or
|
||||||
// an H265 profile, otherwise false.
|
// neither contains an H265 profile/tier/level, otherwise false.
|
||||||
RTC_EXPORT bool H265IsSameProfileTierLevel(const CodecParameterMap& params1,
|
RTC_EXPORT bool H265IsSameProfileTierLevel(const CodecParameterMap& params1,
|
||||||
const CodecParameterMap& params2);
|
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
|
} // namespace webrtc
|
||||||
|
|
||||||
#endif // API_VIDEO_CODECS_H265_PROFILE_TIER_LEVEL_H_
|
#endif // API_VIDEO_CODECS_H265_PROFILE_TIER_LEVEL_H_
|
||||||
|
|||||||
@ -119,7 +119,8 @@ bool IsSameCodecSpecific(const std::string& name1,
|
|||||||
AV1IsSameLevelIdx(params1, params2);
|
AV1IsSameLevelIdx(params1, params2);
|
||||||
#ifdef RTC_ENABLE_H265
|
#ifdef RTC_ENABLE_H265
|
||||||
case kVideoCodecH265:
|
case kVideoCodecH265:
|
||||||
return H265IsSameProfileTierLevel(params1, params2) &&
|
return H265IsSameProfile(params1, params2) &&
|
||||||
|
H265IsSameTier(params1, params2) &&
|
||||||
IsSameH265TxMode(params1, params2);
|
IsSameH265TxMode(params1, params2);
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
|
|||||||
@ -231,8 +231,9 @@ TEST(H265ProfileTierLevel, TestProfileTierLevelCompare) {
|
|||||||
params2.clear();
|
params2.clear();
|
||||||
params1["profile-id"] = "1";
|
params1["profile-id"] = "1";
|
||||||
params2["profile-id"] = "1";
|
params2["profile-id"] = "1";
|
||||||
params1["level-id"] = "93";
|
params1["level-id"] = "180";
|
||||||
params2["level-id"] = "93";
|
// Level 3.1 is not allowed for tier 1.
|
||||||
|
params2["level-id"] = "180";
|
||||||
params1["tier-flag"] = "0";
|
params1["tier-flag"] = "0";
|
||||||
params2["tier-flag"] = "1";
|
params2["tier-flag"] = "1";
|
||||||
EXPECT_FALSE(H265IsSameProfileTierLevel(params1, params2));
|
EXPECT_FALSE(H265IsSameProfileTierLevel(params1, params2));
|
||||||
@ -247,6 +248,114 @@ TEST(H265ProfileTierLevel, TestProfileTierLevelCompare) {
|
|||||||
EXPECT_FALSE(H265IsSameProfileTierLevel(params1, params2));
|
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(H265ProfileTierLevel, TestGetSupportedH265Level) {
|
||||||
// Test with 720p at 30fps
|
// Test with 720p at 30fps
|
||||||
Resolution r{.width = 1280, .height = 720};
|
Resolution r{.width = 1280, .height = 720};
|
||||||
|
|||||||
@ -92,7 +92,7 @@ TEST(SdpVideoFormatTest, SameCodecNameDifferentParameters) {
|
|||||||
EXPECT_FALSE(Sdp("H265").IsSameCodec(Sdp(
|
EXPECT_FALSE(Sdp("H265").IsSameCodec(Sdp(
|
||||||
"H265",
|
"H265",
|
||||||
Params{{"profile-id", "1"}, {"tier-flag", "1"}, {"level-id", "93"}})));
|
Params{{"profile-id", "1"}, {"tier-flag", "1"}, {"level-id", "93"}})));
|
||||||
EXPECT_FALSE(Sdp("H265").IsSameCodec(Sdp(
|
EXPECT_TRUE(Sdp("H265").IsSameCodec(Sdp(
|
||||||
"H265",
|
"H265",
|
||||||
Params{{"profile-id", "1"}, {"tier-flag", "0"}, {"level-id", "90"}})));
|
Params{{"profile-id", "1"}, {"tier-flag", "0"}, {"level-id", "90"}})));
|
||||||
EXPECT_FALSE(
|
EXPECT_FALSE(
|
||||||
@ -107,7 +107,7 @@ TEST(SdpVideoFormatTest, SameCodecNameDifferentParameters) {
|
|||||||
.IsSameCodec(Sdp("H265", Params{{"profile-id", "1"},
|
.IsSameCodec(Sdp("H265", Params{{"profile-id", "1"},
|
||||||
{"tier-flag", "0"},
|
{"tier-flag", "0"},
|
||||||
{"level-id", "120"}})));
|
{"level-id", "120"}})));
|
||||||
EXPECT_FALSE(
|
EXPECT_TRUE(
|
||||||
Sdp("H265",
|
Sdp("H265",
|
||||||
Params{{"profile-id", "1"}, {"tier-flag", "0"}, {"level-id", "93"}})
|
Params{{"profile-id", "1"}, {"tier-flag", "0"}, {"level-id", "93"}})
|
||||||
.IsSameCodec(Sdp("H265", Params{{"profile-id", "1"},
|
.IsSameCodec(Sdp("H265", Params{{"profile-id", "1"},
|
||||||
|
|||||||
@ -122,7 +122,8 @@ bool IsSameCodecSpecific(const std::string& name1,
|
|||||||
AV1IsSameLevelIdx(params1, params2);
|
AV1IsSameLevelIdx(params1, params2);
|
||||||
#ifdef RTC_ENABLE_H265
|
#ifdef RTC_ENABLE_H265
|
||||||
if (either_name_matches(kH265CodecName)) {
|
if (either_name_matches(kH265CodecName)) {
|
||||||
return webrtc::H265IsSameProfileTierLevel(params1, params2) &&
|
return webrtc::H265IsSameProfile(params1, params2) &&
|
||||||
|
webrtc::H265IsSameTier(params1, params2) &&
|
||||||
IsSameH265TxMode(params1, params2);
|
IsSameH265TxMode(params1, params2);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -420,8 +420,8 @@ TEST(CodecTest, TestH265CodecMatches) {
|
|||||||
Codec c_level_id_4 = cricket::CreateVideoCodec(95, cricket::kH265CodecName);
|
Codec c_level_id_4 = cricket::CreateVideoCodec(95, cricket::kH265CodecName);
|
||||||
c_level_id_4.params[cricket::kH265FmtpLevelId] = kLevel4;
|
c_level_id_4.params[cricket::kH265FmtpLevelId] = kLevel4;
|
||||||
|
|
||||||
// Does not match since different level-ids are specified.
|
// Matches since we ignore level-id when matching H.265 codecs.
|
||||||
EXPECT_FALSE(c_ptl_blank.Matches(c_level_id_4));
|
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
|
// 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
|
// since we should limit the encode level to the lower of local and remote
|
||||||
// level when level asymmetry is not allowed.
|
// 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(
|
if (format_it->IsSameCodec(
|
||||||
{remote_codec.codec.name, remote_codec.codec.params})) {
|
{remote_codec.codec.name, remote_codec.codec.params})) {
|
||||||
encoders.push_back(remote_codec);
|
encoders.push_back(remote_codec);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user