Add to-string function for H264 profile level id

BUG=webrtc:6337
TBR=hta@webrtc.org

Review-Url: https://codereview.webrtc.org/2472693002
Cr-Commit-Position: refs/heads/master@{#14912}
This commit is contained in:
magjed 2016-11-03 06:50:28 -07:00 committed by Commit bot
parent 46c4e3caa3
commit b92184ba0d
3 changed files with 91 additions and 7 deletions

View File

@ -10,6 +10,7 @@
#include "webrtc/common_video/h264/profile_level_id.h"
#include <cstdio>
#include <cstdlib>
#include <cstring>
@ -128,5 +129,49 @@ rtc::Optional<ProfileLevelId> ParseProfileLevelId(const char* str) {
return rtc::Optional<ProfileLevelId>();
}
rtc::Optional<std::string> ProfileLevelIdToString(
const ProfileLevelId& profile_level_id) {
// Handle special case level == 1b.
if (profile_level_id.level == kLevel1_b) {
switch (profile_level_id.profile) {
case kProfileConstrainedBaseline:
return rtc::Optional<std::string>("42f00b");
case kProfileBaseline:
return rtc::Optional<std::string>("42100b");
case kProfileMain:
return rtc::Optional<std::string>("4D100b");
// Level 1b is not allowed for other profiles.
default:
return rtc::Optional<std::string>();
}
}
const char* profile_idc_iop_string;
switch (profile_level_id.profile) {
case kProfileConstrainedBaseline:
profile_idc_iop_string = "42e0";
break;
case kProfileBaseline:
profile_idc_iop_string = "4200";
break;
case kProfileMain:
profile_idc_iop_string = "4D00";
break;
case kProfileConstrainedHigh:
profile_idc_iop_string = "640c";
break;
case kProfileHigh:
profile_idc_iop_string = "6400";
break;
// Unrecognized profile.
default:
return rtc::Optional<std::string>();
}
char str[7];
snprintf(str, 7u, "%s%02x", profile_idc_iop_string, profile_level_id.level);
return rtc::Optional<std::string>(str);
}
} // namespace H264
} // namespace webrtc

View File

@ -11,6 +11,8 @@
#ifndef WEBRTC_COMMON_VIDEO_H264_PROFILE_LEVEL_ID_H_
#define WEBRTC_COMMON_VIDEO_H264_PROFILE_LEVEL_ID_H_
#include <string>
#include "webrtc/base/optional.h"
namespace webrtc {
@ -47,6 +49,8 @@ enum Level {
};
struct ProfileLevelId {
ProfileLevelId(Profile profile, Level level)
: profile(profile), level(level) {}
Profile profile;
Level level;
};
@ -56,6 +60,11 @@ struct ProfileLevelId {
// profile level id.
rtc::Optional<ProfileLevelId> ParseProfileLevelId(const char* str);
// 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(
const ProfileLevelId& profile_level_id);
} // namespace H264
} // namespace webrtc

View File

@ -15,7 +15,7 @@
namespace webrtc {
namespace H264 {
TEST(H264ProfileLevelIdParsing, TestInvalid) {
TEST(H264ProfileLevelId, TestParsingInvalid) {
// Malformed strings.
EXPECT_FALSE(ParseProfileLevelId(""));
EXPECT_FALSE(ParseProfileLevelId(" 42e01f"));
@ -34,7 +34,7 @@ TEST(H264ProfileLevelIdParsing, TestInvalid) {
EXPECT_FALSE(ParseProfileLevelId("64e01f"));
}
TEST(H264ProfileLevelIdParsing, TestLevel) {
TEST(H264ProfileLevelId, TestParsingLevel) {
EXPECT_EQ(kLevel3_1, ParseProfileLevelId("42e01f")->level);
EXPECT_EQ(kLevel1_1, ParseProfileLevelId("42e00b")->level);
EXPECT_EQ(kLevel1_b, ParseProfileLevelId("42f00b")->level);
@ -42,7 +42,7 @@ TEST(H264ProfileLevelIdParsing, TestLevel) {
EXPECT_EQ(kLevel5_2, ParseProfileLevelId("640c34")->level);
}
TEST(H264ProfileLevelIdParsing, TestConstrainedBaseline) {
TEST(H264ProfileLevelId, TestParsingConstrainedBaseline) {
EXPECT_EQ(kProfileConstrainedBaseline,
ParseProfileLevelId("42e01f")->profile);
EXPECT_EQ(kProfileConstrainedBaseline,
@ -53,22 +53,52 @@ TEST(H264ProfileLevelIdParsing, TestConstrainedBaseline) {
ParseProfileLevelId("58f01f")->profile);
}
TEST(H264ProfileLevelIdParsing, TestBaseline) {
TEST(H264ProfileLevelId, TestParsingBaseline) {
EXPECT_EQ(kProfileBaseline, ParseProfileLevelId("42a01f")->profile);
EXPECT_EQ(kProfileBaseline, ParseProfileLevelId("58A01F")->profile);
}
TEST(H264ProfileLevelIdParsing, TestMain) {
TEST(H264ProfileLevelId, TestParsingMain) {
EXPECT_EQ(kProfileMain, ParseProfileLevelId("4D401f")->profile);
}
TEST(H264ProfileLevelIdParsing, TestHigh) {
TEST(H264ProfileLevelId, TestParsingHigh) {
EXPECT_EQ(kProfileHigh, ParseProfileLevelId("64001f")->profile);
}
TEST(H264ProfileLevelIdParsing, TestConstrainedHigh) {
TEST(H264ProfileLevelId, TestParsingConstrainedHigh) {
EXPECT_EQ(kProfileConstrainedHigh, ParseProfileLevelId("640c1f")->profile);
}
TEST(H264ProfileLevelId, TestToString) {
EXPECT_EQ("42e01f", *ProfileLevelIdToString(ProfileLevelId(
kProfileConstrainedBaseline, kLevel3_1)));
EXPECT_EQ("42000a",
*ProfileLevelIdToString(ProfileLevelId(kProfileBaseline, kLevel1)));
EXPECT_EQ("4D001f",
ProfileLevelIdToString(ProfileLevelId(kProfileMain, kLevel3_1)));
EXPECT_EQ("640c2a", *ProfileLevelIdToString(
ProfileLevelId(kProfileConstrainedHigh, kLevel4_2)));
EXPECT_EQ("64002a",
*ProfileLevelIdToString(ProfileLevelId(kProfileHigh, kLevel4_2)));
}
TEST(H264ProfileLevelId, TestToStringLevel1b) {
EXPECT_EQ("42f00b", *ProfileLevelIdToString(ProfileLevelId(
kProfileConstrainedBaseline, kLevel1_b)));
EXPECT_EQ("42100b", *ProfileLevelIdToString(
ProfileLevelId(kProfileBaseline, kLevel1_b)));
EXPECT_EQ("4D100b",
*ProfileLevelIdToString(ProfileLevelId(kProfileMain, kLevel1_b)));
}
TEST(H264ProfileLevelId, TestToStringInvalid) {
EXPECT_FALSE(ProfileLevelIdToString(ProfileLevelId(kProfileHigh, kLevel1_b)));
EXPECT_FALSE(ProfileLevelIdToString(
ProfileLevelId(kProfileConstrainedHigh, kLevel1_b)));
EXPECT_FALSE(ProfileLevelIdToString(
ProfileLevelId(static_cast<Profile>(255), kLevel3_1)));
}
} // namespace H264
} // namespace webrtc