From b92184ba0da8af0059ec08fafacccb67ad2475a8 Mon Sep 17 00:00:00 2001 From: magjed Date: Thu, 3 Nov 2016 06:50:28 -0700 Subject: [PATCH] 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} --- webrtc/common_video/h264/profile_level_id.cc | 45 +++++++++++++++++++ webrtc/common_video/h264/profile_level_id.h | 9 ++++ .../h264/profile_level_id_unittest.cc | 44 +++++++++++++++--- 3 files changed, 91 insertions(+), 7 deletions(-) diff --git a/webrtc/common_video/h264/profile_level_id.cc b/webrtc/common_video/h264/profile_level_id.cc index 9f9aef9f61..6d8c5c0ce8 100644 --- a/webrtc/common_video/h264/profile_level_id.cc +++ b/webrtc/common_video/h264/profile_level_id.cc @@ -10,6 +10,7 @@ #include "webrtc/common_video/h264/profile_level_id.h" +#include #include #include @@ -128,5 +129,49 @@ rtc::Optional ParseProfileLevelId(const char* str) { return rtc::Optional(); } +rtc::Optional 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("42f00b"); + case kProfileBaseline: + return rtc::Optional("42100b"); + case kProfileMain: + return rtc::Optional("4D100b"); + // Level 1b is not allowed for other profiles. + default: + return rtc::Optional(); + } + } + + 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(); + } + + char str[7]; + snprintf(str, 7u, "%s%02x", profile_idc_iop_string, profile_level_id.level); + return rtc::Optional(str); +} + } // namespace H264 } // namespace webrtc diff --git a/webrtc/common_video/h264/profile_level_id.h b/webrtc/common_video/h264/profile_level_id.h index 84f0005785..44292631cb 100644 --- a/webrtc/common_video/h264/profile_level_id.h +++ b/webrtc/common_video/h264/profile_level_id.h @@ -11,6 +11,8 @@ #ifndef WEBRTC_COMMON_VIDEO_H264_PROFILE_LEVEL_ID_H_ #define WEBRTC_COMMON_VIDEO_H264_PROFILE_LEVEL_ID_H_ +#include + #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 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 ProfileLevelIdToString( + const ProfileLevelId& profile_level_id); + } // namespace H264 } // namespace webrtc diff --git a/webrtc/common_video/h264/profile_level_id_unittest.cc b/webrtc/common_video/h264/profile_level_id_unittest.cc index 772f5b038e..8bc50689d9 100644 --- a/webrtc/common_video/h264/profile_level_id_unittest.cc +++ b/webrtc/common_video/h264/profile_level_id_unittest.cc @@ -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(255), kLevel3_1))); +} + } // namespace H264 } // namespace webrtc