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 if (ReadBit()) {
173 display_width_ = VpxReadLiteral(16) + 1;
174 display_height_ = VpxReadLiteral(16) + 1;
175 } else {
176 display_width_ = width_;
177 display_height_ = height_;
178 }
179 }
180
ParseFrameParallelMode()181 void Vp9HeaderParser::ParseFrameParallelMode() {
182 if (!error_resilient_mode_) {
183 ReadBit(); // Consume refresh frame context
184 frame_parallel_mode_ = ReadBit();
185 } else {
186 frame_parallel_mode_ = 1;
187 }
188 }
189
ParseTileInfo()190 void Vp9HeaderParser::ParseTileInfo() {
191 VpxReadLiteral(2); // Consume frame context index
192
193 // loopfilter
194 VpxReadLiteral(6); // Consume filter level
195 VpxReadLiteral(3); // Consume sharpness level
196
197 const bool mode_ref_delta_enabled = ReadBit();
198 if (mode_ref_delta_enabled) {
199 const bool mode_ref_delta_update = ReadBit();
200 if (mode_ref_delta_update) {
201 const int kMaxRefLFDeltas = 4;
202 for (int i = 0; i < kMaxRefLFDeltas; ++i) {
203 if (ReadBit())
204 VpxReadLiteral(7); // Consume ref_deltas + sign
205 }
206
207 const int kMaxModeDeltas = 2;
208 for (int i = 0; i < kMaxModeDeltas; ++i) {
209 if (ReadBit())
210 VpxReadLiteral(7); // Consume mode_delta + sign
211 }
212 }
213 }
214
215 // quantization
216 VpxReadLiteral(8); // Consume base_q
217 SkipDeltaQ(); // y dc
218 SkipDeltaQ(); // uv ac
219 SkipDeltaQ(); // uv dc
220
221 // segmentation
222 const bool segmentation_enabled = ReadBit();
223 if (!segmentation_enabled) {
224 const int aligned_width = AlignPowerOfTwo(width_, kMiSizeLog2);
225 const int mi_cols = aligned_width >> kMiSizeLog2;
226 const int aligned_mi_cols = AlignPowerOfTwo(mi_cols, kMiSizeLog2);
227 const int sb_cols = aligned_mi_cols >> 3; // to_sbs(mi_cols);
228 int min_log2_n_tiles, max_log2_n_tiles;
229
230 for (max_log2_n_tiles = 0;
231 (sb_cols >> max_log2_n_tiles) >= kMinTileWidthB64;
232 max_log2_n_tiles++) {
233 }
234 max_log2_n_tiles--;
235 if (max_log2_n_tiles < 0)
236 max_log2_n_tiles = 0;
237
238 for (min_log2_n_tiles = 0; (kMaxTileWidthB64 << min_log2_n_tiles) < sb_cols;
239 min_log2_n_tiles++) {
240 }
241
242 // columns
243 const int max_log2_tile_cols = max_log2_n_tiles;
244 const int min_log2_tile_cols = min_log2_n_tiles;
245 int max_ones = max_log2_tile_cols - min_log2_tile_cols;
246 int log2_tile_cols = min_log2_tile_cols;
247 while (max_ones-- && ReadBit())
248 log2_tile_cols++;
249
250 // rows
251 int log2_tile_rows = ReadBit();
252 if (log2_tile_rows)
253 log2_tile_rows += ReadBit();
254
255 row_tiles_ = 1 << log2_tile_rows;
256 column_tiles_ = 1 << log2_tile_cols;
257 }
258 }
259
SkipDeltaQ()260 void Vp9HeaderParser::SkipDeltaQ() {
261 if (ReadBit())
262 VpxReadLiteral(4);
263 }
264
AlignPowerOfTwo(int value,int n)265 int Vp9HeaderParser::AlignPowerOfTwo(int value, int n) {
266 return (((value) + ((1 << (n)) - 1)) & ~((1 << (n)) - 1));
267 }
268
269 } // namespace vp9_parser
270