Chromium Code Reviews| 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 |