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