1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 // This file contains an implementation of a VP9 bitstream parser.
7 #include "media/filters/vp9_parser.h"
9 #include "base/logging.h"
13 // Helper function for Vp9Parser::ReadTiles. Defined as get_min_log2_tile_cols
15 int GetMinLog2TileCols(int sb64_cols
) {
16 const int kMaxTileWidthB64
= 64;
18 while ((kMaxTileWidthB64
<< min_log2
) < sb64_cols
)
23 // Helper function for Vp9Parser::ReadTiles. Defined as get_max_log2_tile_cols
25 int GetMaxLog2TileCols(int sb64_cols
) {
26 const int kMinTileWidthB64
= 4;
28 while ((sb64_cols
>> max_log2
) >= kMinTileWidthB64
)
37 Vp9Parser::Vp9Parser() : stream_(nullptr), size_(0) {
38 memset(&ref_slots_
, 0, sizeof(ref_slots_
));
41 uint8_t Vp9Parser::ReadProfile() {
45 if (reader_
.ReadBool())
47 if (reader_
.ReadBool())
49 if (profile
> 2 && reader_
.ReadBool())
54 bool Vp9Parser::VerifySyncCode() {
55 const int kSyncCode
= 0x498342;
56 if (reader_
.ReadLiteral(8 * 3) != kSyncCode
) {
57 DVLOG(1) << "Invalid frame sync code";
63 bool Vp9Parser::ReadBitDepthColorSpaceSampling(Vp9FrameHeader
* fhdr
) {
64 if (fhdr
->profile
== 2 || fhdr
->profile
== 3) {
65 fhdr
->bit_depth
= reader_
.ReadBool() ? 12 : 10;
70 fhdr
->color_space
= static_cast<Vp9ColorSpace
>(reader_
.ReadLiteral(3));
71 if (fhdr
->color_space
!= Vp9ColorSpace::SRGB
) {
72 fhdr
->yuv_range
= reader_
.ReadBool();
73 if (fhdr
->profile
== 1 || fhdr
->profile
== 3) {
74 fhdr
->subsampling_x
= reader_
.ReadBool() ? 1 : 0;
75 fhdr
->subsampling_y
= reader_
.ReadBool() ? 1 : 0;
76 if (fhdr
->subsampling_x
== 1 && fhdr
->subsampling_y
== 1) {
77 DVLOG(1) << "4:2:0 color not supported in profile 1 or 3";
80 bool reserved
= reader_
.ReadBool();
82 DVLOG(1) << "reserved bit set";
86 fhdr
->subsampling_x
= fhdr
->subsampling_y
= 1;
89 if (fhdr
->profile
== 1 || fhdr
->profile
== 3) {
90 fhdr
->subsampling_x
= fhdr
->subsampling_y
= 0;
92 bool reserved
= reader_
.ReadBool();
94 DVLOG(1) << "reserved bit set";
98 DVLOG(1) << "4:4:4 color not supported in profile 0 or 2";
106 void Vp9Parser::ReadFrameSize(Vp9FrameHeader
* fhdr
) {
107 fhdr
->width
= reader_
.ReadLiteral(16) + 1;
108 fhdr
->height
= reader_
.ReadLiteral(16) + 1;
111 bool Vp9Parser::ReadFrameSizeFromRefs(Vp9FrameHeader
* fhdr
) {
112 for (size_t i
= 0; i
< kVp9NumRefsPerFrame
; i
++) {
113 if (reader_
.ReadBool()) {
114 fhdr
->width
= ref_slots_
[i
].width
;
115 fhdr
->height
= ref_slots_
[i
].height
;
117 const int kMaxDimension
= 1 << 16;
118 if (fhdr
->width
== 0 || fhdr
->width
> kMaxDimension
||
119 fhdr
->height
== 0 || fhdr
->height
> kMaxDimension
) {
120 DVLOG(1) << "The size of reference frame is out of range: "
121 << ref_slots_
[i
].width
<< "," << ref_slots_
[i
].height
;
128 fhdr
->width
= reader_
.ReadLiteral(16) + 1;
129 fhdr
->height
= reader_
.ReadLiteral(16) + 1;
133 void Vp9Parser::ReadDisplayFrameSize(Vp9FrameHeader
* fhdr
) {
134 if (reader_
.ReadBool()) {
135 fhdr
->display_width
= reader_
.ReadLiteral(16) + 1;
136 fhdr
->display_height
= reader_
.ReadLiteral(16) + 1;
138 fhdr
->display_width
= fhdr
->width
;
139 fhdr
->display_height
= fhdr
->height
;
143 Vp9InterpFilter
Vp9Parser::ReadInterpFilter() {
144 if (reader_
.ReadBool())
145 return Vp9InterpFilter::INTERP_FILTER_SELECT
;
147 // The mapping table for next two bits.
148 const Vp9InterpFilter table
[] = {
149 Vp9InterpFilter::EIGHTTAP_SMOOTH
, Vp9InterpFilter::EIGHTTAP
,
150 Vp9InterpFilter::EIGHTTAP_SHARP
, Vp9InterpFilter::BILINEAR
,
152 return table
[reader_
.ReadLiteral(2)];
155 void Vp9Parser::ReadLoopFilter(Vp9LoopFilter
* loop_filter
) {
156 loop_filter
->filter_level
= reader_
.ReadLiteral(6);
157 loop_filter
->sharpness_level
= reader_
.ReadLiteral(3);
159 loop_filter
->mode_ref_delta_enabled
= reader_
.ReadBool();
160 if (loop_filter
->mode_ref_delta_enabled
) {
161 loop_filter
->mode_ref_delta_update
= reader_
.ReadBool();
162 if (loop_filter
->mode_ref_delta_update
) {
163 for (size_t i
= 0; i
< Vp9LoopFilter::kNumRefDeltas
; i
++) {
164 loop_filter
->update_ref_deltas
[i
] = reader_
.ReadBool();
165 if (loop_filter
->update_ref_deltas
[i
])
166 loop_filter
->ref_deltas
[i
] = reader_
.ReadSignedLiteral(6);
169 for (size_t i
= 0; i
< Vp9LoopFilter::kNumModeDeltas
; i
++) {
170 loop_filter
->update_mode_deltas
[i
] = reader_
.ReadBool();
171 if (loop_filter
->update_mode_deltas
[i
])
172 loop_filter
->mode_deltas
[i
] = reader_
.ReadLiteral(6);
178 void Vp9Parser::ReadQuantization(Vp9QuantizationParams
* quants
) {
179 quants
->base_qindex
= reader_
.ReadLiteral(8);
181 if (reader_
.ReadBool())
182 quants
->y_dc_delta
= reader_
.ReadSignedLiteral(4);
184 if (reader_
.ReadBool())
185 quants
->uv_ac_delta
= reader_
.ReadSignedLiteral(4);
187 if (reader_
.ReadBool())
188 quants
->uv_dc_delta
= reader_
.ReadSignedLiteral(4);
191 void Vp9Parser::ReadSegmentationMap(Vp9Segmentation
* segment
) {
192 for (size_t i
= 0; i
< Vp9Segmentation::kNumTreeProbs
; i
++) {
193 segment
->tree_probs
[i
] =
194 reader_
.ReadBool() ? reader_
.ReadLiteral(8) : kVp9MaxProb
;
197 for (size_t i
= 0; i
< Vp9Segmentation::kNumPredictionProbs
; i
++)
198 segment
->pred_probs
[i
] = kVp9MaxProb
;
200 segment
->temporal_update
= reader_
.ReadBool();
201 if (segment
->temporal_update
) {
202 for (size_t i
= 0; i
< Vp9Segmentation::kNumPredictionProbs
; i
++) {
203 if (reader_
.ReadBool())
204 segment
->pred_probs
[i
] = reader_
.ReadLiteral(8);
209 void Vp9Parser::ReadSegmentationData(Vp9Segmentation
* segment
) {
210 segment
->abs_delta
= reader_
.ReadBool();
212 const int kFeatureDataBits
[] = {7, 6, 2, 0};
213 const bool kFeatureDataSigned
[] = {true, true, false, false};
215 for (size_t i
= 0; i
< Vp9Segmentation::kNumSegments
; i
++) {
216 for (size_t j
= 0; j
< Vp9Segmentation::kNumFeatures
; j
++) {
218 segment
->feature_enabled
[i
][j
] = reader_
.ReadBool();
219 if (segment
->feature_enabled
[i
][j
]) {
220 data
= reader_
.ReadLiteral(kFeatureDataBits
[j
]);
221 if (kFeatureDataSigned
[j
])
222 if (reader_
.ReadBool())
225 segment
->feature_data
[i
][j
] = data
;
230 void Vp9Parser::ReadSegmentation(Vp9Segmentation
* segment
) {
231 segment
->enabled
= reader_
.ReadBool();
233 if (!segment
->enabled
) {
237 segment
->update_map
= reader_
.ReadBool();
238 if (segment
->update_map
)
239 ReadSegmentationMap(segment
);
241 segment
->update_data
= reader_
.ReadBool();
242 if (segment
->update_data
)
243 ReadSegmentationData(segment
);
246 void Vp9Parser::ReadTiles(Vp9FrameHeader
* fhdr
) {
247 int sb64_cols
= (fhdr
->width
+ 63) / 64;
249 int min_log2_tile_cols
= GetMinLog2TileCols(sb64_cols
);
250 int max_log2_tile_cols
= GetMaxLog2TileCols(sb64_cols
);
252 int max_ones
= max_log2_tile_cols
- min_log2_tile_cols
;
253 fhdr
->log2_tile_cols
= min_log2_tile_cols
;
254 while (max_ones
-- && reader_
.ReadBool())
255 fhdr
->log2_tile_cols
++;
257 if (reader_
.ReadBool())
258 fhdr
->log2_tile_rows
= reader_
.ReadLiteral(2) - 1;
261 bool Vp9Parser::ParseUncompressedHeader(Vp9FrameHeader
* fhdr
) {
262 reader_
.Initialize(stream_
, size_
);
265 if (reader_
.ReadLiteral(2) != 0x2)
268 fhdr
->profile
= ReadProfile();
269 if (fhdr
->profile
>= kVp9MaxProfile
) {
270 DVLOG(1) << "Unsupported bitstream profile";
274 fhdr
->show_existing_frame
= reader_
.ReadBool();
275 if (fhdr
->show_existing_frame
) {
276 fhdr
->frame_to_show
= reader_
.ReadLiteral(3);
277 fhdr
->show_frame
= true;
279 if (!reader_
.IsValid()) {
280 DVLOG(1) << "parser reads beyond the end of buffer";
283 fhdr
->uncompressed_header_size
= reader_
.GetBytesRead();
287 fhdr
->frame_type
= static_cast<Vp9FrameHeader::FrameType
>(reader_
.ReadBool());
288 fhdr
->show_frame
= reader_
.ReadBool();
289 fhdr
->error_resilient_mode
= reader_
.ReadBool();
291 if (fhdr
->IsKeyframe()) {
292 if (!VerifySyncCode())
295 if (!ReadBitDepthColorSpaceSampling(fhdr
))
298 for (size_t i
= 0; i
< kVp9NumRefFrames
; i
++)
299 fhdr
->refresh_flag
[i
] = true;
302 ReadDisplayFrameSize(fhdr
);
304 if (!fhdr
->show_frame
)
305 fhdr
->intra_only
= reader_
.ReadBool();
307 if (!fhdr
->error_resilient_mode
)
308 fhdr
->reset_context
= reader_
.ReadLiteral(2);
310 if (fhdr
->intra_only
) {
311 if (!VerifySyncCode())
314 if (fhdr
->profile
> 0) {
315 if (!ReadBitDepthColorSpaceSampling(fhdr
))
319 fhdr
->color_space
= Vp9ColorSpace::BT_601
;
320 fhdr
->subsampling_x
= fhdr
->subsampling_y
= 1;
323 for (size_t i
= 0; i
< kVp9NumRefFrames
; i
++)
324 fhdr
->refresh_flag
[i
] = reader_
.ReadBool();
326 ReadDisplayFrameSize(fhdr
);
328 for (size_t i
= 0; i
< kVp9NumRefFrames
; i
++)
329 fhdr
->refresh_flag
[i
] = reader_
.ReadBool();
331 for (size_t i
= 0; i
< kVp9NumRefsPerFrame
; i
++) {
332 fhdr
->frame_refs
[i
] = reader_
.ReadLiteral(kVp9NumRefFramesLog2
);
333 fhdr
->ref_sign_biases
[i
] = reader_
.ReadBool();
336 if (!ReadFrameSizeFromRefs(fhdr
))
338 ReadDisplayFrameSize(fhdr
);
340 fhdr
->allow_high_precision_mv
= reader_
.ReadBool();
341 fhdr
->interp_filter
= ReadInterpFilter();
345 if (fhdr
->error_resilient_mode
) {
346 fhdr
->frame_parallel_decoding_mode
= true;
348 fhdr
->refresh_frame_context
= reader_
.ReadBool();
349 fhdr
->frame_parallel_decoding_mode
= reader_
.ReadBool();
352 fhdr
->frame_context_idx
= reader_
.ReadLiteral(2);
354 ReadLoopFilter(&fhdr
->loop_filter
);
355 ReadQuantization(&fhdr
->quant_params
);
356 ReadSegmentation(&fhdr
->segment
);
360 fhdr
->first_partition_size
= reader_
.ReadLiteral(16);
361 if (fhdr
->first_partition_size
== 0) {
362 DVLOG(1) << "invalid header size";
366 if (!reader_
.IsValid()) {
367 DVLOG(1) << "parser reads beyond the end of buffer";
370 fhdr
->uncompressed_header_size
= reader_
.GetBytesRead();
375 void Vp9Parser::UpdateSlots(const Vp9FrameHeader
* fhdr
) {
376 for (size_t i
= 0; i
< kVp9NumRefFrames
; i
++) {
377 if (fhdr
->refresh_flag
[i
]) {
378 ref_slots_
[i
].width
= fhdr
->width
;
379 ref_slots_
[i
].height
= fhdr
->height
;
384 bool Vp9Parser::ParseFrame(const uint8_t* stream
,
386 Vp9FrameHeader
* fhdr
) {
390 memset(fhdr
, 0, sizeof(*fhdr
));
392 if (!ParseUncompressedHeader(fhdr
))