Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(519)

Unified Diff: webrtc/common_video/h264/profile_level_id.cc

Issue 2481033003: Add helper functions for negotiating H264 profile level id (Closed)
Patch Set: Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: webrtc/common_video/h264/profile_level_id.cc
diff --git a/webrtc/common_video/h264/profile_level_id.cc b/webrtc/common_video/h264/profile_level_id.cc
index c7b7f2c2fffd13f8796fe92fd0999ee422dba68d..3a872ebc900cf7e6488adb85ffd3e3d130d45e1f 100644
--- a/webrtc/common_video/h264/profile_level_id.cc
+++ b/webrtc/common_video/h264/profile_level_id.cc
@@ -68,6 +68,20 @@ constexpr ProfilePattern kProfilePatterns[] = {
{0x64, BitPattern("00000000"), webrtc::H264::kProfileHigh},
{0x64, BitPattern("00001100"), webrtc::H264::kProfileConstrainedHigh}};
+// Compare H264 levels and handle the level 1b case.
+bool IsLess(webrtc::H264::Level a, webrtc::H264::Level b) {
+ if (a == webrtc::H264::kLevel1_b)
+ return b != webrtc::H264::kLevel1 && b != webrtc::H264::kLevel1_b;
+ if (b == webrtc::H264::kLevel1_b)
+ return a == webrtc::H264::kLevel1;
+ return a < b;
+}
+
+bool IsLevelAsymmetryAllowed(const webrtc::H264::CodecParameterMap& params) {
+ const auto it = params.find("level-asymmetry-allowed");
+ return it != params.end() && strcmp(it->second.c_str(), "1") == 0;
+}
+
} // anonymous namespace
namespace webrtc {
@@ -129,6 +143,24 @@ rtc::Optional<ProfileLevelId> ParseProfileLevelId(const char* str) {
return rtc::Optional<ProfileLevelId>();
}
+rtc::Optional<ProfileLevelId> ParseSdpProfileLevelId(
+ const CodecParameterMap& params) {
+ // TODO(magjed): The default should really be kProfileBaseline and kLevel1
+ // according to the spec: https://tools.ietf.org/html/rfc6184#section-8.1. In
+ // order to not break backwards compatibility with older versions of WebRTC
+ // where external codecs don't have any parameters, use
+ // kProfileConstrainedBaseline kLevel3_1 instead. This workaround will only be
+ // done in an interim period to allow external clients to update their code.
+ // http://crbug/webrtc/6337.
+ static const ProfileLevelId kDefaultProfileLevelId(
+ kProfileConstrainedBaseline, kLevel3_1);
+
+ const auto profile_level_id_it = params.find("profile-level-id");
+ return (profile_level_id_it == params.end())
+ ? rtc::Optional<ProfileLevelId>(kDefaultProfileLevelId)
+ : ParseProfileLevelId(profile_level_id_it->second.c_str());
kthelgason 2016/11/08 09:27:24 nit: IMO this is a little too much code for a tern
magjed_webrtc 2016/11/08 15:48:40 Acknowledged, but I think this is fine.
+}
+
rtc::Optional<std::string> ProfileLevelIdToString(
const ProfileLevelId& profile_level_id) {
// Handle special case level == 1b.
@@ -173,5 +205,33 @@ rtc::Optional<std::string> ProfileLevelIdToString(
return rtc::Optional<std::string>(str);
}
+rtc::Optional<ProfileLevelId> NegotiateProfileLevelId(
hta-webrtc 2016/11/08 09:39:06 The name of this function is misleading - it doesn
magjed_webrtc 2016/11/08 15:48:39 What I'm trying to implement here is the negotiati
+ const CodecParameterMap& local_params,
+ const CodecParameterMap& remote_params) {
+ const rtc::Optional<ProfileLevelId> local_profile_level_id =
+ ParseSdpProfileLevelId(local_params);
+ const rtc::Optional<ProfileLevelId> remote_profile_level_id =
+ ParseSdpProfileLevelId(remote_params);
+ // Check that local and remote have the same H264 Profile.
+ if (!local_profile_level_id || !remote_profile_level_id ||
+ local_profile_level_id->profile != remote_profile_level_id->profile) {
+ return rtc::Optional<ProfileLevelId>();
kthelgason 2016/11/08 09:27:24 Can't you just choose the lower of the two profile
magjed_webrtc 2016/11/08 15:48:39 This is unfortunately not allowed according to the
+ }
+
+ // Parse level-asymmetry-allowed.
+ const bool level_asymmetry_allowed = IsLevelAsymmetryAllowed(local_params) &&
+ IsLevelAsymmetryAllowed(remote_params);
+ // Abort if local codec can't cope with the remote H264 level.
+ if (!level_asymmetry_allowed &&
+ IsLess(local_profile_level_id->level, remote_profile_level_id->level)) {
+ return rtc::Optional<ProfileLevelId>();
hta-webrtc 2016/11/08 09:39:06 In the case where we end up here, the local profil
magjed_webrtc 2016/11/08 15:48:40 I see, I misunderstood what level-asymmetry-allowe
+ }
+
+ const Level level = level_asymmetry_allowed ? local_profile_level_id->level
+ : remote_profile_level_id->level;
+ return rtc::Optional<ProfileLevelId>(
+ ProfileLevelId(local_profile_level_id->profile, level));
+}
+
} // namespace H264
} // namespace webrtc

Powered by Google App Engine
This is Rietveld 408576698