OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include "webrtc/base/checks.h" | 11 #include "webrtc/base/checks.h" |
12 #include "webrtc/common_types.h" | 12 #include "webrtc/common_types.h" |
13 | 13 |
14 #include <stdlib.h> | |
14 #include <string.h> | 15 #include <string.h> |
15 | 16 |
17 namespace { | |
18 | |
19 // For level_idc=11 and profile_idc=0x42, 0x4D, or 0x58, the constraint set3 | |
20 // flag specifies if level 1b or level 1.1 is used. | |
21 const uint8_t kConstraintSet3Flag = 0x10; | |
22 | |
23 // Convert a string of 8 characters into a byte where the positions containing | |
24 // character c will have their bit set. For example, c = 'x', str = "x1xx0000" | |
25 // will return 0b10110000. constexpr is used so that the pattern table in | |
26 // kProfilePatterns is statically initialized. | |
27 constexpr uint8_t ByteMaskString(char c, const char str[]) { | |
28 return (str[0] == c) << 7 | |
hta-webrtc
2016/10/28 09:55:22
Can you insert a DCHECK that strlen(str) == 8?
Thi
magjed_webrtc
2016/10/28 14:59:27
It's not possible to call non-constexpr functions
tommi
2016/10/28 15:02:20
as one more try, sizeof() == 9? or even specify t
| |
29 | (str[1] == c) << 6 | |
30 | (str[2] == c) << 5 | |
31 | (str[3] == c) << 4 | |
32 | (str[4] == c) << 3 | |
33 | (str[5] == c) << 2 | |
34 | (str[6] == c) << 1 | |
35 | (str[7] == c) << 0; | |
36 } | |
37 | |
38 // Class for matching bit patterns such as "x1xx0000" where 'x' is allowed to be | |
39 // either 0 or 1. | |
40 class BitPattern { | |
41 public: | |
42 constexpr BitPattern(const char str[]) | |
43 : mask_(~ByteMaskString('x', str)), | |
44 masked_value_(ByteMaskString('1', str)) {} | |
45 | |
46 bool isMatch(uint8_t value) const { return masked_value_ == (value & mask_); } | |
tommi
2016/10/28 10:09:47
nit: IsMatch
magjed_webrtc
2016/10/28 14:59:27
Done.
| |
47 | |
48 private: | |
49 const uint8_t mask_; | |
50 const uint8_t masked_value_; | |
51 }; | |
52 | |
53 // Table for converting between profile_idc/profile_iop to H264Profile. | |
54 struct ProfilePattern { | |
55 const uint8_t profile_idc; | |
56 const BitPattern profile_iop; | |
57 const webrtc::H264Profile profile; | |
58 }; | |
59 | |
60 // This is from https://tools.ietf.org/html/rfc6184#section-8.1. | |
61 const ProfilePattern kProfilePatterns[] = { | |
62 {0x42, BitPattern("x1xx0000"), webrtc::kProfileConstrainedBaseline}, | |
63 {0x4D, BitPattern("1xxx0000"), webrtc::kProfileConstrainedBaseline}, | |
64 {0x58, BitPattern("11xx0000"), webrtc::kProfileConstrainedBaseline}, | |
65 {0x42, BitPattern("x0xx0000"), webrtc::kProfileBaseline}, | |
66 {0x58, BitPattern("10xx0000"), webrtc::kProfileBaseline}, | |
67 {0x4D, BitPattern("0x0x0000"), webrtc::kProfileMain}, | |
68 {0x64, BitPattern("00000000"), webrtc::kProfileHigh}, | |
69 {0x64, BitPattern("00001100"), webrtc::kProfileConstrainedHigh}}; | |
70 | |
71 } // anonymous namespace | |
72 | |
16 namespace webrtc { | 73 namespace webrtc { |
17 | 74 |
18 StreamDataCounters::StreamDataCounters() : first_packet_time_ms(-1) {} | 75 StreamDataCounters::StreamDataCounters() : first_packet_time_ms(-1) {} |
19 | 76 |
20 RTPHeaderExtension::RTPHeaderExtension() | 77 RTPHeaderExtension::RTPHeaderExtension() |
21 : hasTransmissionTimeOffset(false), | 78 : hasTransmissionTimeOffset(false), |
22 transmissionTimeOffset(0), | 79 transmissionTimeOffset(0), |
23 hasAbsoluteSendTime(false), | 80 hasAbsoluteSendTime(false), |
24 absoluteSendTime(0), | 81 absoluteSendTime(0), |
25 hasTransportSequenceNumber(false), | 82 hasTransportSequenceNumber(false), |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
84 VideoCodecH264* VideoCodec::H264() { | 141 VideoCodecH264* VideoCodec::H264() { |
85 RTC_DCHECK_EQ(codecType, kVideoCodecH264); | 142 RTC_DCHECK_EQ(codecType, kVideoCodecH264); |
86 return &codecSpecific.H264; | 143 return &codecSpecific.H264; |
87 } | 144 } |
88 | 145 |
89 const VideoCodecH264& VideoCodec::H264() const { | 146 const VideoCodecH264& VideoCodec::H264() const { |
90 RTC_DCHECK_EQ(codecType, kVideoCodecH264); | 147 RTC_DCHECK_EQ(codecType, kVideoCodecH264); |
91 return codecSpecific.H264; | 148 return codecSpecific.H264; |
92 } | 149 } |
93 | 150 |
151 rtc::Optional<H264ProfileLevelId> ParseH264ProfileLevelId(const char* str) { | |
hta-webrtc
2016/10/28 09:55:23
Same comment goes for this function.
magjed_webrtc
2016/10/28 14:59:27
I check the string length in this function and ret
| |
152 // The string should consist of 3 bytes in hexadecimal format. | |
153 if (strlen(str) != 6u) | |
154 return rtc::Optional<H264ProfileLevelId>(); | |
155 const long profile_level_id_numeric = strtol(str, nullptr, 16); | |
156 if (profile_level_id_numeric == 0) | |
157 return rtc::Optional<H264ProfileLevelId>(); | |
158 | |
159 // Separate into three bytes. | |
160 const uint8_t level_idc = | |
161 static_cast<uint8_t>(profile_level_id_numeric & 0xFF); | |
162 const uint8_t profile_iop = | |
163 static_cast<uint8_t>((profile_level_id_numeric >> 8) & 0xFF); | |
164 const uint8_t profile_idc = | |
165 static_cast<uint8_t>((profile_level_id_numeric >> 16) & 0xFF); | |
166 | |
167 // Parse level based on level_idc and constraint set 3 flag. | |
168 H264Level level; | |
169 switch (level_idc) { | |
170 case kH264Level1_1: | |
171 level = (profile_iop & kConstraintSet3Flag) != 0 ? kH264Level1_b | |
172 : kH264Level1_1; | |
173 break; | |
174 case kH264Level1: | |
175 case kH264Level1_2: | |
176 case kH264Level1_3: | |
177 case kH264Level2: | |
178 case kH264Level2_1: | |
179 case kH264Level2_2: | |
180 case kH264Level3: | |
181 case kH264Level3_1: | |
182 case kH264Level3_2: | |
183 case kH264Level4: | |
184 case kH264Level4_1: | |
185 case kH264Level4_2: | |
186 case kH264Level5: | |
187 case kH264Level5_1: | |
188 case kH264Level5_2: | |
189 level = static_cast<H264Level>(level_idc); | |
190 break; | |
191 default: | |
192 // Unrecognized level_idc. | |
193 return rtc::Optional<H264ProfileLevelId>(); | |
194 } | |
195 | |
196 // Parse profile_idc/profile_iop into a H264Profile enum. | |
197 for (const ProfilePattern& pattern : kProfilePatterns) { | |
198 if (profile_idc == pattern.profile_idc && | |
199 pattern.profile_iop.isMatch(profile_iop)) { | |
200 return rtc::Optional<H264ProfileLevelId>({pattern.profile, level}); | |
201 } | |
202 } | |
203 | |
204 // Unrecognized profile_idc/profile_iop combination. | |
205 return rtc::Optional<H264ProfileLevelId>(); | |
206 } | |
207 | |
94 } // namespace webrtc | 208 } // namespace webrtc |
OLD | NEW |