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)55 bool Vp9ReadColorConfig(rtc::BitBuffer* br, uint8_t profile) {
56 if (profile == 2 || profile == 3) {
57 // Bitdepth.
58 RETURN_FALSE_IF_ERROR(br->ConsumeBits(1));
59 }
60 uint32_t color_space;
61 RETURN_FALSE_IF_ERROR(br->ReadBits(&color_space, 3));
62
63 // SRGB is 7.
64 if (color_space != 7) {
65 // YUV range flag.
66 RETURN_FALSE_IF_ERROR(br->ConsumeBits(1));
67 if (profile == 1 || profile == 3) {
68 // 1 bit: subsampling x.
69 // 1 bit: subsampling y.
70 RETURN_FALSE_IF_ERROR(br->ConsumeBits(2));
71 uint32_t reserved_bit;
72 RETURN_FALSE_IF_ERROR(br->ReadBits(&reserved_bit, 1));
73 if (reserved_bit) {
74 RTC_LOG(LS_WARNING) << "Failed to get QP. Reserved bit set.";
75 return false;
76 }
77 }
78 } else {
79 if (profile == 1 || profile == 3) {
80 uint32_t reserved_bit;
81 RETURN_FALSE_IF_ERROR(br->ReadBits(&reserved_bit, 1));
82 if (reserved_bit) {
83 RTC_LOG(LS_WARNING) << "Failed to get QP. Reserved bit set.";
84 return false;
85 }
86 } else {
87 RTC_LOG(LS_WARNING) << "Failed to get QP. 4:4:4 color not supported in "
88 "profile 0 or 2.";
89 return false;
90 }
91 }
92
93 return true;
94 }
95
Vp9ReadFrameSize(rtc::BitBuffer * br)96 bool Vp9ReadFrameSize(rtc::BitBuffer* br) {
97 // 2 bytes: frame width.
98 // 2 bytes: frame height.
99 return br->ConsumeBytes(4);
100 }
101
Vp9ReadRenderSize(rtc::BitBuffer * br)102 bool Vp9ReadRenderSize(rtc::BitBuffer* br) {
103 uint32_t bit;
104 RETURN_FALSE_IF_ERROR(br->ReadBits(&bit, 1));
105 if (bit) {
106 // 2 bytes: render width.
107 // 2 bytes: render height.
108 RETURN_FALSE_IF_ERROR(br->ConsumeBytes(4));
109 }
110 return true;
111 }
112
Vp9ReadFrameSizeFromRefs(rtc::BitBuffer * br)113 bool Vp9ReadFrameSizeFromRefs(rtc::BitBuffer* br) {
114 uint32_t found_ref = 0;
115 for (size_t i = 0; i < kVp9NumRefsPerFrame; i++) {
116 // Size in refs.
117 RETURN_FALSE_IF_ERROR(br->ReadBits(&found_ref, 1));
118 if (found_ref)
119 break;
120 }
121
122 if (!found_ref) {
123 if (!Vp9ReadFrameSize(br)) {
124 return false;
125 }
126 }
127 return Vp9ReadRenderSize(br);
128 }
129
Vp9ReadInterpolationFilter(rtc::BitBuffer * br)130 bool Vp9ReadInterpolationFilter(rtc::BitBuffer* br) {
131 uint32_t bit;
132 RETURN_FALSE_IF_ERROR(br->ReadBits(&bit, 1));
133 if (bit)
134 return true;
135
136 return br->ConsumeBits(2);
137 }
138
Vp9ReadLoopfilter(rtc::BitBuffer * br)139 bool Vp9ReadLoopfilter(rtc::BitBuffer* br) {
140 // 6 bits: filter level.
141 // 3 bits: sharpness level.
142 RETURN_FALSE_IF_ERROR(br->ConsumeBits(9));
143
144 uint32_t mode_ref_delta_enabled;
145 RETURN_FALSE_IF_ERROR(br->ReadBits(&mode_ref_delta_enabled, 1));
146 if (mode_ref_delta_enabled) {
147 uint32_t mode_ref_delta_update;
148 RETURN_FALSE_IF_ERROR(br->ReadBits(&mode_ref_delta_update, 1));
149 if (mode_ref_delta_update) {
150 uint32_t bit;
151 for (size_t i = 0; i < kVp9MaxRefLFDeltas; i++) {
152 RETURN_FALSE_IF_ERROR(br->ReadBits(&bit, 1));
153 if (bit) {
154 RETURN_FALSE_IF_ERROR(br->ConsumeBits(7));
155 }
156 }
157 for (size_t i = 0; i < kVp9MaxModeLFDeltas; i++) {
158 RETURN_FALSE_IF_ERROR(br->ReadBits(&bit, 1));
159 if (bit) {
160 RETURN_FALSE_IF_ERROR(br->ConsumeBits(7));
161 }
162 }
163 }
164 }
165 return true;
166 }
167 } // namespace
168
GetQp(const uint8_t * buf,size_t length,int * qp)169 bool GetQp(const uint8_t* buf, size_t length, int* qp) {
170 rtc::BitBuffer br(buf, length);
171
172 // Frame marker.
173 uint32_t frame_marker;
174 RETURN_FALSE_IF_ERROR(br.ReadBits(&frame_marker, 2));
175 if (frame_marker != 0x2) {
176 RTC_LOG(LS_WARNING) << "Failed to get QP. Frame marker should be 2.";
177 return false;
178 }
179
180 // Profile.
181 uint8_t profile;
182 if (!Vp9ReadProfile(&br, &profile))
183 return false;
184
185 // Show existing frame.
186 uint32_t show_existing_frame;
187 RETURN_FALSE_IF_ERROR(br.ReadBits(&show_existing_frame, 1));
188 if (show_existing_frame)
189 return false;
190
191 // Frame type: KEY_FRAME(0), INTER_FRAME(1).
192 uint32_t frame_type;
193 uint32_t show_frame;
194 uint32_t error_resilient;
195 RETURN_FALSE_IF_ERROR(br.ReadBits(&frame_type, 1));
196 RETURN_FALSE_IF_ERROR(br.ReadBits(&show_frame, 1));
197 RETURN_FALSE_IF_ERROR(br.ReadBits(&error_resilient, 1));
198
199 if (!frame_type) {
200 if (!Vp9ReadSyncCode(&br))
201 return false;
202 if (!Vp9ReadColorConfig(&br, profile))
203 return false;
204 if (!Vp9ReadFrameSize(&br))
205 return false;
206 if (!Vp9ReadRenderSize(&br))
207 return false;
208
209 } else {
210 uint32_t intra_only = 0;
211 if (!show_frame)
212 RETURN_FALSE_IF_ERROR(br.ReadBits(&intra_only, 1));
213 if (!error_resilient)
214 RETURN_FALSE_IF_ERROR(br.ConsumeBits(2)); // Reset frame context.
215
216 if (intra_only) {
217 if (!Vp9ReadSyncCode(&br))
218 return false;
219
220 if (profile > 0) {
221 if (!Vp9ReadColorConfig(&br, profile))
222 return false;
223 }
224 // Refresh frame flags.
225 RETURN_FALSE_IF_ERROR(br.ConsumeBits(8));
226 if (!Vp9ReadFrameSize(&br))
227 return false;
228 if (!Vp9ReadRenderSize(&br))
229 return false;
230 } else {
231 // Refresh frame flags.
232 RETURN_FALSE_IF_ERROR(br.ConsumeBits(8));
233
234 for (size_t i = 0; i < kVp9NumRefsPerFrame; i++) {
235 // 3 bits: Ref frame index.
236 // 1 bit: Ref frame sign biases.
237 RETURN_FALSE_IF_ERROR(br.ConsumeBits(4));
238 }
239
240 if (!Vp9ReadFrameSizeFromRefs(&br))
241 return false;
242
243 // Allow high precision mv.
244 RETURN_FALSE_IF_ERROR(br.ConsumeBits(1));
245 // Interpolation filter.
246 if (!Vp9ReadInterpolationFilter(&br))
247 return false;
248 }
249 }
250
251 if (!error_resilient) {
252 // 1 bit: Refresh frame context.
253 // 1 bit: Frame parallel decoding mode.
254 RETURN_FALSE_IF_ERROR(br.ConsumeBits(2));
255 }
256
257 // Frame context index.
258 RETURN_FALSE_IF_ERROR(br.ConsumeBits(2));
259
260 if (!Vp9ReadLoopfilter(&br))
261 return false;
262
263 // Base QP.
264 uint8_t base_q0;
265 RETURN_FALSE_IF_ERROR(br.ReadUInt8(&base_q0));
266 *qp = base_q0;
267 return true;
268 }
269
270 } // namespace vp9
271
272 } // namespace webrtc
273