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