OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright (c) 2017 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 #include "webrtc/modules/video_coding/utility/vp9_uncomp_header_parser.h" | |
11 | |
brandtr
2017/05/19 14:10:27
General comment: have you looked into using the rt
jianj1
2017/05/19 21:20:56
Done.
| |
12 #include "webrtc/base/logging.h" | |
13 | |
14 namespace webrtc { | |
15 | |
16 namespace vp9 { | |
17 namespace { | |
18 const size_t kVp9MaxProfile = 4; | |
19 const size_t kVp9NumRefsPerFrame = 3; | |
20 const size_t kVp9MaxRefLFDeltas = 4; | |
21 const size_t kVp9MaxModeLFDeltas = 2; | |
22 } // namespace | |
23 | |
24 static void VP9InitBitReader(VP9BitReader *const br, const uint8_t *const start, | |
brandtr
2017/05/19 14:10:27
To me, it seems that VP9BitReader could be a full-
jianj1
2017/05/19 21:20:56
Done.
BTW, the same thing could be done to vp8_he
| |
25 const uint8_t *const end) { | |
brandtr
2017/05/19 14:10:27
const uint8_t*, here and in other signatures.
jianj1
2017/05/19 21:20:56
Done.
| |
26 br->offset_ = 0; | |
27 br->buf_ = start; | |
28 br->buf_end_ = end; | |
29 } | |
30 | |
31 static int32_t VP9GetBit(VP9BitReader *const br) { | |
32 const size_t off = br->offset_; | |
33 const size_t p = off >> 3; | |
34 const int q = 7 - static_cast<int>(off & 0x7); | |
35 if (br->buf_ + p < br->buf_end_) { | |
36 const int bit = (br->buf_[p] >> q) & 1; | |
37 br->offset_ = off + 1; | |
38 return bit; | |
39 } else { | |
40 LOG(LS_WARNING) << "Failed to get QP. Reached EOF."; | |
41 return 0; | |
42 } | |
43 } | |
44 | |
45 static int32_t VP9GetValue(VP9BitReader *const br, int bits) { | |
46 int value = 0, bit; | |
47 for (bit = bits - 1; bit >= 0; bit--) | |
48 value |= VP9GetBit(br) << bit; | |
49 return value; | |
50 } | |
51 | |
52 static int32_t VP9GetSignedValue(VP9BitReader *const br, int bits) { | |
53 const int value = VP9GetValue(br, bits); | |
54 return VP9GetBit(br) ? -value : value; | |
55 } | |
56 | |
57 static uint8_t VP9ReadProfile(VP9BitReader *const br) { | |
58 uint8_t profile = 0; | |
59 if (VP9GetBit(br)) | |
60 profile |= 1; | |
61 if (VP9GetBit(br)) | |
62 profile |= 2; | |
63 if (profile > 2 && VP9GetBit(br)) | |
64 profile += 1; | |
65 return profile; | |
66 } | |
67 | |
68 static bool VP9ReadColorConfig(VP9BitReader *const br, const uint8_t profile) { | |
69 if (profile == 2 || profile == 3) { | |
70 // bitdepth | |
71 VP9GetBit(br); | |
72 } | |
73 | |
74 uint8_t color_space = VP9GetValue(br, 3); | |
75 // SRGB is 7 | |
76 if (color_space != 7) { | |
77 // yuv range flag | |
78 VP9GetBit(br); | |
79 if (profile == 1 || profile == 3) { | |
80 // subsampling x | |
brandtr
2017/05/19 14:10:27
Comments: start with capital letter and end with p
jianj1
2017/05/19 21:20:56
Done.
| |
81 VP9GetBit(br); | |
82 // subsampling y | |
83 VP9GetBit(br); | |
84 // reserved | |
85 if (VP9GetBit(br)) { | |
86 LOG(LS_WARNING) << "Failed to get QP. Reserved bit set."; | |
87 return false; | |
88 } | |
89 } | |
90 } else { | |
91 if (profile == 1 || profile == 3) { | |
92 // reserved | |
93 if (VP9GetBit(br)) { | |
94 LOG(LS_WARNING) << "Failed to get QP. Reserved bit set."; | |
95 return false; | |
96 } | |
97 } else { | |
98 LOG(LS_WARNING) << "Failed to get QP. 4:4:4 color not supported in " | |
99 "profile 0 or 2."; | |
100 return false; | |
101 } | |
102 } | |
103 | |
104 return true; | |
105 } | |
106 | |
107 static void VP9ReadFrameSize(VP9BitReader *const br) { | |
108 // frame width | |
109 uint32_t width = VP9GetValue(br, 16); | |
110 (void)width; | |
111 // frame height | |
112 uint32_t height = VP9GetValue(br, 16); | |
113 (void)height; | |
114 } | |
115 | |
116 static void VP9ReadRenderSize(VP9BitReader *const br) { | |
117 // scaling | |
118 if (VP9GetBit(br)) { | |
119 // render width | |
120 uint32_t width = VP9GetValue(br, 16); | |
121 // render height | |
122 uint32_t height = VP9GetValue(br, 16); | |
123 (void)width; | |
124 (void)height; | |
125 } | |
126 } | |
127 | |
128 static void VP9ReadFrameSizeFromRefs(VP9BitReader *const br) { | |
129 int found_ref = 0; | |
130 for (size_t i = 0; i < kVp9NumRefsPerFrame; i++) { | |
131 // size in refs | |
132 found_ref = VP9GetBit(br); | |
133 if (found_ref) | |
134 break; | |
135 } | |
136 | |
137 if (!found_ref) | |
138 VP9ReadFrameSize(br); | |
139 | |
140 VP9ReadRenderSize(br); | |
141 } | |
142 | |
143 static void VP9ReadInterpolationFilter(VP9BitReader *const br) { | |
144 if (VP9GetBit(br)) | |
145 return; | |
146 | |
147 VP9GetValue(br, 2); | |
148 } | |
149 | |
150 static void VP9ReadLoopfilter(VP9BitReader *const br) { | |
151 // filter level | |
152 VP9GetValue(br, 6); | |
153 // sharpness level | |
154 VP9GetValue(br, 3); | |
155 uint32_t mode_ref_delta_enabled = VP9GetBit(br); | |
156 if (mode_ref_delta_enabled) { | |
157 uint32_t mode_ref_delta_update = VP9GetBit(br); | |
158 if (mode_ref_delta_update) { | |
159 for (size_t i = 0; i < kVp9MaxRefLFDeltas; i++) { | |
160 if (VP9GetBit(br)) | |
161 VP9GetSignedValue(br, 6); | |
162 } | |
163 for (size_t i = 0; i < kVp9MaxModeLFDeltas; i++) { | |
164 if (VP9GetBit(br)) | |
165 VP9GetSignedValue(br, 6); | |
166 } | |
167 } | |
168 } | |
169 } | |
170 | |
171 bool GetQp(const uint8_t *buf, size_t length, int *qp) { | |
172 VP9BitReader br; | |
173 VP9InitBitReader(&br, buf, buf + length); | |
174 | |
175 // frame marker | |
176 if (VP9GetValue(&br, 2) != 0x2) { | |
177 LOG(LS_WARNING) << "Failed to get QP. Frame marker should be 2."; | |
178 return false; | |
179 } | |
180 | |
181 // profile | |
182 uint8_t profile = VP9ReadProfile(&br); | |
183 if (profile > kVp9MaxProfile) { | |
184 LOG(LS_WARNING) << "Failed to get QP. Unsupported bitstream profile: " | |
185 << profile; | |
186 return false; | |
187 } | |
188 | |
189 // show existing frame | |
190 if (VP9GetBit(&br)) { | |
191 VP9GetValue(&br, 3); | |
192 return false; | |
193 } | |
194 | |
195 // frame type: KEY_FRAME(0), INTER_FRAME(1) | |
196 uint8_t frame_type = VP9GetBit(&br); | |
197 // show frame | |
198 uint8_t show_frame = VP9GetBit(&br); | |
199 // error resilient | |
200 uint8_t error_resilient = VP9GetBit(&br); | |
201 | |
202 if (!frame_type) { | |
203 // sync code | |
204 uint32_t sync_code = VP9GetValue(&br, 24); | |
205 if (sync_code != 0x498342) { | |
206 LOG(LS_WARNING) << "Failed to get QP. Invalid sync code."; | |
207 return false; | |
208 } | |
209 | |
210 if (!VP9ReadColorConfig(&br, profile)) | |
211 return false; | |
212 | |
213 VP9ReadFrameSize(&br); | |
214 VP9ReadRenderSize(&br); | |
215 } else { | |
216 uint8_t intra_only = 0; | |
217 if (!show_frame) | |
218 intra_only = VP9GetBit(&br); | |
219 | |
220 if (!error_resilient) | |
221 // reset frame context | |
222 VP9GetValue(&br, 2); | |
223 | |
224 if (intra_only) { | |
225 // sync code | |
226 if (VP9GetValue(&br, 24) != 0x498342) { | |
227 LOG(LS_WARNING) << "Failed to get QP. Invalid sync code."; | |
228 return false; | |
229 } | |
230 if (profile > 0) { | |
231 if (!VP9ReadColorConfig(&br, profile)) | |
232 return false; | |
233 } | |
234 // refresh frame flags | |
235 VP9GetValue(&br, 8); | |
236 | |
237 VP9ReadFrameSize(&br); | |
238 VP9ReadRenderSize(&br); | |
239 } else { | |
240 // refresh frame flags | |
241 int32_t test = VP9GetValue(&br, 8); | |
242 (void)test; | |
243 | |
244 for (size_t i = 0; i < kVp9NumRefsPerFrame; i++) { | |
245 // ref frame index | |
246 int32_t idx = VP9GetValue(&br, 3); | |
247 // ref frame sign biases | |
248 int32_t bias = VP9GetBit(&br); | |
249 (void)idx; | |
250 (void)bias; | |
251 } | |
252 | |
253 VP9ReadFrameSizeFromRefs(&br); | |
254 | |
255 // allow high precision mv | |
256 VP9GetBit(&br); | |
257 | |
258 // interpolation filter | |
259 VP9ReadInterpolationFilter(&br); | |
260 } | |
261 } | |
262 | |
263 if (!error_resilient) { | |
264 // refresh frame context | |
265 VP9GetBit(&br); | |
266 // frame parallel decoding mode | |
267 VP9GetBit(&br); | |
268 } | |
269 | |
270 // frame context index | |
271 VP9GetValue(&br, 2); | |
272 | |
273 VP9ReadLoopfilter(&br); | |
274 | |
275 // Base QP. | |
276 const int base_q0 = VP9GetValue(&br, 8); | |
277 *qp = base_q0; | |
278 return true; | |
279 } | |
280 | |
281 } // namespace vp9 | |
282 | |
283 } // namespace webrtc | |
OLD | NEW |