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.
4 //
5 // This file contains an implementation of a VP9 bitstream parser.
6 //
7 // VERBOSE level:
8 // 1 something wrong in bitstream
9 // 2 parsing steps
10 // 3 parsed values (selected)
11
12 #include "vp9_parser.h"
13
14 #include <algorithm>
15
16 #include "base/bind.h"
17 #include "base/logging.h"
18 #include "base/macros.h"
19 #include "base/numerics/safe_conversions.h"
20 #include "vp9_compressed_header_parser.h"
21 #include "vp9_uncompressed_header_parser.h"
22
23 namespace media {
24
IsKeyframe() const25 bool Vp9FrameHeader::IsKeyframe() const {
26 // When show_existing_frame is true, the frame header does not precede an
27 // actual frame to be decoded, so frame_type does not apply (and is not read
28 // from the stream).
29 return !show_existing_frame && frame_type == KEYFRAME;
30 }
31
IsIntra() const32 bool Vp9FrameHeader::IsIntra() const {
33 return !show_existing_frame && (frame_type == KEYFRAME || intra_only);
34 }
35
FrameInfo(const uint8_t * ptr,off_t size)36 Vp9Parser::FrameInfo::FrameInfo(const uint8_t* ptr, off_t size)
37 : ptr(ptr), size(size) {}
38
IsValid() const39 bool Vp9FrameContext::IsValid() const {
40 // probs should be in [1, 255] range.
41 static_assert(sizeof(Vp9Prob) == 1,
42 "following checks assuming Vp9Prob is single byte");
43 if (memchr(tx_probs_8x8, 0, sizeof(tx_probs_8x8)))
44 return false;
45 if (memchr(tx_probs_16x16, 0, sizeof(tx_probs_16x16)))
46 return false;
47 if (memchr(tx_probs_32x32, 0, sizeof(tx_probs_32x32)))
48 return false;
49
50 for (auto& a : coef_probs) {
51 for (auto& ai : a) {
52 for (auto& aj : ai) {
53 for (auto& ak : aj) {
54 int max_l = (ak == aj[0]) ? 3 : 6;
55 for (int l = 0; l < max_l; l++) {
56 for (auto& x : ak[l]) {
57 if (x == 0)
58 return false;
59 }
60 }
61 }
62 }
63 }
64 }
65 if (memchr(skip_prob, 0, sizeof(skip_prob)))
66 return false;
67 if (memchr(inter_mode_probs, 0, sizeof(inter_mode_probs)))
68 return false;
69 if (memchr(interp_filter_probs, 0, sizeof(interp_filter_probs)))
70 return false;
71 if (memchr(is_inter_prob, 0, sizeof(is_inter_prob)))
72 return false;
73 if (memchr(comp_mode_prob, 0, sizeof(comp_mode_prob)))
74 return false;
75 if (memchr(single_ref_prob, 0, sizeof(single_ref_prob)))
76 return false;
77 if (memchr(comp_ref_prob, 0, sizeof(comp_ref_prob)))
78 return false;
79 if (memchr(y_mode_probs, 0, sizeof(y_mode_probs)))
80 return false;
81 if (memchr(uv_mode_probs, 0, sizeof(uv_mode_probs)))
82 return false;
83 if (memchr(partition_probs, 0, sizeof(partition_probs)))
84 return false;
85 if (memchr(mv_joint_probs, 0, sizeof(mv_joint_probs)))
86 return false;
87 if (memchr(mv_sign_prob, 0, sizeof(mv_sign_prob)))
88 return false;
89 if (memchr(mv_class_probs, 0, sizeof(mv_class_probs)))
90 return false;
91 if (memchr(mv_class0_bit_prob, 0, sizeof(mv_class0_bit_prob)))
92 return false;
93 if (memchr(mv_bits_prob, 0, sizeof(mv_bits_prob)))
94 return false;
95 if (memchr(mv_class0_fr_probs, 0, sizeof(mv_class0_fr_probs)))
96 return false;
97 if (memchr(mv_fr_probs, 0, sizeof(mv_fr_probs)))
98 return false;
99 if (memchr(mv_class0_hp_prob, 0, sizeof(mv_class0_hp_prob)))
100 return false;
101 if (memchr(mv_hp_prob, 0, sizeof(mv_hp_prob)))
102 return false;
103
104 return true;
105 }
106
Vp9FrameContextManager()107 Vp9Parser::Context::Vp9FrameContextManager::Vp9FrameContextManager()
108 : weak_ptr_factory_(this) {}
109
~Vp9FrameContextManager()110 Vp9Parser::Context::Vp9FrameContextManager::~Vp9FrameContextManager() {}
111
112 const Vp9FrameContext&
frame_context() const113 Vp9Parser::Context::Vp9FrameContextManager::frame_context() const {
114 DCHECK(initialized_);
115 DCHECK(!needs_client_update_);
116 return frame_context_;
117 }
118
Reset()119 void Vp9Parser::Context::Vp9FrameContextManager::Reset() {
120 initialized_ = false;
121 needs_client_update_ = false;
122 weak_ptr_factory_.InvalidateWeakPtrs();
123 }
124
SetNeedsClientUpdate()125 void Vp9Parser::Context::Vp9FrameContextManager::SetNeedsClientUpdate() {
126 DCHECK(!needs_client_update_);
127 initialized_ = true;
128 needs_client_update_ = true;
129 }
130
131 Vp9Parser::ContextRefreshCallback
GetUpdateCb()132 Vp9Parser::Context::Vp9FrameContextManager::GetUpdateCb() {
133 if (needs_client_update_)
134 return base::Bind(&Vp9FrameContextManager::UpdateFromClient,
135 weak_ptr_factory_.GetWeakPtr());
136 else
137 return Vp9Parser::ContextRefreshCallback();
138 }
139
Update(const Vp9FrameContext & frame_context)140 void Vp9Parser::Context::Vp9FrameContextManager::Update(
141 const Vp9FrameContext& frame_context) {
142 // DCHECK because we can trust values from our parser.
143 DCHECK(frame_context.IsValid());
144 initialized_ = true;
145 frame_context_ = frame_context;
146
147 // For frame context we are updating, it may be still awaiting previous
148 // ContextRefreshCallback. Because we overwrite the value of context here and
149 // previous ContextRefreshCallback no longer matters, invalidate the weak ptr
150 // to prevent previous ContextRefreshCallback run.
151 // With this optimization, we may be able to parse more frames while previous
152 // are still decoding.
153 weak_ptr_factory_.InvalidateWeakPtrs();
154 needs_client_update_ = false;
155 }
156
UpdateFromClient(const Vp9FrameContext & frame_context)157 void Vp9Parser::Context::Vp9FrameContextManager::UpdateFromClient(
158 const Vp9FrameContext& frame_context) {
159 DVLOG(2) << "Got external frame_context update";
160 DCHECK(needs_client_update_);
161 if (!frame_context.IsValid()) {
162 DLOG(ERROR) << "Invalid prob value in frame_context";
163 return;
164 }
165 needs_client_update_ = false;
166 initialized_ = true;
167 frame_context_ = frame_context;
168 }
169
Reset()170 void Vp9Parser::Context::Reset() {
171 memset(&segmentation_, 0, sizeof(segmentation_));
172 memset(&loop_filter_, 0, sizeof(loop_filter_));
173 memset(&ref_slots_, 0, sizeof(ref_slots_));
174 for (auto& manager : frame_context_managers_)
175 manager.Reset();
176 }
177
MarkFrameContextForUpdate(size_t frame_context_idx)178 void Vp9Parser::Context::MarkFrameContextForUpdate(size_t frame_context_idx) {
179 DCHECK_LT(frame_context_idx, arraysize(frame_context_managers_));
180 frame_context_managers_[frame_context_idx].SetNeedsClientUpdate();
181 }
182
UpdateFrameContext(size_t frame_context_idx,const Vp9FrameContext & frame_context)183 void Vp9Parser::Context::UpdateFrameContext(
184 size_t frame_context_idx,
185 const Vp9FrameContext& frame_context) {
186 DCHECK_LT(frame_context_idx, arraysize(frame_context_managers_));
187 frame_context_managers_[frame_context_idx].Update(frame_context);
188 }
189
GetRefSlot(size_t ref_type) const190 const Vp9Parser::ReferenceSlot& Vp9Parser::Context::GetRefSlot(
191 size_t ref_type) const {
192 DCHECK_LT(ref_type, arraysize(ref_slots_));
193 return ref_slots_[ref_type];
194 }
195
UpdateRefSlot(size_t ref_type,const Vp9Parser::ReferenceSlot & ref_slot)196 void Vp9Parser::Context::UpdateRefSlot(
197 size_t ref_type,
198 const Vp9Parser::ReferenceSlot& ref_slot) {
199 DCHECK_LT(ref_type, arraysize(ref_slots_));
200 ref_slots_[ref_type] = ref_slot;
201 }
202
Vp9Parser(bool parsing_compressed_header)203 Vp9Parser::Vp9Parser(bool parsing_compressed_header)
204 : parsing_compressed_header_(parsing_compressed_header) {
205 Reset();
206 }
207
~Vp9Parser()208 Vp9Parser::~Vp9Parser() {}
209
SetStream(const uint8_t * stream,off_t stream_size)210 void Vp9Parser::SetStream(const uint8_t* stream, off_t stream_size) {
211 DCHECK(stream);
212 stream_ = stream;
213 bytes_left_ = stream_size;
214 frames_.clear();
215 }
216
Reset()217 void Vp9Parser::Reset() {
218 stream_ = nullptr;
219 bytes_left_ = 0;
220 frames_.clear();
221 curr_frame_info_.Reset();
222
223 context_.Reset();
224 }
225
ParseNextFrame(Vp9FrameHeader * fhdr)226 Vp9Parser::Result Vp9Parser::ParseNextFrame(Vp9FrameHeader* fhdr) {
227 DCHECK(fhdr);
228 DVLOG(2) << "ParseNextFrame";
229
230 // If |curr_frame_info_| is valid, uncompressed header was parsed into
231 // |curr_frame_header_| and we are awaiting context update to proceed with
232 // compressed header parsing.
233 if (!curr_frame_info_.IsValid()) {
234 if (frames_.empty()) {
235 // No frames to be decoded, if there is no more stream, request more.
236 if (!stream_)
237 return kEOStream;
238
239 // New stream to be parsed, parse it and fill frames_.
240 frames_ = ParseSuperframe();
241 if (frames_.empty()) {
242 DVLOG(1) << "Failed parsing superframes";
243 return kInvalidStream;
244 }
245 }
246
247 curr_frame_info_ = frames_.front();
248 frames_.pop_front();
249
250 memset(&curr_frame_header_, 0, sizeof(curr_frame_header_));
251
252 Vp9UncompressedHeaderParser uncompressed_parser(&context_);
253 if (!uncompressed_parser.Parse(curr_frame_info_.ptr, curr_frame_info_.size,
254 &curr_frame_header_))
255 return kInvalidStream;
256
257 if (curr_frame_header_.header_size_in_bytes == 0) {
258 // Verify padding bits are zero.
259 for (off_t i = curr_frame_header_.uncompressed_header_size;
260 i < curr_frame_info_.size; i++) {
261 if (curr_frame_info_.ptr[i] != 0) {
262 DVLOG(1) << "Padding bits are not zeros.";
263 return kInvalidStream;
264 }
265 }
266 *fhdr = curr_frame_header_;
267 curr_frame_info_.Reset();
268 return kOk;
269 }
270 if (curr_frame_header_.uncompressed_header_size +
271 curr_frame_header_.header_size_in_bytes >
272 base::checked_cast<size_t>(curr_frame_info_.size)) {
273 DVLOG(1) << "header_size_in_bytes="
274 << curr_frame_header_.header_size_in_bytes
275 << " is larger than bytes left in buffer: "
276 << curr_frame_info_.size -
277 curr_frame_header_.uncompressed_header_size;
278 return kInvalidStream;
279 }
280 }
281
282 if (parsing_compressed_header_) {
283 size_t frame_context_idx = curr_frame_header_.frame_context_idx;
284 const Context::Vp9FrameContextManager& context_to_load =
285 context_.frame_context_managers_[frame_context_idx];
286 if (!context_to_load.initialized()) {
287 // 8.2 Frame order constraints
288 // must load an initialized set of probabilities.
289 DVLOG(1) << "loading uninitialized frame context, index="
290 << frame_context_idx;
291 return kInvalidStream;
292 }
293 if (context_to_load.needs_client_update()) {
294 DVLOG(3) << "waiting frame_context_idx=" << frame_context_idx
295 << " to update";
296 return kAwaitingRefresh;
297 }
298 curr_frame_header_.initial_frame_context =
299 curr_frame_header_.frame_context = context_to_load.frame_context();
300
301 Vp9CompressedHeaderParser compressed_parser;
302 if (!compressed_parser.Parse(
303 curr_frame_info_.ptr + curr_frame_header_.uncompressed_header_size,
304 curr_frame_header_.header_size_in_bytes, &curr_frame_header_)) {
305 return kInvalidStream;
306 }
307
308 if (curr_frame_header_.refresh_frame_context) {
309 // In frame parallel mode, we can refresh the context without decoding
310 // tile data.
311 if (curr_frame_header_.frame_parallel_decoding_mode) {
312 context_.UpdateFrameContext(frame_context_idx,
313 curr_frame_header_.frame_context);
314 } else {
315 context_.MarkFrameContextForUpdate(frame_context_idx);
316 }
317 }
318 }
319
320 SetupSegmentationDequant();
321 SetupLoopFilter();
322 UpdateSlots();
323
324 *fhdr = curr_frame_header_;
325 curr_frame_info_.Reset();
326 return kOk;
327 }
328
GetContextRefreshCb(size_t frame_context_idx)329 Vp9Parser::ContextRefreshCallback Vp9Parser::GetContextRefreshCb(
330 size_t frame_context_idx) {
331 DCHECK_LT(frame_context_idx, arraysize(context_.frame_context_managers_));
332 auto& frame_context_manager =
333 context_.frame_context_managers_[frame_context_idx];
334
335 return frame_context_manager.GetUpdateCb();
336 }
337
338 // Annex B Superframes
ParseSuperframe()339 std::deque<Vp9Parser::FrameInfo> Vp9Parser::ParseSuperframe() {
340 const uint8_t* stream = stream_;
341 off_t bytes_left = bytes_left_;
342
343 // Make sure we don't parse stream_ more than once.
344 stream_ = nullptr;
345 bytes_left_ = 0;
346
347 if (bytes_left < 1)
348 return std::deque<FrameInfo>();
349
350 // If this is a superframe, the last byte in the stream will contain the
351 // superframe marker. If not, the whole buffer contains a single frame.
352 uint8_t marker = *(stream + bytes_left - 1);
353 if ((marker & 0xe0) != 0xc0) {
354 return {FrameInfo(stream, bytes_left)};
355 }
356
357 DVLOG(1) << "Parsing a superframe";
358
359 // The bytes immediately before the superframe marker constitute superframe
360 // index, which stores information about sizes of each frame in it.
361 // Calculate its size and set index_ptr to the beginning of it.
362 size_t num_frames = (marker & 0x7) + 1;
363 size_t mag = ((marker >> 3) & 0x3) + 1;
364 off_t index_size = 2 + mag * num_frames;
365
366 if (bytes_left < index_size)
367 return std::deque<FrameInfo>();
368
369 const uint8_t* index_ptr = stream + bytes_left - index_size;
370 if (marker != *index_ptr)
371 return std::deque<FrameInfo>();
372
373 ++index_ptr;
374 bytes_left -= index_size;
375
376 // Parse frame information contained in the index and add a pointer to and
377 // size of each frame to frames.
378 std::deque<FrameInfo> frames;
379 for (size_t i = 0; i < num_frames; ++i) {
380 uint32_t size = 0;
381 for (size_t j = 0; j < mag; ++j) {
382 size |= *index_ptr << (j * 8);
383 ++index_ptr;
384 }
385
386 if (base::checked_cast<off_t>(size) > bytes_left) {
387 DVLOG(1) << "Not enough data in the buffer for frame " << i;
388 return std::deque<FrameInfo>();
389 }
390
391 frames.push_back(FrameInfo(stream, size));
392 stream += size;
393 bytes_left -= size;
394
395 DVLOG(1) << "Frame " << i << ", size: " << size;
396 }
397
398 return frames;
399 }
400
401 // 8.6.1
402 const size_t QINDEX_RANGE = 256;
403 const int16_t kDcQLookup[QINDEX_RANGE] = {
404 4, 8, 8, 9, 10, 11, 12, 12,
405 13, 14, 15, 16, 17, 18, 19, 19,
406 20, 21, 22, 23, 24, 25, 26, 26,
407 27, 28, 29, 30, 31, 32, 32, 33,
408 34, 35, 36, 37, 38, 38, 39, 40,
409 41, 42, 43, 43, 44, 45, 46, 47,
410 48, 48, 49, 50, 51, 52, 53, 53,
411 54, 55, 56, 57, 57, 58, 59, 60,
412 61, 62, 62, 63, 64, 65, 66, 66,
413 67, 68, 69, 70, 70, 71, 72, 73,
414 74, 74, 75, 76, 77, 78, 78, 79,
415 80, 81, 81, 82, 83, 84, 85, 85,
416 87, 88, 90, 92, 93, 95, 96, 98,
417 99, 101, 102, 104, 105, 107, 108, 110,
418 111, 113, 114, 116, 117, 118, 120, 121,
419 123, 125, 127, 129, 131, 134, 136, 138,
420 140, 142, 144, 146, 148, 150, 152, 154,
421 156, 158, 161, 164, 166, 169, 172, 174,
422 177, 180, 182, 185, 187, 190, 192, 195,
423 199, 202, 205, 208, 211, 214, 217, 220,
424 223, 226, 230, 233, 237, 240, 243, 247,
425 250, 253, 257, 261, 265, 269, 272, 276,
426 280, 284, 288, 292, 296, 300, 304, 309,
427 313, 317, 322, 326, 330, 335, 340, 344,
428 349, 354, 359, 364, 369, 374, 379, 384,
429 389, 395, 400, 406, 411, 417, 423, 429,
430 435, 441, 447, 454, 461, 467, 475, 482,
431 489, 497, 505, 513, 522, 530, 539, 549,
432 559, 569, 579, 590, 602, 614, 626, 640,
433 654, 668, 684, 700, 717, 736, 755, 775,
434 796, 819, 843, 869, 896, 925, 955, 988,
435 1022, 1058, 1098, 1139, 1184, 1232, 1282, 1336,
436 };
437
438 const int16_t kAcQLookup[QINDEX_RANGE] = {
439 4, 8, 9, 10, 11, 12, 13, 14,
440 15, 16, 17, 18, 19, 20, 21, 22,
441 23, 24, 25, 26, 27, 28, 29, 30,
442 31, 32, 33, 34, 35, 36, 37, 38,
443 39, 40, 41, 42, 43, 44, 45, 46,
444 47, 48, 49, 50, 51, 52, 53, 54,
445 55, 56, 57, 58, 59, 60, 61, 62,
446 63, 64, 65, 66, 67, 68, 69, 70,
447 71, 72, 73, 74, 75, 76, 77, 78,
448 79, 80, 81, 82, 83, 84, 85, 86,
449 87, 88, 89, 90, 91, 92, 93, 94,
450 95, 96, 97, 98, 99, 100, 101, 102,
451 104, 106, 108, 110, 112, 114, 116, 118,
452 120, 122, 124, 126, 128, 130, 132, 134,
453 136, 138, 140, 142, 144, 146, 148, 150,
454 152, 155, 158, 161, 164, 167, 170, 173,
455 176, 179, 182, 185, 188, 191, 194, 197,
456 200, 203, 207, 211, 215, 219, 223, 227,
457 231, 235, 239, 243, 247, 251, 255, 260,
458 265, 270, 275, 280, 285, 290, 295, 300,
459 305, 311, 317, 323, 329, 335, 341, 347,
460 353, 359, 366, 373, 380, 387, 394, 401,
461 408, 416, 424, 432, 440, 448, 456, 465,
462 474, 483, 492, 501, 510, 520, 530, 540,
463 550, 560, 571, 582, 593, 604, 615, 627,
464 639, 651, 663, 676, 689, 702, 715, 729,
465 743, 757, 771, 786, 801, 816, 832, 848,
466 864, 881, 898, 915, 933, 951, 969, 988,
467 1007, 1026, 1046, 1066, 1087, 1108, 1129, 1151,
468 1173, 1196, 1219, 1243, 1267, 1292, 1317, 1343,
469 1369, 1396, 1423, 1451, 1479, 1508, 1537, 1567,
470 1597, 1628, 1660, 1692, 1725, 1759, 1793, 1828,
471 };
472
473 static_assert(arraysize(kDcQLookup) == arraysize(kAcQLookup),
474 "quantizer lookup arrays of incorrect size");
475
ClampQ(size_t q)476 static size_t ClampQ(size_t q) {
477 return std::min(std::max(static_cast<size_t>(0), q),
478 arraysize(kDcQLookup) - 1);
479 }
480
481 // 8.6.1 Dequantization functions
GetQIndex(const Vp9QuantizationParams & quant,size_t segid) const482 size_t Vp9Parser::GetQIndex(const Vp9QuantizationParams& quant,
483 size_t segid) const {
484 const Vp9SegmentationParams& segmentation = context_.segmentation();
485
486 if (segmentation.FeatureEnabled(segid,
487 Vp9SegmentationParams::SEG_LVL_ALT_Q)) {
488 int16_t feature_data =
489 segmentation.FeatureData(segid, Vp9SegmentationParams::SEG_LVL_ALT_Q);
490 size_t q_index = segmentation.abs_or_delta_update
491 ? feature_data
492 : quant.base_q_idx + feature_data;
493 return ClampQ(q_index);
494 }
495
496 return quant.base_q_idx;
497 }
498
499 // 8.6.1 Dequantization functions
SetupSegmentationDequant()500 void Vp9Parser::SetupSegmentationDequant() {
501 const Vp9QuantizationParams& quant = curr_frame_header_.quant_params;
502 Vp9SegmentationParams& segmentation = context_.segmentation_;
503
504 DLOG_IF(ERROR, curr_frame_header_.bit_depth > 8)
505 << "bit_depth > 8 is not supported "
506 "yet, kDcQLookup and kAcQLookup "
507 "need extended";
508 if (segmentation.enabled) {
509 for (size_t i = 0; i < Vp9SegmentationParams::kNumSegments; ++i) {
510 const size_t q_index = GetQIndex(quant, i);
511 segmentation.y_dequant[i][0] =
512 kDcQLookup[ClampQ(q_index + quant.delta_q_y_dc)];
513 segmentation.y_dequant[i][1] = kAcQLookup[ClampQ(q_index)];
514 segmentation.uv_dequant[i][0] =
515 kDcQLookup[ClampQ(q_index + quant.delta_q_uv_dc)];
516 segmentation.uv_dequant[i][1] =
517 kAcQLookup[ClampQ(q_index + quant.delta_q_uv_ac)];
518 }
519 } else {
520 const size_t q_index = quant.base_q_idx;
521 segmentation.y_dequant[0][0] =
522 kDcQLookup[ClampQ(q_index + quant.delta_q_y_dc)];
523 segmentation.y_dequant[0][1] = kAcQLookup[ClampQ(q_index)];
524 segmentation.uv_dequant[0][0] =
525 kDcQLookup[ClampQ(q_index + quant.delta_q_uv_dc)];
526 segmentation.uv_dequant[0][1] =
527 kAcQLookup[ClampQ(q_index + quant.delta_q_uv_ac)];
528 }
529 }
530
ClampLf(int lf)531 static int ClampLf(int lf) {
532 const int kMaxLoopFilterLevel = 63;
533 return std::min(std::max(0, lf), kMaxLoopFilterLevel);
534 }
535
536 // 8.8.1 Loop filter frame init process
SetupLoopFilter()537 void Vp9Parser::SetupLoopFilter() {
538 Vp9LoopFilterParams& loop_filter = context_.loop_filter_;
539 if (!loop_filter.level)
540 return;
541
542 int scale = loop_filter.level < 32 ? 1 : 2;
543
544 for (size_t i = 0; i < Vp9SegmentationParams::kNumSegments; ++i) {
545 int level = loop_filter.level;
546 const Vp9SegmentationParams& segmentation = context_.segmentation();
547
548 if (segmentation.FeatureEnabled(i, Vp9SegmentationParams::SEG_LVL_ALT_LF)) {
549 int feature_data =
550 segmentation.FeatureData(i, Vp9SegmentationParams::SEG_LVL_ALT_LF);
551 level = ClampLf(segmentation.abs_or_delta_update ? feature_data
552 : level + feature_data);
553 }
554
555 if (!loop_filter.delta_enabled) {
556 memset(loop_filter.lvl[i], level, sizeof(loop_filter.lvl[i]));
557 } else {
558 loop_filter.lvl[i][Vp9RefType::VP9_FRAME_INTRA][0] = ClampLf(
559 level + loop_filter.ref_deltas[Vp9RefType::VP9_FRAME_INTRA] * scale);
560 loop_filter.lvl[i][Vp9RefType::VP9_FRAME_INTRA][1] = 0;
561
562 for (size_t type = Vp9RefType::VP9_FRAME_LAST;
563 type < Vp9RefType::VP9_FRAME_MAX; ++type) {
564 for (size_t mode = 0; mode < Vp9LoopFilterParams::kNumModeDeltas;
565 ++mode) {
566 loop_filter.lvl[i][type][mode] =
567 ClampLf(level + loop_filter.ref_deltas[type] * scale +
568 loop_filter.mode_deltas[mode] * scale);
569 }
570 }
571 }
572 }
573 }
574
UpdateSlots()575 void Vp9Parser::UpdateSlots() {
576 // 8.10 Reference frame update process
577 for (size_t i = 0; i < kVp9NumRefFrames; i++) {
578 if (curr_frame_header_.RefreshFlag(i)) {
579 ReferenceSlot ref_slot;
580 ref_slot.initialized = true;
581
582 ref_slot.frame_width = curr_frame_header_.frame_width;
583 ref_slot.frame_height = curr_frame_header_.frame_height;
584 ref_slot.subsampling_x = curr_frame_header_.subsampling_x;
585 ref_slot.subsampling_y = curr_frame_header_.subsampling_y;
586 ref_slot.bit_depth = curr_frame_header_.bit_depth;
587
588 ref_slot.profile = curr_frame_header_.profile;
589 ref_slot.color_space = curr_frame_header_.color_space;
590 context_.UpdateRefSlot(i, ref_slot);
591 }
592 }
593 }
594
595 } // namespace media
596