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