Home | History | Annotate | Download | only in vda
      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 
     25 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 
     32 bool Vp9FrameHeader::IsIntra() const {
     33   return !show_existing_frame && (frame_type == KEYFRAME || intra_only);
     34 }
     35 
     36 Vp9Parser::FrameInfo::FrameInfo(const uint8_t* ptr, off_t size)
     37     : ptr(ptr), size(size) {}
     38 
     39 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 
    107 Vp9Parser::Context::Vp9FrameContextManager::Vp9FrameContextManager()
    108     : weak_ptr_factory_(this) {}
    109 
    110 Vp9Parser::Context::Vp9FrameContextManager::~Vp9FrameContextManager() {}
    111 
    112 const Vp9FrameContext&
    113 Vp9Parser::Context::Vp9FrameContextManager::frame_context() const {
    114   DCHECK(initialized_);
    115   DCHECK(!needs_client_update_);
    116   return frame_context_;
    117 }
    118 
    119 void Vp9Parser::Context::Vp9FrameContextManager::Reset() {
    120   initialized_ = false;
    121   needs_client_update_ = false;
    122   weak_ptr_factory_.InvalidateWeakPtrs();
    123 }
    124 
    125 void Vp9Parser::Context::Vp9FrameContextManager::SetNeedsClientUpdate() {
    126   DCHECK(!needs_client_update_);
    127   initialized_ = true;
    128   needs_client_update_ = true;
    129 }
    130 
    131 Vp9Parser::ContextRefreshCallback
    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 
    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 
    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 
    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 
    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 
    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 
    190 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 
    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 
    203 Vp9Parser::Vp9Parser(bool parsing_compressed_header)
    204     : parsing_compressed_header_(parsing_compressed_header) {
    205   Reset();
    206 }
    207 
    208 Vp9Parser::~Vp9Parser() {}
    209 
    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 
    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 
    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 
    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
    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 
    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
    482 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
    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 
    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
    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 
    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