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 "modules/video_coding/utility/vp9_uncompressed_header_parser.h"
11
12 #include "rtc_base/bit_buffer.h"
13 #include "rtc_base/logging.h"
14
15 namespace webrtc {
16
17 #define RETURN_FALSE_IF_ERROR(x) \
18 if (!(x)) { \
19 return false; \
20 }
21
22 namespace vp9 {
23 namespace {
24 const size_t kVp9NumRefsPerFrame = 3;
25 const size_t kVp9MaxRefLFDeltas = 4;
26 const size_t kVp9MaxModeLFDeltas = 2;
27
Vp9ReadProfile(rtc::BitBuffer * br,uint8_t * profile)28 bool Vp9ReadProfile(rtc::BitBuffer* br, uint8_t* profile) {
29 uint32_t high_bit;
30 uint32_t low_bit;
31 RETURN_FALSE_IF_ERROR(br->ReadBits(&low_bit, 1));
32 RETURN_FALSE_IF_ERROR(br->ReadBits(&high_bit, 1));
33 *profile = (high_bit << 1) + low_bit;
34 if (*profile > 2) {
35 uint32_t reserved_bit;
36 RETURN_FALSE_IF_ERROR(br->ReadBits(&reserved_bit, 1));
37 if (reserved_bit) {
38 RTC_LOG(LS_WARNING) << "Failed to get QP. Unsupported bitstream profile.";
39 return false;
40 }
41 }
42 return true;
43 }
44
Vp9ReadSyncCode(rtc::BitBuffer * br)45 bool Vp9ReadSyncCode(rtc::BitBuffer* br) {
46 uint32_t sync_code;
47 RETURN_FALSE_IF_ERROR(br->ReadBits(&sync_code, 24));
48 if (sync_code != 0x498342) {
49 RTC_LOG(LS_WARNING) << "Failed to get QP. Invalid sync code.";
50 return false;
51 }
52 return true;
53 }
54
Vp9ReadColorConfig(rtc::BitBuffer * br,uint8_t profile,FrameInfo * frame_info)55 bool Vp9ReadColorConfig(rtc::BitBuffer* br,
56 uint8_t profile,
57 FrameInfo* frame_info) {
58 if (profile == 0 || profile == 1) {
59 frame_info->bit_detph = BitDept::k8Bit;
60 } else if (profile == 2 || profile == 3) {
61 uint32_t ten_or_twelve_bits;
62 RETURN_FALSE_IF_ERROR(br->ReadBits(&ten_or_twelve_bits, 1));
63 frame_info->bit_detph =
64 ten_or_twelve_bits ? BitDept::k12Bit : BitDept::k10Bit;
65 }
66 uint32_t color_space;
67 RETURN_FALSE_IF_ERROR(br->ReadBits(&color_space, 3));
68 frame_info->color_space = static_cast<ColorSpace>(color_space);
69
70 // SRGB is 7.
71 if (color_space != 7) {
72 uint32_t color_range;
73 RETURN_FALSE_IF_ERROR(br->ReadBits(&color_range, 1));
74 frame_info->color_range =
75 color_range ? ColorRange::kFull : ColorRange::kStudio;
76
77 if (profile == 1 || profile == 3) {
78 uint32_t subsampling_x;
79 uint32_t subsampling_y;
80 RETURN_FALSE_IF_ERROR(br->ReadBits(&subsampling_x, 1));
81 RETURN_FALSE_IF_ERROR(br->ReadBits(&subsampling_y, 1));
82 if (subsampling_x) {
83 frame_info->sub_sampling =
84 subsampling_y ? YuvSubsampling::k420 : YuvSubsampling::k422;
85 } else {
86 frame_info->sub_sampling =
87 subsampling_y ? YuvSubsampling::k440 : YuvSubsampling::k444;
88 }
89
90 uint32_t reserved_bit;
91 RETURN_FALSE_IF_ERROR(br->ReadBits(&reserved_bit, 1));
92 if (reserved_bit) {
93 RTC_LOG(LS_WARNING) << "Failed to parse header. Reserved bit set.";
94 return false;
95 }
96 } else {
97 // Profile 0 or 2.
98 frame_info->sub_sampling = YuvSubsampling::k420;
99 }
100 } else {
101 // SRGB
102 frame_info->color_range = ColorRange::kFull;
103 if (profile == 1 || profile == 3) {
104 frame_info->sub_sampling = YuvSubsampling::k444;
105 uint32_t reserved_bit;
106 RETURN_FALSE_IF_ERROR(br->ReadBits(&reserved_bit, 1));
107 if (reserved_bit) {
108 RTC_LOG(LS_WARNING) << "Failed to parse header. Reserved bit set.";
109 return false;
110 }
111 } else {
112 RTC_LOG(LS_WARNING) << "Failed to parse header. 4:4:4 color not supported"
113 " in profile 0 or 2.";
114 return false;
115 }
116 }
117
118 return true;
119 }
120
Vp9ReadFrameSize(rtc::BitBuffer * br,FrameInfo * frame_info)121 bool Vp9ReadFrameSize(rtc::BitBuffer* br, FrameInfo* frame_info) {
122 // 16 bits: frame width - 1.
123 uint16_t frame_width_minus_one;
124 RETURN_FALSE_IF_ERROR(br->ReadUInt16(&frame_width_minus_one));
125 // 16 bits: frame height - 1.
126 uint16_t frame_height_minus_one;
127 RETURN_FALSE_IF_ERROR(br->ReadUInt16(&frame_height_minus_one));
128 frame_info->frame_width = frame_width_minus_one + 1;
129 frame_info->frame_height = frame_height_minus_one + 1;
130 return true;
131 }
132
Vp9ReadRenderSize(rtc::BitBuffer * br,FrameInfo * frame_info)133 bool Vp9ReadRenderSize(rtc::BitBuffer* br, FrameInfo* frame_info) {
134 uint32_t render_and_frame_size_different;
135 RETURN_FALSE_IF_ERROR(br->ReadBits(&render_and_frame_size_different, 1));
136 if (render_and_frame_size_different) {
137 // 16 bits: render width - 1.
138 uint16_t render_width_minus_one;
139 RETURN_FALSE_IF_ERROR(br->ReadUInt16(&render_width_minus_one));
140 // 16 bits: render height - 1.
141 uint16_t render_height_minus_one;
142 RETURN_FALSE_IF_ERROR(br->ReadUInt16(&render_height_minus_one));
143 frame_info->render_width = render_width_minus_one + 1;
144 frame_info->render_height = render_height_minus_one + 1;
145 } else {
146 frame_info->render_width = frame_info->frame_width;
147 frame_info->render_height = frame_info->frame_height;
148 }
149 return true;
150 }
151
Vp9ReadFrameSizeFromRefs(rtc::BitBuffer * br,FrameInfo * frame_info)152 bool Vp9ReadFrameSizeFromRefs(rtc::BitBuffer* br, FrameInfo* frame_info) {
153 uint32_t found_ref = 0;
154 for (size_t i = 0; i < kVp9NumRefsPerFrame; i++) {
155 // Size in refs.
156 RETURN_FALSE_IF_ERROR(br->ReadBits(&found_ref, 1));
157 if (found_ref)
158 break;
159 }
160
161 if (!found_ref) {
162 if (!Vp9ReadFrameSize(br, frame_info)) {
163 return false;
164 }
165 }
166 return Vp9ReadRenderSize(br, frame_info);
167 }
168
Vp9ReadInterpolationFilter(rtc::BitBuffer * br)169 bool Vp9ReadInterpolationFilter(rtc::BitBuffer* br) {
170 uint32_t bit;
171 RETURN_FALSE_IF_ERROR(br->ReadBits(&bit, 1));
172 if (bit)
173 return true;
174
175 return br->ConsumeBits(2);
176 }
177
Vp9ReadLoopfilter(rtc::BitBuffer * br)178 bool Vp9ReadLoopfilter(rtc::BitBuffer* br) {
179 // 6 bits: filter level.
180 // 3 bits: sharpness level.
181 RETURN_FALSE_IF_ERROR(br->ConsumeBits(9));
182
183 uint32_t mode_ref_delta_enabled;
184 RETURN_FALSE_IF_ERROR(br->ReadBits(&mode_ref_delta_enabled, 1));
185 if (mode_ref_delta_enabled) {
186 uint32_t mode_ref_delta_update;
187 RETURN_FALSE_IF_ERROR(br->ReadBits(&mode_ref_delta_update, 1));
188 if (mode_ref_delta_update) {
189 uint32_t bit;
190 for (size_t i = 0; i < kVp9MaxRefLFDeltas; i++) {
191 RETURN_FALSE_IF_ERROR(br->ReadBits(&bit, 1));
192 if (bit) {
193 RETURN_FALSE_IF_ERROR(br->ConsumeBits(7));
194 }
195 }
196 for (size_t i = 0; i < kVp9MaxModeLFDeltas; i++) {
197 RETURN_FALSE_IF_ERROR(br->ReadBits(&bit, 1));
198 if (bit) {
199 RETURN_FALSE_IF_ERROR(br->ConsumeBits(7));
200 }
201 }
202 }
203 }
204 return true;
205 }
206 } // namespace
207
Parse(const uint8_t * buf,size_t length,int * qp,FrameInfo * frame_info)208 bool Parse(const uint8_t* buf, size_t length, int* qp, FrameInfo* frame_info) {
209 rtc::BitBuffer br(buf, length);
210
211 // Frame marker.
212 uint32_t frame_marker;
213 RETURN_FALSE_IF_ERROR(br.ReadBits(&frame_marker, 2));
214 if (frame_marker != 0x2) {
215 RTC_LOG(LS_WARNING) << "Failed to parse header. Frame marker should be 2.";
216 return false;
217 }
218
219 // Profile.
220 uint8_t profile;
221 if (!Vp9ReadProfile(&br, &profile))
222 return false;
223 frame_info->profile = profile;
224
225 // Show existing frame.
226 uint32_t show_existing_frame;
227 RETURN_FALSE_IF_ERROR(br.ReadBits(&show_existing_frame, 1));
228 if (show_existing_frame)
229 return false;
230
231 // Frame type: KEY_FRAME(0), INTER_FRAME(1).
232 uint32_t frame_type;
233 uint32_t show_frame;
234 uint32_t error_resilient;
235 RETURN_FALSE_IF_ERROR(br.ReadBits(&frame_type, 1));
236 RETURN_FALSE_IF_ERROR(br.ReadBits(&show_frame, 1));
237 RETURN_FALSE_IF_ERROR(br.ReadBits(&error_resilient, 1));
238 frame_info->show_frame = show_frame;
239 frame_info->error_resilient = error_resilient;
240
241 if (frame_type == 0) {
242 // Key-frame.
243 if (!Vp9ReadSyncCode(&br))
244 return false;
245 if (!Vp9ReadColorConfig(&br, profile, frame_info))
246 return false;
247 if (!Vp9ReadFrameSize(&br, frame_info))
248 return false;
249 if (!Vp9ReadRenderSize(&br, frame_info))
250 return false;
251 } else {
252 // Non-keyframe.
253 uint32_t intra_only = 0;
254 if (!show_frame)
255 RETURN_FALSE_IF_ERROR(br.ReadBits(&intra_only, 1));
256 if (!error_resilient)
257 RETURN_FALSE_IF_ERROR(br.ConsumeBits(2)); // Reset frame context.
258
259 if (intra_only) {
260 if (!Vp9ReadSyncCode(&br))
261 return false;
262
263 if (profile > 0) {
264 if (!Vp9ReadColorConfig(&br, profile, frame_info))
265 return false;
266 }
267 // Refresh frame flags.
268 RETURN_FALSE_IF_ERROR(br.ConsumeBits(8));
269 if (!Vp9ReadFrameSize(&br, frame_info))
270 return false;
271 if (!Vp9ReadRenderSize(&br, frame_info))
272 return false;
273 } else {
274 // Refresh frame flags.
275 RETURN_FALSE_IF_ERROR(br.ConsumeBits(8));
276
277 for (size_t i = 0; i < kVp9NumRefsPerFrame; i++) {
278 // 3 bits: Ref frame index.
279 // 1 bit: Ref frame sign biases.
280 RETURN_FALSE_IF_ERROR(br.ConsumeBits(4));
281 }
282
283 if (!Vp9ReadFrameSizeFromRefs(&br, frame_info))
284 return false;
285
286 // Allow high precision mv.
287 RETURN_FALSE_IF_ERROR(br.ConsumeBits(1));
288 // Interpolation filter.
289 if (!Vp9ReadInterpolationFilter(&br))
290 return false;
291 }
292 }
293
294 if (!error_resilient) {
295 // 1 bit: Refresh frame context.
296 // 1 bit: Frame parallel decoding mode.
297 RETURN_FALSE_IF_ERROR(br.ConsumeBits(2));
298 }
299
300 // Frame context index.
301 RETURN_FALSE_IF_ERROR(br.ConsumeBits(2));
302
303 if (!Vp9ReadLoopfilter(&br))
304 return false;
305
306 // Base QP.
307 uint8_t base_q0;
308 RETURN_FALSE_IF_ERROR(br.ReadUInt8(&base_q0));
309 *qp = base_q0;
310 return true;
311 }
312
GetQp(const uint8_t * buf,size_t length,int * qp)313 bool GetQp(const uint8_t* buf, size_t length, int* qp) {
314 FrameInfo frame_info;
315 return Parse(buf, length, qp, &frame_info);
316 }
317
ParseIntraFrameInfo(const uint8_t * buf,size_t length)318 absl::optional<FrameInfo> ParseIntraFrameInfo(const uint8_t* buf,
319 size_t length) {
320 int qp = 0;
321 FrameInfo frame_info;
322 if (Parse(buf, length, &qp, &frame_info) && frame_info.frame_width > 0) {
323 return frame_info;
324 }
325 return absl::nullopt;
326 }
327
328 } // namespace vp9
329 } // namespace webrtc
330