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_uncompressed_header_parser.h" | |
11 | |
12 namespace webrtc { | |
13 | |
14 namespace vp9 { | |
15 namespace { | |
16 const size_t kVp9MaxProfile = 4; | |
17 const size_t kVp9NumRefsPerFrame = 3; | |
18 const size_t kVp9MaxRefLFDeltas = 4; | |
19 const size_t kVp9MaxModeLFDeltas = 2; | |
20 } // namespace | |
21 | |
22 static uint8_t VP9ReadProfile(VP9BitReader *br) { | |
brandtr
2017/05/23 08:59:02
Style nit: VP9ReadProfile(VP9BitReader* br)
jianj1
2017/05/23 17:37:30
Done.
| |
23 uint8_t profile = 0; | |
24 if (br->GetBit()) | |
25 profile |= 1; | |
26 if (br->GetBit()) | |
27 profile |= 2; | |
28 if (profile > 2 && br->GetBit()) | |
29 profile += 1; | |
30 return profile; | |
31 } | |
32 | |
33 static bool VP9ReadColorConfig(VP9BitReader *const br, const uint8_t profile) { | |
brandtr
2017/05/23 08:59:02
We generally don't make the parameters const, sinc
jianj1
2017/05/23 17:37:30
Done.
| |
34 if (profile == 2 || profile == 3) { | |
35 // Bitdepth. | |
36 br->GetBit(); | |
37 } | |
38 | |
39 uint8_t color_space = br->GetValue(3); | |
40 // SRGB is 7. | |
41 if (color_space != 7) { | |
42 // YUV range flag. | |
43 br->GetBit(); | |
44 if (profile == 1 || profile == 3) { | |
45 // Subsampling x. | |
46 br->GetBit(); | |
47 // Subsampling y. | |
48 br->GetBit(); | |
49 // Reserved. | |
50 if (br->GetBit()) { | |
51 LOG(LS_WARNING) << "Failed to get QP. Reserved bit set."; | |
52 return false; | |
53 } | |
54 } | |
55 } else { | |
56 if (profile == 1 || profile == 3) { | |
57 // Reserved. | |
58 if (br->GetBit()) { | |
59 LOG(LS_WARNING) << "Failed to get QP. Reserved bit set."; | |
60 return false; | |
61 } | |
62 } else { | |
63 LOG(LS_WARNING) << "Failed to get QP. 4:4:4 color not supported in " | |
64 "profile 0 or 2."; | |
65 return false; | |
66 } | |
67 } | |
68 | |
69 return true; | |
70 } | |
71 | |
72 static void VP9ReadFrameSize(VP9BitReader *const br) { | |
brandtr
2017/05/23 08:59:02
VP9ReadFrameSize(VP9BitReader* br)
jianj1
2017/05/23 17:37:30
Done.
| |
73 // Frame width. | |
74 br->GetValue(16); | |
75 // Frame height. | |
76 br->GetValue(16); | |
77 } | |
78 | |
79 static void VP9ReadRenderSize(VP9BitReader *const br) { | |
brandtr
2017/05/23 08:59:02
VP9ReadRenderSize(VP9BitReader* br)
jianj1
2017/05/23 17:37:30
Done.
| |
80 // Scaling. | |
81 if (br->GetBit()) { | |
82 // Render width. | |
83 br->GetValue(16); | |
84 // Render height. | |
85 br->GetValue(16); | |
86 } | |
87 } | |
88 | |
89 static void VP9ReadFrameSizeFromRefs(VP9BitReader *const br) { | |
brandtr
2017/05/23 08:59:02
VP9ReadFrameSizeFromRefs(VP9BitReader* br)
jianj1
2017/05/23 17:37:30
Done.
| |
90 int found_ref = 0; | |
91 for (size_t i = 0; i < kVp9NumRefsPerFrame; i++) { | |
92 // Size in refs. | |
93 found_ref = br->GetBit(); | |
94 if (found_ref) | |
95 break; | |
96 } | |
97 | |
98 if (!found_ref) | |
99 VP9ReadFrameSize(br); | |
100 | |
101 VP9ReadRenderSize(br); | |
102 } | |
103 | |
104 static void VP9ReadInterpolationFilter(VP9BitReader *const br) { | |
brandtr
2017/05/23 08:59:02
VP9ReadInterpolationFilter(VP9BitReader* br)
jianj1
2017/05/23 17:37:30
Done.
| |
105 if (br->GetBit()) | |
106 return; | |
107 | |
108 br->GetValue(2); | |
109 } | |
110 | |
111 static void VP9ReadLoopfilter(VP9BitReader *const br) { | |
brandtr
2017/05/23 08:59:02
VP9ReadLoopfilter(VP9BitReader* br)
jianj1
2017/05/23 17:37:29
Done.
| |
112 // Filter level. | |
113 br->GetValue(6); | |
114 // Sharpness level. | |
115 br->GetValue(3); | |
116 uint32_t mode_ref_delta_enabled = br->GetBit(); | |
117 if (mode_ref_delta_enabled) { | |
118 uint32_t mode_ref_delta_update = br->GetBit(); | |
119 if (mode_ref_delta_update) { | |
120 for (size_t i = 0; i < kVp9MaxRefLFDeltas; i++) { | |
121 if (br->GetBit()) | |
122 br->GetSignedValue(6); | |
123 } | |
124 for (size_t i = 0; i < kVp9MaxModeLFDeltas; i++) { | |
125 if (br->GetBit()) | |
126 br->GetSignedValue(6); | |
127 } | |
128 } | |
129 } | |
130 } | |
131 | |
132 bool GetQp(const uint8_t *buf, size_t length, int *qp) { | |
brandtr
2017/05/23 08:59:02
GetQp(const uint8_t* buf, size_t length, int* qp)
jianj1
2017/05/23 17:37:30
Done.
| |
133 VP9BitReader br(buf, length); | |
134 | |
135 // Frame marker. | |
136 if (br.GetValue(2) != 0x2) { | |
137 LOG(LS_WARNING) << "Failed to get QP. Frame marker should be 2."; | |
138 return false; | |
139 } | |
140 | |
141 // Profile. | |
142 uint8_t profile = VP9ReadProfile(&br); | |
143 if (profile > kVp9MaxProfile) { | |
144 LOG(LS_WARNING) << "Failed to get QP. Unsupported bitstream profile: " | |
145 << profile; | |
146 return false; | |
147 } | |
148 | |
149 // Show existing frame. | |
150 if (br.GetBit()) | |
151 return false; | |
152 | |
153 // Frame type: KEY_FRAME(0), INTER_FRAME(1). | |
154 uint8_t frame_type = br.GetBit(); | |
155 // Show frame. | |
156 uint8_t show_frame = br.GetBit(); | |
157 // Error resilient. | |
158 uint8_t error_resilient = br.GetBit(); | |
159 | |
160 if (!frame_type) { | |
161 // Sync code. | |
162 uint32_t sync_code = br.GetValue(24); | |
163 if (sync_code != 0x498342) { | |
164 LOG(LS_WARNING) << "Failed to get QP. Invalid sync code."; | |
165 return false; | |
166 } | |
167 | |
168 if (!VP9ReadColorConfig(&br, profile)) | |
169 return false; | |
170 | |
171 VP9ReadFrameSize(&br); | |
172 VP9ReadRenderSize(&br); | |
173 } else { | |
174 uint8_t intra_only = 0; | |
175 if (!show_frame) | |
176 intra_only = br.GetBit(); | |
177 | |
178 if (!error_resilient) | |
179 // Reset frame context. | |
180 br.GetValue(2); | |
181 | |
182 if (intra_only) { | |
183 // Sync code. | |
184 if (br.GetValue(24) != 0x498342) { | |
185 LOG(LS_WARNING) << "Failed to get QP. Invalid sync code."; | |
186 return false; | |
187 } | |
188 if (profile > 0) { | |
189 if (!VP9ReadColorConfig(&br, profile)) | |
190 return false; | |
191 } | |
192 // Refresh frame flags. | |
193 br.GetValue(8); | |
194 | |
195 VP9ReadFrameSize(&br); | |
196 VP9ReadRenderSize(&br); | |
197 } else { | |
198 // Refresh frame flags. | |
199 br.GetValue(8); | |
200 | |
201 for (size_t i = 0; i < kVp9NumRefsPerFrame; i++) { | |
202 // Ref frame index. | |
203 br.GetValue(3); | |
204 // Ref frame sign biases. | |
205 br.GetBit(); | |
206 } | |
207 | |
208 VP9ReadFrameSizeFromRefs(&br); | |
209 // Allow high precision mv. | |
210 br.GetBit(); | |
211 // Interpolation filter. | |
212 VP9ReadInterpolationFilter(&br); | |
213 } | |
214 } | |
215 | |
216 if (!error_resilient) { | |
217 // Refresh frame context. | |
218 br.GetBit(); | |
219 // Frame parallel decoding mode. | |
220 br.GetBit(); | |
221 } | |
222 | |
223 // Frame context index. | |
224 br.GetValue(2); | |
225 | |
226 VP9ReadLoopfilter(&br); | |
227 | |
228 // Base QP. | |
229 const int base_q0 = br.GetValue(8); | |
230 *qp = base_q0; | |
231 return true; | |
232 } | |
233 | |
234 } // namespace vp9 | |
235 | |
236 } // namespace webrtc | |
OLD | NEW |