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