Add function for getting supported H264 level from max resolution and fps
BUG=webrtc:6337 Review-Url: https://codereview.webrtc.org/2470133002 Cr-Commit-Position: refs/heads/master@{#14969}
This commit is contained in:
parent
79e05888e8
commit
a92704e6f5
@ -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.
|
||||
|
||||
@ -60,6 +60,12 @@ struct ProfileLevelId {
|
||||
// profile level id.
|
||||
rtc::Optional<ProfileLevelId> ParseProfileLevelId(const char* str);
|
||||
|
||||
// Given that a decoder supports up to a given frame size (in pixels) at up to a
|
||||
// given number of frames per second, return the highest H.264 level where it
|
||||
// can guarantee that it will be able to support all valid encoded streams that
|
||||
// are within that level.
|
||||
rtc::Optional<Level> SupportedLevel(int max_frame_pixel_count, float max_fps);
|
||||
|
||||
// Returns canonical string representation as three hex bytes of the profile
|
||||
// level id, or returns nothing for invalid profile level ids.
|
||||
rtc::Optional<std::string> ProfileLevelIdToString(
|
||||
|
||||
@ -70,6 +70,21 @@ TEST(H264ProfileLevelId, TestParsingConstrainedHigh) {
|
||||
EXPECT_EQ(kProfileConstrainedHigh, ParseProfileLevelId("640c1f")->profile);
|
||||
}
|
||||
|
||||
TEST(H264ProfileLevelId, TestSupportedLevel) {
|
||||
EXPECT_EQ(kLevel2_1, *SupportedLevel(640 * 480, 25));
|
||||
EXPECT_EQ(kLevel3_1, *SupportedLevel(1280 * 720, 30));
|
||||
EXPECT_EQ(kLevel4_2, *SupportedLevel(1920 * 1280, 60));
|
||||
}
|
||||
|
||||
// Test supported level below level 1 requirements.
|
||||
TEST(H264ProfileLevelId, TestSupportedLevelInvalid) {
|
||||
EXPECT_FALSE(SupportedLevel(0, 0));
|
||||
// All levels support fps > 5.
|
||||
EXPECT_FALSE(SupportedLevel(1280 * 720, 5));
|
||||
// All levels support frame sizes > 183 * 137.
|
||||
EXPECT_FALSE(SupportedLevel(183 * 137, 30));
|
||||
}
|
||||
|
||||
TEST(H264ProfileLevelId, TestToString) {
|
||||
EXPECT_EQ("42e01f", *ProfileLevelIdToString(ProfileLevelId(
|
||||
kProfileConstrainedBaseline, kLevel3_1)));
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user