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 |