xref: /aosp_15_r20/external/libwebm/common/vp9_header_parser.cc (revision 103e46e4cd4b6efcf6001f23fa8665fb110abf8d)
1*103e46e4SHarish Mahendrakar // Copyright (c) 2016 The WebM project authors. All Rights Reserved.
2*103e46e4SHarish Mahendrakar //
3*103e46e4SHarish Mahendrakar // Use of this source code is governed by a BSD-style license
4*103e46e4SHarish Mahendrakar // that can be found in the LICENSE file in the root of the source
5*103e46e4SHarish Mahendrakar // tree. An additional intellectual property rights grant can be found
6*103e46e4SHarish Mahendrakar // in the file PATENTS.  All contributing project authors may
7*103e46e4SHarish Mahendrakar // be found in the AUTHORS file in the root of the source tree.
8*103e46e4SHarish Mahendrakar #include "common/vp9_header_parser.h"
9*103e46e4SHarish Mahendrakar 
10*103e46e4SHarish Mahendrakar #include <stdio.h>
11*103e46e4SHarish Mahendrakar 
12*103e46e4SHarish Mahendrakar namespace vp9_parser {
13*103e46e4SHarish Mahendrakar 
SetFrame(const uint8_t * frame,size_t length)14*103e46e4SHarish Mahendrakar bool Vp9HeaderParser::SetFrame(const uint8_t* frame, size_t length) {
15*103e46e4SHarish Mahendrakar   if (!frame || length == 0)
16*103e46e4SHarish Mahendrakar     return false;
17*103e46e4SHarish Mahendrakar 
18*103e46e4SHarish Mahendrakar   frame_ = frame;
19*103e46e4SHarish Mahendrakar   frame_size_ = length;
20*103e46e4SHarish Mahendrakar   bit_offset_ = 0;
21*103e46e4SHarish Mahendrakar   profile_ = -1;
22*103e46e4SHarish Mahendrakar   show_existing_frame_ = 0;
23*103e46e4SHarish Mahendrakar   key_ = 0;
24*103e46e4SHarish Mahendrakar   altref_ = 0;
25*103e46e4SHarish Mahendrakar   error_resilient_mode_ = 0;
26*103e46e4SHarish Mahendrakar   intra_only_ = 0;
27*103e46e4SHarish Mahendrakar   reset_frame_context_ = 0;
28*103e46e4SHarish Mahendrakar   color_space_ = 0;
29*103e46e4SHarish Mahendrakar   color_range_ = 0;
30*103e46e4SHarish Mahendrakar   subsampling_x_ = 0;
31*103e46e4SHarish Mahendrakar   subsampling_y_ = 0;
32*103e46e4SHarish Mahendrakar   refresh_frame_flags_ = 0;
33*103e46e4SHarish Mahendrakar   return true;
34*103e46e4SHarish Mahendrakar }
35*103e46e4SHarish Mahendrakar 
ParseUncompressedHeader(const uint8_t * frame,size_t length)36*103e46e4SHarish Mahendrakar bool Vp9HeaderParser::ParseUncompressedHeader(const uint8_t* frame,
37*103e46e4SHarish Mahendrakar                                               size_t length) {
38*103e46e4SHarish Mahendrakar   if (!SetFrame(frame, length))
39*103e46e4SHarish Mahendrakar     return false;
40*103e46e4SHarish Mahendrakar   const int frame_marker = VpxReadLiteral(2);
41*103e46e4SHarish Mahendrakar   if (frame_marker != kVp9FrameMarker) {
42*103e46e4SHarish Mahendrakar     fprintf(stderr, "Invalid VP9 frame_marker:%d\n", frame_marker);
43*103e46e4SHarish Mahendrakar     return false;
44*103e46e4SHarish Mahendrakar   }
45*103e46e4SHarish Mahendrakar 
46*103e46e4SHarish Mahendrakar   profile_ = ReadBit();
47*103e46e4SHarish Mahendrakar   profile_ |= ReadBit() << 1;
48*103e46e4SHarish Mahendrakar   if (profile_ > 2)
49*103e46e4SHarish Mahendrakar     profile_ += ReadBit();
50*103e46e4SHarish Mahendrakar 
51*103e46e4SHarish Mahendrakar   // TODO(fgalligan): Decide how to handle show existing frames.
52*103e46e4SHarish Mahendrakar   show_existing_frame_ = ReadBit();
53*103e46e4SHarish Mahendrakar   if (show_existing_frame_)
54*103e46e4SHarish Mahendrakar     return true;
55*103e46e4SHarish Mahendrakar 
56*103e46e4SHarish Mahendrakar   key_ = !ReadBit();
57*103e46e4SHarish Mahendrakar   altref_ = !ReadBit();
58*103e46e4SHarish Mahendrakar   error_resilient_mode_ = ReadBit();
59*103e46e4SHarish Mahendrakar   if (key_) {
60*103e46e4SHarish Mahendrakar     if (!ValidateVp9SyncCode()) {
61*103e46e4SHarish Mahendrakar       fprintf(stderr, "Invalid Sync code!\n");
62*103e46e4SHarish Mahendrakar       return false;
63*103e46e4SHarish Mahendrakar     }
64*103e46e4SHarish Mahendrakar 
65*103e46e4SHarish Mahendrakar     ParseColorSpace();
66*103e46e4SHarish Mahendrakar     ParseFrameResolution();
67*103e46e4SHarish Mahendrakar     ParseFrameParallelMode();
68*103e46e4SHarish Mahendrakar     ParseTileInfo();
69*103e46e4SHarish Mahendrakar   } else {
70*103e46e4SHarish Mahendrakar     intra_only_ = altref_ ? ReadBit() : 0;
71*103e46e4SHarish Mahendrakar     reset_frame_context_ = error_resilient_mode_ ? 0 : VpxReadLiteral(2);
72*103e46e4SHarish Mahendrakar     if (intra_only_) {
73*103e46e4SHarish Mahendrakar       if (!ValidateVp9SyncCode()) {
74*103e46e4SHarish Mahendrakar         fprintf(stderr, "Invalid Sync code!\n");
75*103e46e4SHarish Mahendrakar         return false;
76*103e46e4SHarish Mahendrakar       }
77*103e46e4SHarish Mahendrakar 
78*103e46e4SHarish Mahendrakar       if (profile_ > 0) {
79*103e46e4SHarish Mahendrakar         ParseColorSpace();
80*103e46e4SHarish Mahendrakar       } else {
81*103e46e4SHarish Mahendrakar         // NOTE: The intra-only frame header does not include the specification
82*103e46e4SHarish Mahendrakar         // of either the color format or color sub-sampling in profile 0. VP9
83*103e46e4SHarish Mahendrakar         // specifies that the default color format should be YUV 4:2:0 in this
84*103e46e4SHarish Mahendrakar         // case (normative).
85*103e46e4SHarish Mahendrakar         color_space_ = kVpxCsBt601;
86*103e46e4SHarish Mahendrakar         color_range_ = kVpxCrStudioRange;
87*103e46e4SHarish Mahendrakar         subsampling_y_ = subsampling_x_ = 1;
88*103e46e4SHarish Mahendrakar         bit_depth_ = 8;
89*103e46e4SHarish Mahendrakar       }
90*103e46e4SHarish Mahendrakar 
91*103e46e4SHarish Mahendrakar       refresh_frame_flags_ = VpxReadLiteral(kRefFrames);
92*103e46e4SHarish Mahendrakar       ParseFrameResolution();
93*103e46e4SHarish Mahendrakar     } else {
94*103e46e4SHarish Mahendrakar       refresh_frame_flags_ = VpxReadLiteral(kRefFrames);
95*103e46e4SHarish Mahendrakar       for (int i = 0; i < kRefsPerFrame; ++i) {
96*103e46e4SHarish Mahendrakar         VpxReadLiteral(kRefFrames_LOG2);  // Consume ref.
97*103e46e4SHarish Mahendrakar         ReadBit();  // Consume ref sign bias.
98*103e46e4SHarish Mahendrakar       }
99*103e46e4SHarish Mahendrakar 
100*103e46e4SHarish Mahendrakar       bool found = false;
101*103e46e4SHarish Mahendrakar       for (int i = 0; i < kRefsPerFrame; ++i) {
102*103e46e4SHarish Mahendrakar         if (ReadBit()) {
103*103e46e4SHarish Mahendrakar           // Found previous reference, width and height did not change since
104*103e46e4SHarish Mahendrakar           // last frame.
105*103e46e4SHarish Mahendrakar           found = true;
106*103e46e4SHarish Mahendrakar           break;
107*103e46e4SHarish Mahendrakar         }
108*103e46e4SHarish Mahendrakar       }
109*103e46e4SHarish Mahendrakar 
110*103e46e4SHarish Mahendrakar       if (!found)
111*103e46e4SHarish Mahendrakar         ParseFrameResolution();
112*103e46e4SHarish Mahendrakar     }
113*103e46e4SHarish Mahendrakar   }
114*103e46e4SHarish Mahendrakar   return true;
115*103e46e4SHarish Mahendrakar }
116*103e46e4SHarish Mahendrakar 
ReadBit()117*103e46e4SHarish Mahendrakar int Vp9HeaderParser::ReadBit() {
118*103e46e4SHarish Mahendrakar   const size_t off = bit_offset_;
119*103e46e4SHarish Mahendrakar   const size_t byte_offset = off >> 3;
120*103e46e4SHarish Mahendrakar   const int bit_shift = 7 - static_cast<int>(off & 0x7);
121*103e46e4SHarish Mahendrakar   if (byte_offset < frame_size_) {
122*103e46e4SHarish Mahendrakar     const int bit = (frame_[byte_offset] >> bit_shift) & 1;
123*103e46e4SHarish Mahendrakar     bit_offset_++;
124*103e46e4SHarish Mahendrakar     return bit;
125*103e46e4SHarish Mahendrakar   } else {
126*103e46e4SHarish Mahendrakar     return 0;
127*103e46e4SHarish Mahendrakar   }
128*103e46e4SHarish Mahendrakar }
129*103e46e4SHarish Mahendrakar 
VpxReadLiteral(int bits)130*103e46e4SHarish Mahendrakar int Vp9HeaderParser::VpxReadLiteral(int bits) {
131*103e46e4SHarish Mahendrakar   int value = 0;
132*103e46e4SHarish Mahendrakar   for (int bit = bits - 1; bit >= 0; --bit)
133*103e46e4SHarish Mahendrakar     value |= ReadBit() << bit;
134*103e46e4SHarish Mahendrakar   return value;
135*103e46e4SHarish Mahendrakar }
136*103e46e4SHarish Mahendrakar 
ValidateVp9SyncCode()137*103e46e4SHarish Mahendrakar bool Vp9HeaderParser::ValidateVp9SyncCode() {
138*103e46e4SHarish Mahendrakar   const int sync_code_0 = VpxReadLiteral(8);
139*103e46e4SHarish Mahendrakar   const int sync_code_1 = VpxReadLiteral(8);
140*103e46e4SHarish Mahendrakar   const int sync_code_2 = VpxReadLiteral(8);
141*103e46e4SHarish Mahendrakar   return (sync_code_0 == 0x49 && sync_code_1 == 0x83 && sync_code_2 == 0x42);
142*103e46e4SHarish Mahendrakar }
143*103e46e4SHarish Mahendrakar 
ParseColorSpace()144*103e46e4SHarish Mahendrakar void Vp9HeaderParser::ParseColorSpace() {
145*103e46e4SHarish Mahendrakar   bit_depth_ = 0;
146*103e46e4SHarish Mahendrakar   if (profile_ >= 2)
147*103e46e4SHarish Mahendrakar     bit_depth_ = ReadBit() ? 12 : 10;
148*103e46e4SHarish Mahendrakar   else
149*103e46e4SHarish Mahendrakar     bit_depth_ = 8;
150*103e46e4SHarish Mahendrakar   color_space_ = VpxReadLiteral(3);
151*103e46e4SHarish Mahendrakar   if (color_space_ != kVpxCsSrgb) {
152*103e46e4SHarish Mahendrakar     color_range_ = ReadBit();
153*103e46e4SHarish Mahendrakar     if (profile_ == 1 || profile_ == 3) {
154*103e46e4SHarish Mahendrakar       subsampling_x_ = ReadBit();
155*103e46e4SHarish Mahendrakar       subsampling_y_ = ReadBit();
156*103e46e4SHarish Mahendrakar       ReadBit();
157*103e46e4SHarish Mahendrakar     } else {
158*103e46e4SHarish Mahendrakar       subsampling_y_ = subsampling_x_ = 1;
159*103e46e4SHarish Mahendrakar     }
160*103e46e4SHarish Mahendrakar   } else {
161*103e46e4SHarish Mahendrakar     color_range_ = kVpxCrFullRange;
162*103e46e4SHarish Mahendrakar     if (profile_ == 1 || profile_ == 3) {
163*103e46e4SHarish Mahendrakar       subsampling_y_ = subsampling_x_ = 0;
164*103e46e4SHarish Mahendrakar       ReadBit();
165*103e46e4SHarish Mahendrakar     }
166*103e46e4SHarish Mahendrakar   }
167*103e46e4SHarish Mahendrakar }
168*103e46e4SHarish Mahendrakar 
ParseFrameResolution()169*103e46e4SHarish Mahendrakar void Vp9HeaderParser::ParseFrameResolution() {
170*103e46e4SHarish Mahendrakar   width_ = VpxReadLiteral(16) + 1;
171*103e46e4SHarish Mahendrakar   height_ = VpxReadLiteral(16) + 1;
172*103e46e4SHarish Mahendrakar   if (ReadBit()) {
173*103e46e4SHarish Mahendrakar     display_width_ = VpxReadLiteral(16) + 1;
174*103e46e4SHarish Mahendrakar     display_height_ = VpxReadLiteral(16) + 1;
175*103e46e4SHarish Mahendrakar   } else {
176*103e46e4SHarish Mahendrakar     display_width_ = width_;
177*103e46e4SHarish Mahendrakar     display_height_ = height_;
178*103e46e4SHarish Mahendrakar   }
179*103e46e4SHarish Mahendrakar }
180*103e46e4SHarish Mahendrakar 
ParseFrameParallelMode()181*103e46e4SHarish Mahendrakar void Vp9HeaderParser::ParseFrameParallelMode() {
182*103e46e4SHarish Mahendrakar   if (!error_resilient_mode_) {
183*103e46e4SHarish Mahendrakar     ReadBit();  // Consume refresh frame context
184*103e46e4SHarish Mahendrakar     frame_parallel_mode_ = ReadBit();
185*103e46e4SHarish Mahendrakar   } else {
186*103e46e4SHarish Mahendrakar     frame_parallel_mode_ = 1;
187*103e46e4SHarish Mahendrakar   }
188*103e46e4SHarish Mahendrakar }
189*103e46e4SHarish Mahendrakar 
ParseTileInfo()190*103e46e4SHarish Mahendrakar void Vp9HeaderParser::ParseTileInfo() {
191*103e46e4SHarish Mahendrakar   VpxReadLiteral(2);  // Consume frame context index
192*103e46e4SHarish Mahendrakar 
193*103e46e4SHarish Mahendrakar   // loopfilter
194*103e46e4SHarish Mahendrakar   VpxReadLiteral(6);  // Consume filter level
195*103e46e4SHarish Mahendrakar   VpxReadLiteral(3);  // Consume sharpness level
196*103e46e4SHarish Mahendrakar 
197*103e46e4SHarish Mahendrakar   const bool mode_ref_delta_enabled = ReadBit();
198*103e46e4SHarish Mahendrakar   if (mode_ref_delta_enabled) {
199*103e46e4SHarish Mahendrakar     const bool mode_ref_delta_update = ReadBit();
200*103e46e4SHarish Mahendrakar     if (mode_ref_delta_update) {
201*103e46e4SHarish Mahendrakar       const int kMaxRefLFDeltas = 4;
202*103e46e4SHarish Mahendrakar       for (int i = 0; i < kMaxRefLFDeltas; ++i) {
203*103e46e4SHarish Mahendrakar         if (ReadBit())
204*103e46e4SHarish Mahendrakar           VpxReadLiteral(7);  // Consume ref_deltas + sign
205*103e46e4SHarish Mahendrakar       }
206*103e46e4SHarish Mahendrakar 
207*103e46e4SHarish Mahendrakar       const int kMaxModeDeltas = 2;
208*103e46e4SHarish Mahendrakar       for (int i = 0; i < kMaxModeDeltas; ++i) {
209*103e46e4SHarish Mahendrakar         if (ReadBit())
210*103e46e4SHarish Mahendrakar           VpxReadLiteral(7);  // Consume mode_delta + sign
211*103e46e4SHarish Mahendrakar       }
212*103e46e4SHarish Mahendrakar     }
213*103e46e4SHarish Mahendrakar   }
214*103e46e4SHarish Mahendrakar 
215*103e46e4SHarish Mahendrakar   // quantization
216*103e46e4SHarish Mahendrakar   VpxReadLiteral(8);  // Consume base_q
217*103e46e4SHarish Mahendrakar   SkipDeltaQ();  // y dc
218*103e46e4SHarish Mahendrakar   SkipDeltaQ();  // uv ac
219*103e46e4SHarish Mahendrakar   SkipDeltaQ();  // uv dc
220*103e46e4SHarish Mahendrakar 
221*103e46e4SHarish Mahendrakar   // segmentation
222*103e46e4SHarish Mahendrakar   const bool segmentation_enabled = ReadBit();
223*103e46e4SHarish Mahendrakar   if (!segmentation_enabled) {
224*103e46e4SHarish Mahendrakar     const int aligned_width = AlignPowerOfTwo(width_, kMiSizeLog2);
225*103e46e4SHarish Mahendrakar     const int mi_cols = aligned_width >> kMiSizeLog2;
226*103e46e4SHarish Mahendrakar     const int aligned_mi_cols = AlignPowerOfTwo(mi_cols, kMiSizeLog2);
227*103e46e4SHarish Mahendrakar     const int sb_cols = aligned_mi_cols >> 3;  // to_sbs(mi_cols);
228*103e46e4SHarish Mahendrakar     int min_log2_n_tiles, max_log2_n_tiles;
229*103e46e4SHarish Mahendrakar 
230*103e46e4SHarish Mahendrakar     for (max_log2_n_tiles = 0;
231*103e46e4SHarish Mahendrakar          (sb_cols >> max_log2_n_tiles) >= kMinTileWidthB64;
232*103e46e4SHarish Mahendrakar          max_log2_n_tiles++) {
233*103e46e4SHarish Mahendrakar     }
234*103e46e4SHarish Mahendrakar     max_log2_n_tiles--;
235*103e46e4SHarish Mahendrakar     if (max_log2_n_tiles < 0)
236*103e46e4SHarish Mahendrakar       max_log2_n_tiles = 0;
237*103e46e4SHarish Mahendrakar 
238*103e46e4SHarish Mahendrakar     for (min_log2_n_tiles = 0; (kMaxTileWidthB64 << min_log2_n_tiles) < sb_cols;
239*103e46e4SHarish Mahendrakar          min_log2_n_tiles++) {
240*103e46e4SHarish Mahendrakar     }
241*103e46e4SHarish Mahendrakar 
242*103e46e4SHarish Mahendrakar     // columns
243*103e46e4SHarish Mahendrakar     const int max_log2_tile_cols = max_log2_n_tiles;
244*103e46e4SHarish Mahendrakar     const int min_log2_tile_cols = min_log2_n_tiles;
245*103e46e4SHarish Mahendrakar     int max_ones = max_log2_tile_cols - min_log2_tile_cols;
246*103e46e4SHarish Mahendrakar     int log2_tile_cols = min_log2_tile_cols;
247*103e46e4SHarish Mahendrakar     while (max_ones-- && ReadBit())
248*103e46e4SHarish Mahendrakar       log2_tile_cols++;
249*103e46e4SHarish Mahendrakar 
250*103e46e4SHarish Mahendrakar     // rows
251*103e46e4SHarish Mahendrakar     int log2_tile_rows = ReadBit();
252*103e46e4SHarish Mahendrakar     if (log2_tile_rows)
253*103e46e4SHarish Mahendrakar       log2_tile_rows += ReadBit();
254*103e46e4SHarish Mahendrakar 
255*103e46e4SHarish Mahendrakar     row_tiles_ = 1 << log2_tile_rows;
256*103e46e4SHarish Mahendrakar     column_tiles_ = 1 << log2_tile_cols;
257*103e46e4SHarish Mahendrakar   }
258*103e46e4SHarish Mahendrakar }
259*103e46e4SHarish Mahendrakar 
SkipDeltaQ()260*103e46e4SHarish Mahendrakar void Vp9HeaderParser::SkipDeltaQ() {
261*103e46e4SHarish Mahendrakar   if (ReadBit())
262*103e46e4SHarish Mahendrakar     VpxReadLiteral(4);
263*103e46e4SHarish Mahendrakar }
264*103e46e4SHarish Mahendrakar 
AlignPowerOfTwo(int value,int n)265*103e46e4SHarish Mahendrakar int Vp9HeaderParser::AlignPowerOfTwo(int value, int n) {
266*103e46e4SHarish Mahendrakar   return (((value) + ((1 << (n)) - 1)) & ~((1 << (n)) - 1));
267*103e46e4SHarish Mahendrakar }
268*103e46e4SHarish Mahendrakar 
269*103e46e4SHarish Mahendrakar }  // namespace vp9_parser
270