• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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