| 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..1b3841d2aca7c36301fa4421b132848f873f74fa 100644
|
| --- a/webrtc/common_video/h264/profile_level_id.cc
|
| +++ b/webrtc/common_video/h264/profile_level_id.cc
|
| @@ -14,6 +14,8 @@
|
| #include <cstdlib>
|
| #include <cstring>
|
|
|
| +#include "webrtc/base/arraysize.h"
|
| +
|
| namespace {
|
|
|
| // For level_idc=11 and profile_idc=0x42, 0x4D, or 0x58, the constraint set3
|
| @@ -68,6 +70,33 @@ constexpr ProfilePattern kProfilePatterns[] = {
|
| {0x64, BitPattern("00000000"), webrtc::H264::kProfileHigh},
|
| {0x64, BitPattern("00001100"), webrtc::H264::kProfileConstrainedHigh}};
|
|
|
| +struct LevelConstraint {
|
| + const int max_macroblocks_per_second;
|
| + const int max_macroblock_frame_size;
|
| + const webrtc::H264::Level level;
|
| +};
|
| +
|
| +// This is from ITU-T H.264 (02/2016) Table A-1 – Level limits.
|
| +static constexpr LevelConstraint kLevelConstraints[] = {
|
| + {1485, 99, webrtc::H264::kLevel1},
|
| + {1485, 99, webrtc::H264::kLevel1_b},
|
| + {3000, 396, webrtc::H264::kLevel1_1},
|
| + {6000, 396, webrtc::H264::kLevel1_2},
|
| + {11880, 396, webrtc::H264::kLevel1_3},
|
| + {11880, 396, webrtc::H264::kLevel2},
|
| + {19800, 792, webrtc::H264::kLevel2_1},
|
| + {20250, 1620, webrtc::H264::kLevel2_2},
|
| + {40500, 1620, webrtc::H264::kLevel3},
|
| + {108000, 3600, webrtc::H264::kLevel3_1},
|
| + {216000, 5120, webrtc::H264::kLevel3_2},
|
| + {245760, 8192, webrtc::H264::kLevel4},
|
| + {245760, 8192, webrtc::H264::kLevel4_1},
|
| + {522240, 8704, webrtc::H264::kLevel4_2},
|
| + {589824, 22080, webrtc::H264::kLevel5},
|
| + {983040, 3684, webrtc::H264::kLevel5_1},
|
| + {2073600, 3684, webrtc::H264::kLevel5_2},
|
| +};
|
| +
|
| } // anonymous namespace
|
|
|
| namespace webrtc {
|
| @@ -129,6 +158,23 @@ rtc::Optional<ProfileLevelId> ParseProfileLevelId(const char* str) {
|
| return rtc::Optional<ProfileLevelId>();
|
| }
|
|
|
| +rtc::Optional<Level> SupportedLevel(int max_frame_pixel_count, float max_fps) {
|
| + static const int kPixelsPerMacroblock = 16 * 16;
|
| +
|
| + for (int i = arraysize(kLevelConstraints) - 1; i >= 0; --i) {
|
| + const LevelConstraint& level_constraint = kLevelConstraints[i];
|
| + if (level_constraint.max_macroblock_frame_size * kPixelsPerMacroblock <=
|
| + max_frame_pixel_count &&
|
| + level_constraint.max_macroblocks_per_second <=
|
| + max_fps * level_constraint.max_macroblock_frame_size) {
|
| + return rtc::Optional<Level>(level_constraint.level);
|
| + }
|
| + }
|
| +
|
| + // No level supported.
|
| + return rtc::Optional<Level>();
|
| +}
|
| +
|
| rtc::Optional<std::string> ProfileLevelIdToString(
|
| const ProfileLevelId& profile_level_id) {
|
| // Handle special case level == 1b.
|
|
|