xref: /aosp_15_r20/external/webrtc/modules/video_coding/utility/vp9_uncompressed_header_parser.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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 "absl/numeric/bits.h"
13 #include "absl/strings/string_view.h"
14 #include "rtc_base/bitstream_reader.h"
15 #include "rtc_base/logging.h"
16 #include "rtc_base/strings/string_builder.h"
17 
18 namespace webrtc {
19 namespace {
20 const size_t kVp9NumRefsPerFrame = 3;
21 const size_t kVp9MaxRefLFDeltas = 4;
22 const size_t kVp9MaxModeLFDeltas = 2;
23 const size_t kVp9MinTileWidthB64 = 4;
24 const size_t kVp9MaxTileWidthB64 = 64;
25 
Vp9ReadColorConfig(BitstreamReader & br,Vp9UncompressedHeader * frame_info)26 void Vp9ReadColorConfig(BitstreamReader& br,
27                         Vp9UncompressedHeader* frame_info) {
28   if (frame_info->profile == 2 || frame_info->profile == 3) {
29     frame_info->bit_detph =
30         br.Read<bool>() ? Vp9BitDept::k12Bit : Vp9BitDept::k10Bit;
31   } else {
32     frame_info->bit_detph = Vp9BitDept::k8Bit;
33   }
34 
35   frame_info->color_space = static_cast<Vp9ColorSpace>(br.ReadBits(3));
36 
37   if (frame_info->color_space != Vp9ColorSpace::CS_RGB) {
38     frame_info->color_range =
39         br.Read<bool>() ? Vp9ColorRange::kFull : Vp9ColorRange::kStudio;
40 
41     if (frame_info->profile == 1 || frame_info->profile == 3) {
42       static constexpr Vp9YuvSubsampling kSubSamplings[] = {
43           Vp9YuvSubsampling::k444, Vp9YuvSubsampling::k440,
44           Vp9YuvSubsampling::k422, Vp9YuvSubsampling::k420};
45       frame_info->sub_sampling = kSubSamplings[br.ReadBits(2)];
46 
47       if (br.Read<bool>()) {
48         RTC_LOG(LS_WARNING) << "Failed to parse header. Reserved bit set.";
49         br.Invalidate();
50         return;
51       }
52     } else {
53       // Profile 0 or 2.
54       frame_info->sub_sampling = Vp9YuvSubsampling::k420;
55     }
56   } else {
57     // SRGB
58     frame_info->color_range = Vp9ColorRange::kFull;
59     if (frame_info->profile == 1 || frame_info->profile == 3) {
60       frame_info->sub_sampling = Vp9YuvSubsampling::k444;
61       if (br.Read<bool>()) {
62         RTC_LOG(LS_WARNING) << "Failed to parse header. Reserved bit set.";
63         br.Invalidate();
64       }
65     } else {
66       RTC_LOG(LS_WARNING) << "Failed to parse header. 4:4:4 color not supported"
67                              " in profile 0 or 2.";
68       br.Invalidate();
69     }
70   }
71 }
72 
ReadRefreshFrameFlags(BitstreamReader & br,Vp9UncompressedHeader * frame_info)73 void ReadRefreshFrameFlags(BitstreamReader& br,
74                            Vp9UncompressedHeader* frame_info) {
75   // Refresh frame flags.
76   uint8_t flags = br.Read<uint8_t>();
77   for (int i = 0; i < 8; ++i) {
78     frame_info->updated_buffers.set(i, (flags & (0x01 << (7 - i))) != 0);
79   }
80 }
81 
Vp9ReadFrameSize(BitstreamReader & br,Vp9UncompressedHeader * frame_info)82 void Vp9ReadFrameSize(BitstreamReader& br, Vp9UncompressedHeader* frame_info) {
83   // 16 bits: frame (width|height) - 1.
84   frame_info->frame_width = br.Read<uint16_t>() + 1;
85   frame_info->frame_height = br.Read<uint16_t>() + 1;
86 }
87 
Vp9ReadRenderSize(size_t total_buffer_size_bits,BitstreamReader & br,Vp9UncompressedHeader * frame_info)88 void Vp9ReadRenderSize(size_t total_buffer_size_bits,
89                        BitstreamReader& br,
90                        Vp9UncompressedHeader* frame_info) {
91   // render_and_frame_size_different
92   if (br.Read<bool>()) {
93     frame_info->render_size_offset_bits =
94         total_buffer_size_bits - br.RemainingBitCount();
95     // 16 bits: render (width|height) - 1.
96     frame_info->render_width = br.Read<uint16_t>() + 1;
97     frame_info->render_height = br.Read<uint16_t>() + 1;
98   } else {
99     frame_info->render_height = frame_info->frame_height;
100     frame_info->render_width = frame_info->frame_width;
101   }
102 }
103 
Vp9ReadFrameSizeFromRefs(BitstreamReader & br,Vp9UncompressedHeader * frame_info)104 void Vp9ReadFrameSizeFromRefs(BitstreamReader& br,
105                               Vp9UncompressedHeader* frame_info) {
106   for (size_t i = 0; i < kVp9NumRefsPerFrame; i++) {
107     // Size in refs.
108     if (br.Read<bool>()) {
109       frame_info->infer_size_from_reference = frame_info->reference_buffers[i];
110       return;
111     }
112   }
113 
114   Vp9ReadFrameSize(br, frame_info);
115 }
116 
Vp9ReadLoopfilter(BitstreamReader & br)117 void Vp9ReadLoopfilter(BitstreamReader& br) {
118   // 6 bits: filter level.
119   // 3 bits: sharpness level.
120   br.ConsumeBits(9);
121 
122   if (!br.Read<bool>()) {  // mode_ref_delta_enabled
123     return;
124   }
125   if (!br.Read<bool>()) {  // mode_ref_delta_update
126     return;
127   }
128 
129   for (size_t i = 0; i < kVp9MaxRefLFDeltas; i++) {
130     if (br.Read<bool>()) {  // update_ref_delta
131       br.ConsumeBits(7);
132     }
133   }
134   for (size_t i = 0; i < kVp9MaxModeLFDeltas; i++) {
135     if (br.Read<bool>()) {  // update_mode_delta
136       br.ConsumeBits(7);
137     }
138   }
139 }
140 
Vp9ReadQp(BitstreamReader & br,Vp9UncompressedHeader * frame_info)141 void Vp9ReadQp(BitstreamReader& br, Vp9UncompressedHeader* frame_info) {
142   frame_info->base_qp = br.Read<uint8_t>();
143 
144   // yuv offsets
145   frame_info->is_lossless = frame_info->base_qp == 0;
146   for (int i = 0; i < 3; ++i) {
147     if (br.Read<bool>()) {  // if delta_coded
148       // delta_q is a signed integer with leading 4 bits containing absolute
149       // value and last bit containing sign. There are are two ways to represent
150       // zero with such encoding.
151       if ((br.ReadBits(5) & 0b1111'0) != 0) {  // delta_q
152         frame_info->is_lossless = false;
153       }
154     }
155   }
156 }
157 
Vp9ReadSegmentationParams(BitstreamReader & br,Vp9UncompressedHeader * frame_info)158 void Vp9ReadSegmentationParams(BitstreamReader& br,
159                                Vp9UncompressedHeader* frame_info) {
160   constexpr int kSegmentationFeatureBits[kVp9SegLvlMax] = {8, 6, 2, 0};
161   constexpr bool kSegmentationFeatureSigned[kVp9SegLvlMax] = {true, true, false,
162                                                               false};
163 
164   frame_info->segmentation_enabled = br.Read<bool>();
165   if (!frame_info->segmentation_enabled) {
166     return;
167   }
168 
169   if (br.Read<bool>()) {  // update_map
170     frame_info->segmentation_tree_probs.emplace();
171     for (int i = 0; i < 7; ++i) {
172       if (br.Read<bool>()) {
173         (*frame_info->segmentation_tree_probs)[i] = br.Read<uint8_t>();
174       } else {
175         (*frame_info->segmentation_tree_probs)[i] = 255;
176       }
177     }
178 
179     // temporal_update
180     frame_info->segmentation_pred_prob.emplace();
181     if (br.Read<bool>()) {
182       for (int i = 0; i < 3; ++i) {
183         if (br.Read<bool>()) {
184           (*frame_info->segmentation_pred_prob)[i] = br.Read<uint8_t>();
185         } else {
186           (*frame_info->segmentation_pred_prob)[i] = 255;
187         }
188       }
189     } else {
190       frame_info->segmentation_pred_prob->fill(255);
191     }
192   }
193 
194   if (br.Read<bool>()) {  // segmentation_update_data
195     frame_info->segmentation_is_delta = br.Read<bool>();
196     for (size_t i = 0; i < kVp9MaxSegments; ++i) {
197       for (size_t j = 0; j < kVp9SegLvlMax; ++j) {
198         if (!br.Read<bool>()) {  // feature_enabled
199           continue;
200         }
201         if (kSegmentationFeatureBits[j] == 0) {
202           // No feature bits used and no sign, just mark it and return.
203           frame_info->segmentation_features[i][j] = 1;
204           continue;
205         }
206         frame_info->segmentation_features[i][j] =
207             br.ReadBits(kSegmentationFeatureBits[j]);
208         if (kSegmentationFeatureSigned[j] && br.Read<bool>()) {
209           (*frame_info->segmentation_features[i][j]) *= -1;
210         }
211       }
212     }
213   }
214 }
215 
Vp9ReadTileInfo(BitstreamReader & br,Vp9UncompressedHeader * frame_info)216 void Vp9ReadTileInfo(BitstreamReader& br, Vp9UncompressedHeader* frame_info) {
217   size_t mi_cols = (frame_info->frame_width + 7) >> 3;
218   size_t sb64_cols = (mi_cols + 7) >> 3;
219 
220   size_t min_log2 = 0;
221   while ((kVp9MaxTileWidthB64 << min_log2) < sb64_cols) {
222     ++min_log2;
223   }
224 
225   size_t max_log2 = 1;
226   while ((sb64_cols >> max_log2) >= kVp9MinTileWidthB64) {
227     ++max_log2;
228   }
229   --max_log2;
230 
231   frame_info->tile_cols_log2 = min_log2;
232   while (frame_info->tile_cols_log2 < max_log2) {
233     if (br.Read<bool>()) {
234       ++frame_info->tile_cols_log2;
235     } else {
236       break;
237     }
238   }
239   frame_info->tile_rows_log2 = 0;
240   if (br.Read<bool>()) {
241     ++frame_info->tile_rows_log2;
242     if (br.Read<bool>()) {
243       ++frame_info->tile_rows_log2;
244     }
245   }
246 }
247 
248 const Vp9InterpolationFilter kLiteralToType[4] = {
249     Vp9InterpolationFilter::kEightTapSmooth, Vp9InterpolationFilter::kEightTap,
250     Vp9InterpolationFilter::kEightTapSharp, Vp9InterpolationFilter::kBilinear};
251 }  // namespace
252 
ToString() const253 std::string Vp9UncompressedHeader::ToString() const {
254   char buf[1024];
255   rtc::SimpleStringBuilder oss(buf);
256 
257   oss << "Vp9UncompressedHeader { "
258       << "profile = " << profile;
259 
260   if (show_existing_frame) {
261     oss << ", show_existing_frame = " << *show_existing_frame << " }";
262     return oss.str();
263   }
264 
265   oss << ", frame type = " << (is_keyframe ? "key" : "delta")
266       << ", show_frame = " << (show_frame ? "true" : "false")
267       << ", error_resilient = " << (error_resilient ? "true" : "false");
268 
269   oss << ", bit_depth = ";
270   switch (bit_detph) {
271     case Vp9BitDept::k8Bit:
272       oss << "8bit";
273       break;
274     case Vp9BitDept::k10Bit:
275       oss << "10bit";
276       break;
277     case Vp9BitDept::k12Bit:
278       oss << "12bit";
279       break;
280   }
281 
282   if (color_space) {
283     oss << ", color_space = ";
284     switch (*color_space) {
285       case Vp9ColorSpace::CS_UNKNOWN:
286         oss << "unknown";
287         break;
288       case Vp9ColorSpace::CS_BT_601:
289         oss << "CS_BT_601 Rec. ITU-R BT.601-7";
290         break;
291       case Vp9ColorSpace::CS_BT_709:
292         oss << "Rec. ITU-R BT.709-6";
293         break;
294       case Vp9ColorSpace::CS_SMPTE_170:
295         oss << "SMPTE-170";
296         break;
297       case Vp9ColorSpace::CS_SMPTE_240:
298         oss << "SMPTE-240";
299         break;
300       case Vp9ColorSpace::CS_BT_2020:
301         oss << "Rec. ITU-R BT.2020-2";
302         break;
303       case Vp9ColorSpace::CS_RESERVED:
304         oss << "Reserved";
305         break;
306       case Vp9ColorSpace::CS_RGB:
307         oss << "sRGB (IEC 61966-2-1)";
308         break;
309     }
310   }
311 
312   if (color_range) {
313     oss << ", color_range = ";
314     switch (*color_range) {
315       case Vp9ColorRange::kFull:
316         oss << "full";
317         break;
318       case Vp9ColorRange::kStudio:
319         oss << "studio";
320         break;
321     }
322   }
323 
324   if (sub_sampling) {
325     oss << ", sub_sampling = ";
326     switch (*sub_sampling) {
327       case Vp9YuvSubsampling::k444:
328         oss << "444";
329         break;
330       case Vp9YuvSubsampling::k440:
331         oss << "440";
332         break;
333       case Vp9YuvSubsampling::k422:
334         oss << "422";
335         break;
336       case Vp9YuvSubsampling::k420:
337         oss << "420";
338         break;
339     }
340   }
341 
342   if (infer_size_from_reference) {
343     oss << ", infer_frame_resolution_from = " << *infer_size_from_reference;
344   } else {
345     oss << ", frame_width = " << frame_width
346         << ", frame_height = " << frame_height;
347   }
348   if (render_width != 0 && render_height != 0) {
349     oss << ", render_width = " << render_width
350         << ", render_height = " << render_height;
351   }
352 
353   oss << ", base qp = " << base_qp;
354   if (reference_buffers[0] != -1) {
355     oss << ", last_buffer = " << reference_buffers[0];
356   }
357   if (reference_buffers[1] != -1) {
358     oss << ", golden_buffer = " << reference_buffers[1];
359   }
360   if (reference_buffers[2] != -1) {
361     oss << ", altref_buffer = " << reference_buffers[2];
362   }
363 
364   oss << ", updated buffers = { ";
365   bool first = true;
366   for (int i = 0; i < 8; ++i) {
367     if (updated_buffers.test(i)) {
368       if (first) {
369         first = false;
370       } else {
371         oss << ", ";
372       }
373       oss << i;
374     }
375   }
376   oss << " }";
377 
378   oss << ", compressed_header_size_bytes = " << compressed_header_size;
379 
380   oss << " }";
381   return oss.str();
382 }
383 
Parse(BitstreamReader & br,Vp9UncompressedHeader * frame_info,bool qp_only)384 void Parse(BitstreamReader& br,
385            Vp9UncompressedHeader* frame_info,
386            bool qp_only) {
387   const size_t total_buffer_size_bits = br.RemainingBitCount();
388 
389   // Frame marker.
390   if (br.ReadBits(2) != 0b10) {
391     RTC_LOG(LS_WARNING) << "Failed to parse header. Frame marker should be 2.";
392     br.Invalidate();
393     return;
394   }
395 
396   // Profile has low bit first.
397   frame_info->profile = br.ReadBit();
398   frame_info->profile |= br.ReadBit() << 1;
399   if (frame_info->profile > 2 && br.Read<bool>()) {
400     RTC_LOG(LS_WARNING)
401         << "Failed to parse header. Unsupported bitstream profile.";
402     br.Invalidate();
403     return;
404   }
405 
406   // Show existing frame.
407   if (br.Read<bool>()) {
408     frame_info->show_existing_frame = br.ReadBits(3);
409     return;
410   }
411 
412   // Frame type: KEY_FRAME(0), INTER_FRAME(1).
413   frame_info->is_keyframe = !br.Read<bool>();
414   frame_info->show_frame = br.Read<bool>();
415   frame_info->error_resilient = br.Read<bool>();
416 
417   if (frame_info->is_keyframe) {
418     if (br.ReadBits(24) != 0x498342) {
419       RTC_LOG(LS_WARNING) << "Failed to parse header. Invalid sync code.";
420       br.Invalidate();
421       return;
422     }
423 
424     Vp9ReadColorConfig(br, frame_info);
425     Vp9ReadFrameSize(br, frame_info);
426     Vp9ReadRenderSize(total_buffer_size_bits, br, frame_info);
427 
428     // Key-frames implicitly update all buffers.
429     frame_info->updated_buffers.set();
430   } else {
431     // Non-keyframe.
432     bool is_intra_only = false;
433     if (!frame_info->show_frame) {
434       is_intra_only = br.Read<bool>();
435     }
436     if (!frame_info->error_resilient) {
437       br.ConsumeBits(2);  // Reset frame context.
438     }
439 
440     if (is_intra_only) {
441       if (br.ReadBits(24) != 0x498342) {
442         RTC_LOG(LS_WARNING) << "Failed to parse header. Invalid sync code.";
443         br.Invalidate();
444         return;
445       }
446 
447       if (frame_info->profile > 0) {
448         Vp9ReadColorConfig(br, frame_info);
449       } else {
450         frame_info->color_space = Vp9ColorSpace::CS_BT_601;
451         frame_info->sub_sampling = Vp9YuvSubsampling::k420;
452         frame_info->bit_detph = Vp9BitDept::k8Bit;
453       }
454       frame_info->reference_buffers.fill(-1);
455       ReadRefreshFrameFlags(br, frame_info);
456       Vp9ReadFrameSize(br, frame_info);
457       Vp9ReadRenderSize(total_buffer_size_bits, br, frame_info);
458     } else {
459       ReadRefreshFrameFlags(br, frame_info);
460 
461       frame_info->reference_buffers_sign_bias[0] = false;
462       for (size_t i = 0; i < kVp9NumRefsPerFrame; i++) {
463         frame_info->reference_buffers[i] = br.ReadBits(3);
464         frame_info->reference_buffers_sign_bias[Vp9ReferenceFrame::kLast + i] =
465             br.Read<bool>();
466       }
467 
468       Vp9ReadFrameSizeFromRefs(br, frame_info);
469       Vp9ReadRenderSize(total_buffer_size_bits, br, frame_info);
470 
471       frame_info->allow_high_precision_mv = br.Read<bool>();
472 
473       // Interpolation filter.
474       if (br.Read<bool>()) {
475         frame_info->interpolation_filter = Vp9InterpolationFilter::kSwitchable;
476       } else {
477         frame_info->interpolation_filter = kLiteralToType[br.ReadBits(2)];
478       }
479     }
480   }
481 
482   if (!frame_info->error_resilient) {
483     // 1 bit: Refresh frame context.
484     // 1 bit: Frame parallel decoding mode.
485     br.ConsumeBits(2);
486   }
487 
488   // Frame context index.
489   frame_info->frame_context_idx = br.ReadBits(2);
490 
491   Vp9ReadLoopfilter(br);
492 
493   // Read base QP.
494   Vp9ReadQp(br, frame_info);
495 
496   if (qp_only) {
497     // Not interested in the rest of the header, return early.
498     return;
499   }
500 
501   Vp9ReadSegmentationParams(br, frame_info);
502   Vp9ReadTileInfo(br, frame_info);
503   frame_info->compressed_header_size = br.Read<uint16_t>();
504   frame_info->uncompressed_header_size =
505       (total_buffer_size_bits / 8) - (br.RemainingBitCount() / 8);
506 }
507 
ParseUncompressedVp9Header(rtc::ArrayView<const uint8_t> buf)508 absl::optional<Vp9UncompressedHeader> ParseUncompressedVp9Header(
509     rtc::ArrayView<const uint8_t> buf) {
510   BitstreamReader reader(buf);
511   Vp9UncompressedHeader frame_info;
512   Parse(reader, &frame_info, /*qp_only=*/false);
513   if (reader.Ok() && frame_info.frame_width > 0) {
514     return frame_info;
515   }
516   return absl::nullopt;
517 }
518 
519 namespace vp9 {
520 
GetQp(const uint8_t * buf,size_t length,int * qp)521 bool GetQp(const uint8_t* buf, size_t length, int* qp) {
522   BitstreamReader reader(rtc::MakeArrayView(buf, length));
523   Vp9UncompressedHeader frame_info;
524   Parse(reader, &frame_info, /*qp_only=*/true);
525   if (!reader.Ok()) {
526     return false;
527   }
528   *qp = frame_info.base_qp;
529   return true;
530 }
531 
532 }  // namespace vp9
533 }  // namespace webrtc
534