1 /*
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "common_video/h264/profile_level_id.h"
12
13 #include <map>
14 #include <string>
15
16 #include "absl/types/optional.h"
17 #include "media/base/h264_profile_level_id.h"
18 #include "test/gtest.h"
19
20 namespace webrtc {
21 namespace H264 {
22
TEST(H264ProfileLevelId,TestParsingInvalid)23 TEST(H264ProfileLevelId, TestParsingInvalid) {
24 // Malformed strings.
25 EXPECT_FALSE(ParseProfileLevelId(""));
26 EXPECT_FALSE(ParseProfileLevelId(" 42e01f"));
27 EXPECT_FALSE(ParseProfileLevelId("4242e01f"));
28 EXPECT_FALSE(ParseProfileLevelId("e01f"));
29 EXPECT_FALSE(ParseProfileLevelId("gggggg"));
30
31 // Invalid level.
32 EXPECT_FALSE(ParseProfileLevelId("42e000"));
33 EXPECT_FALSE(ParseProfileLevelId("42e00f"));
34 EXPECT_FALSE(ParseProfileLevelId("42e0ff"));
35
36 // Invalid profile.
37 EXPECT_FALSE(ParseProfileLevelId("42e11f"));
38 EXPECT_FALSE(ParseProfileLevelId("58601f"));
39 EXPECT_FALSE(ParseProfileLevelId("64e01f"));
40 }
41
TEST(H264ProfileLevelId,TestParsingLevel)42 TEST(H264ProfileLevelId, TestParsingLevel) {
43 EXPECT_EQ(kLevel3_1, ParseProfileLevelId("42e01f")->level);
44 EXPECT_EQ(kLevel1_1, ParseProfileLevelId("42e00b")->level);
45 EXPECT_EQ(kLevel1_b, ParseProfileLevelId("42f00b")->level);
46 EXPECT_EQ(kLevel4_2, ParseProfileLevelId("42C02A")->level);
47 EXPECT_EQ(kLevel5_2, ParseProfileLevelId("640c34")->level);
48 }
49
TEST(H264ProfileLevelId,TestParsingConstrainedBaseline)50 TEST(H264ProfileLevelId, TestParsingConstrainedBaseline) {
51 EXPECT_EQ(kProfileConstrainedBaseline,
52 ParseProfileLevelId("42e01f")->profile);
53 EXPECT_EQ(kProfileConstrainedBaseline,
54 ParseProfileLevelId("42C02A")->profile);
55 EXPECT_EQ(kProfileConstrainedBaseline,
56 ParseProfileLevelId("4de01f")->profile);
57 EXPECT_EQ(kProfileConstrainedBaseline,
58 ParseProfileLevelId("58f01f")->profile);
59 }
60
TEST(H264ProfileLevelId,TestParsingBaseline)61 TEST(H264ProfileLevelId, TestParsingBaseline) {
62 EXPECT_EQ(kProfileBaseline, ParseProfileLevelId("42a01f")->profile);
63 EXPECT_EQ(kProfileBaseline, ParseProfileLevelId("58A01F")->profile);
64 }
65
TEST(H264ProfileLevelId,TestParsingMain)66 TEST(H264ProfileLevelId, TestParsingMain) {
67 EXPECT_EQ(kProfileMain, ParseProfileLevelId("4D401f")->profile);
68 }
69
TEST(H264ProfileLevelId,TestParsingHigh)70 TEST(H264ProfileLevelId, TestParsingHigh) {
71 EXPECT_EQ(kProfileHigh, ParseProfileLevelId("64001f")->profile);
72 }
73
TEST(H264ProfileLevelId,TestParsingConstrainedHigh)74 TEST(H264ProfileLevelId, TestParsingConstrainedHigh) {
75 EXPECT_EQ(kProfileConstrainedHigh, ParseProfileLevelId("640c1f")->profile);
76 }
77
TEST(H264ProfileLevelId,TestSupportedLevel)78 TEST(H264ProfileLevelId, TestSupportedLevel) {
79 EXPECT_EQ(kLevel2_1, *SupportedLevel(640 * 480, 25));
80 EXPECT_EQ(kLevel3_1, *SupportedLevel(1280 * 720, 30));
81 EXPECT_EQ(kLevel4_2, *SupportedLevel(1920 * 1280, 60));
82 }
83
84 // Test supported level below level 1 requirements.
TEST(H264ProfileLevelId,TestSupportedLevelInvalid)85 TEST(H264ProfileLevelId, TestSupportedLevelInvalid) {
86 EXPECT_FALSE(SupportedLevel(0, 0));
87 // All levels support fps > 5.
88 EXPECT_FALSE(SupportedLevel(1280 * 720, 5));
89 // All levels support frame sizes > 183 * 137.
90 EXPECT_FALSE(SupportedLevel(183 * 137, 30));
91 }
92
TEST(H264ProfileLevelId,TestToString)93 TEST(H264ProfileLevelId, TestToString) {
94 EXPECT_EQ("42e01f", *ProfileLevelIdToString(ProfileLevelId(
95 kProfileConstrainedBaseline, kLevel3_1)));
96 EXPECT_EQ("42000a",
97 *ProfileLevelIdToString(ProfileLevelId(kProfileBaseline, kLevel1)));
98 EXPECT_EQ("4d001f",
99 ProfileLevelIdToString(ProfileLevelId(kProfileMain, kLevel3_1)));
100 EXPECT_EQ("640c2a", *ProfileLevelIdToString(
101 ProfileLevelId(kProfileConstrainedHigh, kLevel4_2)));
102 EXPECT_EQ("64002a",
103 *ProfileLevelIdToString(ProfileLevelId(kProfileHigh, kLevel4_2)));
104 }
105
TEST(H264ProfileLevelId,TestToStringLevel1b)106 TEST(H264ProfileLevelId, TestToStringLevel1b) {
107 EXPECT_EQ("42f00b", *ProfileLevelIdToString(ProfileLevelId(
108 kProfileConstrainedBaseline, kLevel1_b)));
109 EXPECT_EQ("42100b", *ProfileLevelIdToString(
110 ProfileLevelId(kProfileBaseline, kLevel1_b)));
111 EXPECT_EQ("4d100b",
112 *ProfileLevelIdToString(ProfileLevelId(kProfileMain, kLevel1_b)));
113 }
114
TEST(H264ProfileLevelId,TestToStringRoundTrip)115 TEST(H264ProfileLevelId, TestToStringRoundTrip) {
116 EXPECT_EQ("42e01f", *ProfileLevelIdToString(*ParseProfileLevelId("42e01f")));
117 EXPECT_EQ("42e01f", *ProfileLevelIdToString(*ParseProfileLevelId("42E01F")));
118 EXPECT_EQ("4d100b", *ProfileLevelIdToString(*ParseProfileLevelId("4d100b")));
119 EXPECT_EQ("4d100b", *ProfileLevelIdToString(*ParseProfileLevelId("4D100B")));
120 EXPECT_EQ("640c2a", *ProfileLevelIdToString(*ParseProfileLevelId("640c2a")));
121 EXPECT_EQ("640c2a", *ProfileLevelIdToString(*ParseProfileLevelId("640C2A")));
122 }
123
TEST(H264ProfileLevelId,TestToStringInvalid)124 TEST(H264ProfileLevelId, TestToStringInvalid) {
125 EXPECT_FALSE(ProfileLevelIdToString(ProfileLevelId(kProfileHigh, kLevel1_b)));
126 EXPECT_FALSE(ProfileLevelIdToString(
127 ProfileLevelId(kProfileConstrainedHigh, kLevel1_b)));
128 EXPECT_FALSE(ProfileLevelIdToString(
129 ProfileLevelId(static_cast<Profile>(255), kLevel3_1)));
130 }
131
TEST(H264ProfileLevelId,TestParseSdpProfileLevelIdEmpty)132 TEST(H264ProfileLevelId, TestParseSdpProfileLevelIdEmpty) {
133 const absl::optional<ProfileLevelId> profile_level_id =
134 ParseSdpProfileLevelId(CodecParameterMap());
135 EXPECT_TRUE(profile_level_id);
136 EXPECT_EQ(kProfileConstrainedBaseline, profile_level_id->profile);
137 EXPECT_EQ(kLevel3_1, profile_level_id->level);
138 }
139
TEST(H264ProfileLevelId,TestParseSdpProfileLevelIdConstrainedHigh)140 TEST(H264ProfileLevelId, TestParseSdpProfileLevelIdConstrainedHigh) {
141 CodecParameterMap params;
142 params["profile-level-id"] = "640c2a";
143 const absl::optional<ProfileLevelId> profile_level_id =
144 ParseSdpProfileLevelId(params);
145 EXPECT_TRUE(profile_level_id);
146 EXPECT_EQ(kProfileConstrainedHigh, profile_level_id->profile);
147 EXPECT_EQ(kLevel4_2, profile_level_id->level);
148 }
149
TEST(H264ProfileLevelId,TestParseSdpProfileLevelIdInvalid)150 TEST(H264ProfileLevelId, TestParseSdpProfileLevelIdInvalid) {
151 CodecParameterMap params;
152 params["profile-level-id"] = "foobar";
153 EXPECT_FALSE(ParseSdpProfileLevelId(params));
154 }
155
TEST(H264ProfileLevelId,TestGenerateProfileLevelIdForAnswerEmpty)156 TEST(H264ProfileLevelId, TestGenerateProfileLevelIdForAnswerEmpty) {
157 CodecParameterMap answer_params;
158 GenerateProfileLevelIdForAnswer(CodecParameterMap(), CodecParameterMap(),
159 &answer_params);
160 EXPECT_TRUE(answer_params.empty());
161 }
162
TEST(H264ProfileLevelId,TestGenerateProfileLevelIdForAnswerLevelSymmetryCapped)163 TEST(H264ProfileLevelId,
164 TestGenerateProfileLevelIdForAnswerLevelSymmetryCapped) {
165 CodecParameterMap low_level;
166 low_level["profile-level-id"] = "42e015";
167 CodecParameterMap high_level;
168 high_level["profile-level-id"] = "42e01f";
169
170 // Level asymmetry is not allowed; test that answer level is the lower of the
171 // local and remote levels.
172 CodecParameterMap answer_params;
173 GenerateProfileLevelIdForAnswer(low_level /* local_supported */,
174 high_level /* remote_offered */,
175 &answer_params);
176 EXPECT_EQ("42e015", answer_params["profile-level-id"]);
177
178 CodecParameterMap answer_params2;
179 GenerateProfileLevelIdForAnswer(high_level /* local_supported */,
180 low_level /* remote_offered */,
181 &answer_params2);
182 EXPECT_EQ("42e015", answer_params2["profile-level-id"]);
183 }
184
TEST(H264ProfileLevelId,TestGenerateProfileLevelIdForAnswerConstrainedBaselineLevelAsymmetry)185 TEST(H264ProfileLevelId,
186 TestGenerateProfileLevelIdForAnswerConstrainedBaselineLevelAsymmetry) {
187 CodecParameterMap local_params;
188 local_params["profile-level-id"] = "42e01f";
189 local_params["level-asymmetry-allowed"] = "1";
190 CodecParameterMap remote_params;
191 remote_params["profile-level-id"] = "42e015";
192 remote_params["level-asymmetry-allowed"] = "1";
193 CodecParameterMap answer_params;
194 GenerateProfileLevelIdForAnswer(local_params, remote_params, &answer_params);
195 // When level asymmetry is allowed, we can answer a higher level than what was
196 // offered.
197 EXPECT_EQ("42e01f", answer_params["profile-level-id"]);
198 }
199
200 } // namespace H264
201 } // namespace webrtc
202