Home | History | Annotate | Download | only in media
      1 // Copyright (c) 2012 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 #include <algorithm>
      6 #include <limits>
      7 
      8 #include "base/bind.h"
      9 #include "base/bind_helpers.h"
     10 #include "base/numerics/safe_conversions.h"
     11 #include "base/stl_util.h"
     12 #include "content/common/gpu/media/vaapi_h264_decoder.h"
     13 
     14 namespace content {
     15 
     16 // Decode surface, used for decoding and reference. input_id comes from client
     17 // and is associated with the surface that was produced as the result
     18 // of decoding a bitstream buffer with that id.
     19 class VaapiH264Decoder::DecodeSurface {
     20  public:
     21   DecodeSurface(int poc,
     22                 int32 input_id,
     23                 const scoped_refptr<VASurface>& va_surface);
     24   DecodeSurface(int poc, const scoped_refptr<DecodeSurface>& dec_surface);
     25   ~DecodeSurface();
     26 
     27   int poc() {
     28     return poc_;
     29   }
     30 
     31   scoped_refptr<VASurface> va_surface() {
     32     return va_surface_;
     33   }
     34 
     35   int32 input_id() {
     36     return input_id_;
     37   }
     38 
     39  private:
     40   int poc_;
     41   int32 input_id_;
     42   scoped_refptr<VASurface> va_surface_;
     43 };
     44 
     45 VaapiH264Decoder::DecodeSurface::DecodeSurface(
     46     int poc,
     47     int32 input_id,
     48     const scoped_refptr<VASurface>& va_surface)
     49     : poc_(poc),
     50       input_id_(input_id),
     51       va_surface_(va_surface) {
     52   DCHECK(va_surface_.get());
     53 }
     54 
     55 VaapiH264Decoder::DecodeSurface::~DecodeSurface() {
     56 }
     57 
     58 VaapiH264Decoder::VaapiH264Decoder(
     59     VaapiWrapper* vaapi_wrapper,
     60     const OutputPicCB& output_pic_cb,
     61     const ReportErrorToUmaCB& report_error_to_uma_cb)
     62     : max_pic_order_cnt_lsb_(0),
     63       max_frame_num_(0),
     64       max_pic_num_(0),
     65       max_long_term_frame_idx_(0),
     66       max_num_reorder_frames_(0),
     67       curr_sps_id_(-1),
     68       curr_pps_id_(-1),
     69       vaapi_wrapper_(vaapi_wrapper),
     70       output_pic_cb_(output_pic_cb),
     71       report_error_to_uma_cb_(report_error_to_uma_cb) {
     72   Reset();
     73   state_ = kNeedStreamMetadata;
     74 }
     75 
     76 VaapiH264Decoder::~VaapiH264Decoder() {
     77 }
     78 
     79 void VaapiH264Decoder::Reset() {
     80   curr_pic_.reset();
     81 
     82   curr_input_id_ = -1;
     83   frame_num_ = 0;
     84   prev_frame_num_ = -1;
     85   prev_frame_num_offset_ = -1;
     86 
     87   prev_ref_has_memmgmnt5_ = false;
     88   prev_ref_top_field_order_cnt_ = -1;
     89   prev_ref_pic_order_cnt_msb_ = -1;
     90   prev_ref_pic_order_cnt_lsb_ = -1;
     91   prev_ref_field_ = H264Picture::FIELD_NONE;
     92 
     93   vaapi_wrapper_->DestroyPendingBuffers();
     94 
     95   ref_pic_list0_.clear();
     96   ref_pic_list1_.clear();
     97 
     98   for (DecSurfacesInUse::iterator it = decode_surfaces_in_use_.begin();
     99        it != decode_surfaces_in_use_.end(); ) {
    100     int poc = it->second->poc();
    101     // Must be incremented before UnassignSurfaceFromPoC as this call
    102     // invalidates |it|.
    103     ++it;
    104     UnassignSurfaceFromPoC(poc);
    105   }
    106   DCHECK(decode_surfaces_in_use_.empty());
    107 
    108   dpb_.Clear();
    109   parser_.Reset();
    110   last_output_poc_ = std::numeric_limits<int>::min();
    111 
    112   // If we are in kDecoding, we can resume without processing an SPS.
    113   if (state_ == kDecoding)
    114     state_ = kAfterReset;
    115 }
    116 
    117 void VaapiH264Decoder::ReuseSurface(
    118     const scoped_refptr<VASurface>& va_surface) {
    119   available_va_surfaces_.push_back(va_surface);
    120 }
    121 
    122 // Fill |va_pic| with default/neutral values.
    123 static void InitVAPicture(VAPictureH264* va_pic) {
    124   memset(va_pic, 0, sizeof(*va_pic));
    125   va_pic->picture_id = VA_INVALID_ID;
    126   va_pic->flags = VA_PICTURE_H264_INVALID;
    127 }
    128 
    129 void VaapiH264Decoder::FillVAPicture(VAPictureH264 *va_pic, H264Picture* pic) {
    130   DCHECK(pic);
    131 
    132   DecodeSurface* dec_surface = DecodeSurfaceByPoC(pic->pic_order_cnt);
    133   if (!dec_surface) {
    134     // Cannot provide a ref picture, will corrupt output, but may be able
    135     // to recover.
    136     InitVAPicture(va_pic);
    137     return;
    138   }
    139 
    140   va_pic->picture_id = dec_surface->va_surface()->id();
    141   va_pic->frame_idx = pic->frame_num;
    142   va_pic->flags = 0;
    143 
    144   switch (pic->field) {
    145     case H264Picture::FIELD_NONE:
    146       break;
    147     case H264Picture::FIELD_TOP:
    148       va_pic->flags |= VA_PICTURE_H264_TOP_FIELD;
    149       break;
    150     case H264Picture::FIELD_BOTTOM:
    151       va_pic->flags |= VA_PICTURE_H264_BOTTOM_FIELD;
    152       break;
    153   }
    154 
    155   if (pic->ref) {
    156     va_pic->flags |= pic->long_term ? VA_PICTURE_H264_LONG_TERM_REFERENCE
    157                                     : VA_PICTURE_H264_SHORT_TERM_REFERENCE;
    158   }
    159 
    160   va_pic->TopFieldOrderCnt = pic->top_field_order_cnt;
    161   va_pic->BottomFieldOrderCnt = pic->bottom_field_order_cnt;
    162 }
    163 
    164 int VaapiH264Decoder::FillVARefFramesFromDPB(VAPictureH264 *va_pics,
    165                                              int num_pics) {
    166   H264DPB::Pictures::reverse_iterator rit;
    167   int i;
    168 
    169   // Return reference frames in reverse order of insertion.
    170   // Libva does not document this, but other implementations (e.g. mplayer)
    171   // do it this way as well.
    172   for (rit = dpb_.rbegin(), i = 0; rit != dpb_.rend() && i < num_pics; ++rit) {
    173     if ((*rit)->ref)
    174       FillVAPicture(&va_pics[i++], *rit);
    175   }
    176 
    177   return i;
    178 }
    179 
    180 VaapiH264Decoder::DecodeSurface* VaapiH264Decoder::DecodeSurfaceByPoC(int poc) {
    181   DecSurfacesInUse::iterator iter = decode_surfaces_in_use_.find(poc);
    182   if (iter == decode_surfaces_in_use_.end()) {
    183     DVLOG(1) << "Could not find surface assigned to POC: " << poc;
    184     return NULL;
    185   }
    186 
    187   return iter->second.get();
    188 }
    189 
    190 bool VaapiH264Decoder::AssignSurfaceToPoC(int32 input_id, int poc) {
    191   if (available_va_surfaces_.empty()) {
    192     DVLOG(1) << "No VA Surfaces available";
    193     return false;
    194   }
    195 
    196   linked_ptr<DecodeSurface> dec_surface(new DecodeSurface(
    197       poc, input_id, available_va_surfaces_.back()));
    198   available_va_surfaces_.pop_back();
    199 
    200   DVLOG(4) << "POC " << poc
    201            << " will use surface " << dec_surface->va_surface()->id();
    202 
    203   bool inserted = decode_surfaces_in_use_.insert(
    204       std::make_pair(poc, dec_surface)).second;
    205   DCHECK(inserted);
    206 
    207   return true;
    208 }
    209 
    210 void VaapiH264Decoder::UnassignSurfaceFromPoC(int poc) {
    211   DecSurfacesInUse::iterator it = decode_surfaces_in_use_.find(poc);
    212   if (it == decode_surfaces_in_use_.end()) {
    213     DVLOG(1) << "Asked to unassign an unassigned POC " << poc;
    214     return;
    215   }
    216 
    217   DVLOG(4) << "POC " << poc << " no longer using VA surface "
    218            << it->second->va_surface()->id();
    219 
    220   decode_surfaces_in_use_.erase(it);
    221 }
    222 
    223 bool VaapiH264Decoder::SendPPS() {
    224   const media::H264PPS* pps = parser_.GetPPS(curr_pps_id_);
    225   DCHECK(pps);
    226 
    227   const media::H264SPS* sps = parser_.GetSPS(pps->seq_parameter_set_id);
    228   DCHECK(sps);
    229 
    230   DCHECK(curr_pic_.get());
    231 
    232   VAPictureParameterBufferH264 pic_param;
    233   memset(&pic_param, 0, sizeof(VAPictureParameterBufferH264));
    234 
    235 #define FROM_SPS_TO_PP(a) pic_param.a = sps->a;
    236 #define FROM_SPS_TO_PP2(a, b) pic_param.b = sps->a;
    237   FROM_SPS_TO_PP2(pic_width_in_mbs_minus1, picture_width_in_mbs_minus1);
    238   // This assumes non-interlaced video
    239   FROM_SPS_TO_PP2(pic_height_in_map_units_minus1,
    240                   picture_height_in_mbs_minus1);
    241   FROM_SPS_TO_PP(bit_depth_luma_minus8);
    242   FROM_SPS_TO_PP(bit_depth_chroma_minus8);
    243 #undef FROM_SPS_TO_PP
    244 #undef FROM_SPS_TO_PP2
    245 
    246 #define FROM_SPS_TO_PP_SF(a) pic_param.seq_fields.bits.a = sps->a;
    247 #define FROM_SPS_TO_PP_SF2(a, b) pic_param.seq_fields.bits.b = sps->a;
    248   FROM_SPS_TO_PP_SF(chroma_format_idc);
    249   FROM_SPS_TO_PP_SF2(separate_colour_plane_flag,
    250                      residual_colour_transform_flag);
    251   FROM_SPS_TO_PP_SF(gaps_in_frame_num_value_allowed_flag);
    252   FROM_SPS_TO_PP_SF(frame_mbs_only_flag);
    253   FROM_SPS_TO_PP_SF(mb_adaptive_frame_field_flag);
    254   FROM_SPS_TO_PP_SF(direct_8x8_inference_flag);
    255   pic_param.seq_fields.bits.MinLumaBiPredSize8x8 = (sps->level_idc >= 31);
    256   FROM_SPS_TO_PP_SF(log2_max_frame_num_minus4);
    257   FROM_SPS_TO_PP_SF(pic_order_cnt_type);
    258   FROM_SPS_TO_PP_SF(log2_max_pic_order_cnt_lsb_minus4);
    259   FROM_SPS_TO_PP_SF(delta_pic_order_always_zero_flag);
    260 #undef FROM_SPS_TO_PP_SF
    261 #undef FROM_SPS_TO_PP_SF2
    262 
    263 #define FROM_PPS_TO_PP(a) pic_param.a = pps->a;
    264   FROM_PPS_TO_PP(num_slice_groups_minus1);
    265   pic_param.slice_group_map_type = 0;
    266   pic_param.slice_group_change_rate_minus1 = 0;
    267   FROM_PPS_TO_PP(pic_init_qp_minus26);
    268   FROM_PPS_TO_PP(pic_init_qs_minus26);
    269   FROM_PPS_TO_PP(chroma_qp_index_offset);
    270   FROM_PPS_TO_PP(second_chroma_qp_index_offset);
    271 #undef FROM_PPS_TO_PP
    272 
    273 #define FROM_PPS_TO_PP_PF(a) pic_param.pic_fields.bits.a = pps->a;
    274 #define FROM_PPS_TO_PP_PF2(a, b) pic_param.pic_fields.bits.b = pps->a;
    275   FROM_PPS_TO_PP_PF(entropy_coding_mode_flag);
    276   FROM_PPS_TO_PP_PF(weighted_pred_flag);
    277   FROM_PPS_TO_PP_PF(weighted_bipred_idc);
    278   FROM_PPS_TO_PP_PF(transform_8x8_mode_flag);
    279 
    280   pic_param.pic_fields.bits.field_pic_flag = 0;
    281   FROM_PPS_TO_PP_PF(constrained_intra_pred_flag);
    282   FROM_PPS_TO_PP_PF2(bottom_field_pic_order_in_frame_present_flag,
    283                 pic_order_present_flag);
    284   FROM_PPS_TO_PP_PF(deblocking_filter_control_present_flag);
    285   FROM_PPS_TO_PP_PF(redundant_pic_cnt_present_flag);
    286   pic_param.pic_fields.bits.reference_pic_flag = curr_pic_->ref;
    287 #undef FROM_PPS_TO_PP_PF
    288 #undef FROM_PPS_TO_PP_PF2
    289 
    290   pic_param.frame_num = curr_pic_->frame_num;
    291 
    292   InitVAPicture(&pic_param.CurrPic);
    293   FillVAPicture(&pic_param.CurrPic, curr_pic_.get());
    294 
    295   // Init reference pictures' array.
    296   for (int i = 0; i < 16; ++i)
    297     InitVAPicture(&pic_param.ReferenceFrames[i]);
    298 
    299   // And fill it with picture info from DPB.
    300   FillVARefFramesFromDPB(pic_param.ReferenceFrames,
    301                          arraysize(pic_param.ReferenceFrames));
    302 
    303   pic_param.num_ref_frames = sps->max_num_ref_frames;
    304 
    305   return vaapi_wrapper_->SubmitBuffer(VAPictureParameterBufferType,
    306                                       sizeof(VAPictureParameterBufferH264),
    307                                       &pic_param);
    308 }
    309 
    310 bool VaapiH264Decoder::SendIQMatrix() {
    311   const media::H264PPS* pps = parser_.GetPPS(curr_pps_id_);
    312   DCHECK(pps);
    313 
    314   VAIQMatrixBufferH264 iq_matrix_buf;
    315   memset(&iq_matrix_buf, 0, sizeof(VAIQMatrixBufferH264));
    316 
    317   if (pps->pic_scaling_matrix_present_flag) {
    318     for (int i = 0; i < 6; ++i) {
    319       for (int j = 0; j < 16; ++j)
    320         iq_matrix_buf.ScalingList4x4[i][j] = pps->scaling_list4x4[i][j];
    321     }
    322 
    323     for (int i = 0; i < 2; ++i) {
    324       for (int j = 0; j < 64; ++j)
    325         iq_matrix_buf.ScalingList8x8[i][j] = pps->scaling_list8x8[i][j];
    326     }
    327   } else {
    328     const media::H264SPS* sps = parser_.GetSPS(pps->seq_parameter_set_id);
    329     DCHECK(sps);
    330     for (int i = 0; i < 6; ++i) {
    331       for (int j = 0; j < 16; ++j)
    332         iq_matrix_buf.ScalingList4x4[i][j] = sps->scaling_list4x4[i][j];
    333     }
    334 
    335     for (int i = 0; i < 2; ++i) {
    336       for (int j = 0; j < 64; ++j)
    337         iq_matrix_buf.ScalingList8x8[i][j] = sps->scaling_list8x8[i][j];
    338     }
    339   }
    340 
    341   return vaapi_wrapper_->SubmitBuffer(VAIQMatrixBufferType,
    342                                       sizeof(VAIQMatrixBufferH264),
    343                                       &iq_matrix_buf);
    344 }
    345 
    346 bool VaapiH264Decoder::SendVASliceParam(media::H264SliceHeader* slice_hdr) {
    347   const media::H264PPS* pps = parser_.GetPPS(slice_hdr->pic_parameter_set_id);
    348   DCHECK(pps);
    349 
    350   const media::H264SPS* sps = parser_.GetSPS(pps->seq_parameter_set_id);
    351   DCHECK(sps);
    352 
    353   VASliceParameterBufferH264 slice_param;
    354   memset(&slice_param, 0, sizeof(VASliceParameterBufferH264));
    355 
    356   slice_param.slice_data_size = slice_hdr->nalu_size;
    357   slice_param.slice_data_offset = 0;
    358   slice_param.slice_data_flag = VA_SLICE_DATA_FLAG_ALL;
    359   slice_param.slice_data_bit_offset = slice_hdr->header_bit_size;
    360 
    361 #define SHDRToSP(a) slice_param.a = slice_hdr->a;
    362   SHDRToSP(first_mb_in_slice);
    363   slice_param.slice_type = slice_hdr->slice_type % 5;
    364   SHDRToSP(direct_spatial_mv_pred_flag);
    365 
    366   // TODO posciak: make sure parser sets those even when override flags
    367   // in slice header is off.
    368   SHDRToSP(num_ref_idx_l0_active_minus1);
    369   SHDRToSP(num_ref_idx_l1_active_minus1);
    370   SHDRToSP(cabac_init_idc);
    371   SHDRToSP(slice_qp_delta);
    372   SHDRToSP(disable_deblocking_filter_idc);
    373   SHDRToSP(slice_alpha_c0_offset_div2);
    374   SHDRToSP(slice_beta_offset_div2);
    375 
    376   if (((slice_hdr->IsPSlice() || slice_hdr->IsSPSlice()) &&
    377        pps->weighted_pred_flag) ||
    378       (slice_hdr->IsBSlice() && pps->weighted_bipred_idc == 1)) {
    379     SHDRToSP(luma_log2_weight_denom);
    380     SHDRToSP(chroma_log2_weight_denom);
    381 
    382     SHDRToSP(luma_weight_l0_flag);
    383     SHDRToSP(luma_weight_l1_flag);
    384 
    385     SHDRToSP(chroma_weight_l0_flag);
    386     SHDRToSP(chroma_weight_l1_flag);
    387 
    388     for (int i = 0; i <= slice_param.num_ref_idx_l0_active_minus1; ++i) {
    389       slice_param.luma_weight_l0[i] =
    390           slice_hdr->pred_weight_table_l0.luma_weight[i];
    391       slice_param.luma_offset_l0[i] =
    392           slice_hdr->pred_weight_table_l0.luma_offset[i];
    393 
    394       for (int j = 0; j < 2; ++j) {
    395         slice_param.chroma_weight_l0[i][j] =
    396             slice_hdr->pred_weight_table_l0.chroma_weight[i][j];
    397         slice_param.chroma_offset_l0[i][j] =
    398             slice_hdr->pred_weight_table_l0.chroma_offset[i][j];
    399       }
    400     }
    401 
    402     if (slice_hdr->IsBSlice()) {
    403       for (int i = 0; i <= slice_param.num_ref_idx_l1_active_minus1; ++i) {
    404         slice_param.luma_weight_l1[i] =
    405             slice_hdr->pred_weight_table_l1.luma_weight[i];
    406         slice_param.luma_offset_l1[i] =
    407             slice_hdr->pred_weight_table_l1.luma_offset[i];
    408 
    409         for (int j = 0; j < 2; ++j) {
    410           slice_param.chroma_weight_l1[i][j] =
    411               slice_hdr->pred_weight_table_l1.chroma_weight[i][j];
    412           slice_param.chroma_offset_l1[i][j] =
    413               slice_hdr->pred_weight_table_l1.chroma_offset[i][j];
    414         }
    415       }
    416     }
    417   }
    418 
    419   for (int i = 0; i < 32; ++i) {
    420     InitVAPicture(&slice_param.RefPicList0[i]);
    421     InitVAPicture(&slice_param.RefPicList1[i]);
    422   }
    423 
    424   int i;
    425   H264Picture::PtrVector::iterator it;
    426   for (it = ref_pic_list0_.begin(), i = 0; it != ref_pic_list0_.end() && *it;
    427        ++it, ++i)
    428     FillVAPicture(&slice_param.RefPicList0[i], *it);
    429   for (it = ref_pic_list1_.begin(), i = 0; it != ref_pic_list1_.end() && *it;
    430        ++it, ++i)
    431     FillVAPicture(&slice_param.RefPicList1[i], *it);
    432 
    433   return vaapi_wrapper_->SubmitBuffer(VASliceParameterBufferType,
    434                                       sizeof(VASliceParameterBufferH264),
    435                                       &slice_param);
    436 }
    437 
    438 bool VaapiH264Decoder::SendSliceData(const uint8* ptr, size_t size) {
    439   // Can't help it, blame libva...
    440   void* non_const_ptr = const_cast<uint8*>(ptr);
    441   return vaapi_wrapper_->SubmitBuffer(VASliceDataBufferType, size,
    442                                       non_const_ptr);
    443 }
    444 
    445 bool VaapiH264Decoder::PrepareRefPicLists(media::H264SliceHeader* slice_hdr) {
    446   ref_pic_list0_.clear();
    447   ref_pic_list1_.clear();
    448 
    449   // Fill reference picture lists for B and S/SP slices.
    450   if (slice_hdr->IsPSlice() || slice_hdr->IsSPSlice()) {
    451     ConstructReferencePicListsP(slice_hdr);
    452     return ModifyReferencePicList(slice_hdr, 0);
    453   }
    454 
    455   if (slice_hdr->IsBSlice()) {
    456     ConstructReferencePicListsB(slice_hdr);
    457     return ModifyReferencePicList(slice_hdr, 0) &&
    458         ModifyReferencePicList(slice_hdr, 1);
    459   }
    460 
    461   return true;
    462 }
    463 
    464 bool VaapiH264Decoder::QueueSlice(media::H264SliceHeader* slice_hdr) {
    465   DCHECK(curr_pic_.get());
    466 
    467   if (!PrepareRefPicLists(slice_hdr))
    468     return false;
    469 
    470   if (!SendVASliceParam(slice_hdr))
    471     return false;
    472 
    473   if (!SendSliceData(slice_hdr->nalu_data, slice_hdr->nalu_size))
    474     return false;
    475 
    476   return true;
    477 }
    478 
    479 // TODO(posciak) start using vaMapBuffer instead of vaCreateBuffer wherever
    480 // possible.
    481 bool VaapiH264Decoder::DecodePicture() {
    482   DCHECK(curr_pic_.get());
    483 
    484   DVLOG(4) << "Decoding POC " << curr_pic_->pic_order_cnt;
    485   DecodeSurface* dec_surface = DecodeSurfaceByPoC(curr_pic_->pic_order_cnt);
    486   if (!dec_surface) {
    487     DVLOG(1) << "Asked to decode an invalid POC " << curr_pic_->pic_order_cnt;
    488     return false;
    489   }
    490 
    491   if (!vaapi_wrapper_->ExecuteAndDestroyPendingBuffers(
    492           dec_surface->va_surface()->id())) {
    493     DVLOG(1) << "Failed decoding picture";
    494     return false;
    495   }
    496 
    497   return true;
    498 }
    499 
    500 bool VaapiH264Decoder::InitCurrPicture(media::H264SliceHeader* slice_hdr) {
    501   DCHECK(curr_pic_.get());
    502 
    503   memset(curr_pic_.get(), 0, sizeof(H264Picture));
    504 
    505   curr_pic_->idr = slice_hdr->idr_pic_flag;
    506 
    507   if (slice_hdr->field_pic_flag) {
    508     curr_pic_->field = slice_hdr->bottom_field_flag ? H264Picture::FIELD_BOTTOM
    509                                                     : H264Picture::FIELD_TOP;
    510   } else {
    511     curr_pic_->field = H264Picture::FIELD_NONE;
    512   }
    513 
    514   curr_pic_->ref = slice_hdr->nal_ref_idc != 0;
    515   // This assumes non-interlaced stream.
    516   curr_pic_->frame_num = curr_pic_->pic_num = slice_hdr->frame_num;
    517 
    518   if (!CalculatePicOrderCounts(slice_hdr))
    519     return false;
    520 
    521   // Try to get an empty surface to decode this picture to.
    522   if (!AssignSurfaceToPoC(curr_input_id_, curr_pic_->pic_order_cnt)) {
    523     DVLOG(1) << "Failed getting a free surface for a picture";
    524     return false;
    525   }
    526 
    527   curr_pic_->long_term_reference_flag = slice_hdr->long_term_reference_flag;
    528   curr_pic_->adaptive_ref_pic_marking_mode_flag =
    529       slice_hdr->adaptive_ref_pic_marking_mode_flag;
    530 
    531   // If the slice header indicates we will have to perform reference marking
    532   // process after this picture is decoded, store required data for that
    533   // purpose.
    534   if (slice_hdr->adaptive_ref_pic_marking_mode_flag) {
    535     COMPILE_ASSERT(sizeof(curr_pic_->ref_pic_marking) ==
    536                    sizeof(slice_hdr->ref_pic_marking),
    537                    ref_pic_marking_array_sizes_do_not_match);
    538     memcpy(curr_pic_->ref_pic_marking, slice_hdr->ref_pic_marking,
    539            sizeof(curr_pic_->ref_pic_marking));
    540   }
    541 
    542   return true;
    543 }
    544 
    545 bool VaapiH264Decoder::CalculatePicOrderCounts(
    546     media::H264SliceHeader* slice_hdr) {
    547   DCHECK_NE(curr_sps_id_, -1);
    548   const media::H264SPS* sps = parser_.GetSPS(curr_sps_id_);
    549 
    550   int pic_order_cnt_lsb = slice_hdr->pic_order_cnt_lsb;
    551   curr_pic_->pic_order_cnt_lsb = pic_order_cnt_lsb;
    552 
    553   switch (sps->pic_order_cnt_type) {
    554     case 0:
    555       // See spec 8.2.1.1.
    556       int prev_pic_order_cnt_msb, prev_pic_order_cnt_lsb;
    557       if (slice_hdr->idr_pic_flag) {
    558         prev_pic_order_cnt_msb = prev_pic_order_cnt_lsb = 0;
    559       } else {
    560         if (prev_ref_has_memmgmnt5_) {
    561           if (prev_ref_field_ != H264Picture::FIELD_BOTTOM) {
    562             prev_pic_order_cnt_msb = 0;
    563             prev_pic_order_cnt_lsb = prev_ref_top_field_order_cnt_;
    564           } else {
    565             prev_pic_order_cnt_msb = 0;
    566             prev_pic_order_cnt_lsb = 0;
    567           }
    568         } else {
    569           prev_pic_order_cnt_msb = prev_ref_pic_order_cnt_msb_;
    570           prev_pic_order_cnt_lsb = prev_ref_pic_order_cnt_lsb_;
    571         }
    572       }
    573 
    574       DCHECK_NE(max_pic_order_cnt_lsb_, 0);
    575       if ((pic_order_cnt_lsb < prev_pic_order_cnt_lsb) &&
    576           (prev_pic_order_cnt_lsb - pic_order_cnt_lsb >=
    577            max_pic_order_cnt_lsb_ / 2)) {
    578         curr_pic_->pic_order_cnt_msb = prev_pic_order_cnt_msb +
    579           max_pic_order_cnt_lsb_;
    580       } else if ((pic_order_cnt_lsb > prev_pic_order_cnt_lsb) &&
    581           (pic_order_cnt_lsb - prev_pic_order_cnt_lsb >
    582            max_pic_order_cnt_lsb_ / 2)) {
    583         curr_pic_->pic_order_cnt_msb = prev_pic_order_cnt_msb -
    584           max_pic_order_cnt_lsb_;
    585       } else {
    586         curr_pic_->pic_order_cnt_msb = prev_pic_order_cnt_msb;
    587       }
    588 
    589       if (curr_pic_->field != H264Picture::FIELD_BOTTOM) {
    590         curr_pic_->top_field_order_cnt = curr_pic_->pic_order_cnt_msb +
    591           pic_order_cnt_lsb;
    592       }
    593 
    594       if (curr_pic_->field != H264Picture::FIELD_TOP) {
    595         // TODO posciak: perhaps replace with pic->field?
    596         if (!slice_hdr->field_pic_flag) {
    597           curr_pic_->bottom_field_order_cnt = curr_pic_->top_field_order_cnt +
    598             slice_hdr->delta_pic_order_cnt_bottom;
    599         } else {
    600           curr_pic_->bottom_field_order_cnt = curr_pic_->pic_order_cnt_msb +
    601             pic_order_cnt_lsb;
    602         }
    603       }
    604       break;
    605 
    606     case 1: {
    607       // See spec 8.2.1.2.
    608       if (prev_has_memmgmnt5_)
    609         prev_frame_num_offset_ = 0;
    610 
    611       if (slice_hdr->idr_pic_flag)
    612         curr_pic_->frame_num_offset = 0;
    613       else if (prev_frame_num_ > slice_hdr->frame_num)
    614         curr_pic_->frame_num_offset = prev_frame_num_offset_ + max_frame_num_;
    615       else
    616         curr_pic_->frame_num_offset = prev_frame_num_offset_;
    617 
    618       int abs_frame_num = 0;
    619       if (sps->num_ref_frames_in_pic_order_cnt_cycle != 0)
    620         abs_frame_num = curr_pic_->frame_num_offset + slice_hdr->frame_num;
    621       else
    622         abs_frame_num = 0;
    623 
    624       if (slice_hdr->nal_ref_idc == 0 && abs_frame_num > 0)
    625         --abs_frame_num;
    626 
    627       int expected_pic_order_cnt = 0;
    628       if (abs_frame_num > 0) {
    629         if (sps->num_ref_frames_in_pic_order_cnt_cycle == 0) {
    630           DVLOG(1) << "Invalid num_ref_frames_in_pic_order_cnt_cycle "
    631                    << "in stream";
    632           return false;
    633         }
    634 
    635         int pic_order_cnt_cycle_cnt = (abs_frame_num - 1) /
    636             sps->num_ref_frames_in_pic_order_cnt_cycle;
    637         int frame_num_in_pic_order_cnt_cycle = (abs_frame_num - 1) %
    638             sps->num_ref_frames_in_pic_order_cnt_cycle;
    639 
    640         expected_pic_order_cnt = pic_order_cnt_cycle_cnt *
    641             sps->expected_delta_per_pic_order_cnt_cycle;
    642         // frame_num_in_pic_order_cnt_cycle is verified < 255 in parser
    643         for (int i = 0; i <= frame_num_in_pic_order_cnt_cycle; ++i)
    644           expected_pic_order_cnt += sps->offset_for_ref_frame[i];
    645       }
    646 
    647       if (!slice_hdr->nal_ref_idc)
    648         expected_pic_order_cnt += sps->offset_for_non_ref_pic;
    649 
    650       if (!slice_hdr->field_pic_flag) {
    651         curr_pic_->top_field_order_cnt = expected_pic_order_cnt +
    652             slice_hdr->delta_pic_order_cnt[0];
    653         curr_pic_->bottom_field_order_cnt = curr_pic_->top_field_order_cnt +
    654             sps->offset_for_top_to_bottom_field +
    655             slice_hdr->delta_pic_order_cnt[1];
    656       } else if (!slice_hdr->bottom_field_flag) {
    657         curr_pic_->top_field_order_cnt = expected_pic_order_cnt +
    658             slice_hdr->delta_pic_order_cnt[0];
    659       } else {
    660         curr_pic_->bottom_field_order_cnt = expected_pic_order_cnt +
    661             sps->offset_for_top_to_bottom_field +
    662             slice_hdr->delta_pic_order_cnt[0];
    663       }
    664       break;
    665     }
    666 
    667     case 2:
    668       // See spec 8.2.1.3.
    669       if (prev_has_memmgmnt5_)
    670         prev_frame_num_offset_ = 0;
    671 
    672       if (slice_hdr->idr_pic_flag)
    673         curr_pic_->frame_num_offset = 0;
    674       else if (prev_frame_num_ > slice_hdr->frame_num)
    675         curr_pic_->frame_num_offset = prev_frame_num_offset_ + max_frame_num_;
    676       else
    677         curr_pic_->frame_num_offset = prev_frame_num_offset_;
    678 
    679       int temp_pic_order_cnt;
    680       if (slice_hdr->idr_pic_flag) {
    681         temp_pic_order_cnt = 0;
    682       } else if (!slice_hdr->nal_ref_idc) {
    683         temp_pic_order_cnt =
    684             2 * (curr_pic_->frame_num_offset + slice_hdr->frame_num) - 1;
    685       } else {
    686         temp_pic_order_cnt = 2 * (curr_pic_->frame_num_offset +
    687             slice_hdr->frame_num);
    688       }
    689 
    690       if (!slice_hdr->field_pic_flag) {
    691         curr_pic_->top_field_order_cnt = temp_pic_order_cnt;
    692         curr_pic_->bottom_field_order_cnt = temp_pic_order_cnt;
    693       } else if (slice_hdr->bottom_field_flag) {
    694         curr_pic_->bottom_field_order_cnt = temp_pic_order_cnt;
    695       } else {
    696         curr_pic_->top_field_order_cnt = temp_pic_order_cnt;
    697       }
    698       break;
    699 
    700     default:
    701       DVLOG(1) << "Invalid pic_order_cnt_type: " << sps->pic_order_cnt_type;
    702       return false;
    703   }
    704 
    705   switch (curr_pic_->field) {
    706     case H264Picture::FIELD_NONE:
    707       curr_pic_->pic_order_cnt = std::min(curr_pic_->top_field_order_cnt,
    708                                           curr_pic_->bottom_field_order_cnt);
    709       break;
    710     case H264Picture::FIELD_TOP:
    711       curr_pic_->pic_order_cnt = curr_pic_->top_field_order_cnt;
    712       break;
    713     case H264Picture::FIELD_BOTTOM:
    714       curr_pic_->pic_order_cnt = curr_pic_->bottom_field_order_cnt;
    715       break;
    716   }
    717 
    718   return true;
    719 }
    720 
    721 void VaapiH264Decoder::UpdatePicNums() {
    722   for (H264DPB::Pictures::iterator it = dpb_.begin(); it != dpb_.end(); ++it) {
    723     H264Picture* pic = *it;
    724     DCHECK(pic);
    725     if (!pic->ref)
    726       continue;
    727 
    728     // Below assumes non-interlaced stream.
    729     DCHECK_EQ(pic->field, H264Picture::FIELD_NONE);
    730     if (pic->long_term) {
    731       pic->long_term_pic_num = pic->long_term_frame_idx;
    732     } else {
    733       if (pic->frame_num > frame_num_)
    734         pic->frame_num_wrap = pic->frame_num - max_frame_num_;
    735       else
    736         pic->frame_num_wrap = pic->frame_num;
    737 
    738       pic->pic_num = pic->frame_num_wrap;
    739     }
    740   }
    741 }
    742 
    743 struct PicNumDescCompare {
    744   bool operator()(const H264Picture* a, const H264Picture* b) const {
    745     return a->pic_num > b->pic_num;
    746   }
    747 };
    748 
    749 struct LongTermPicNumAscCompare {
    750   bool operator()(const H264Picture* a, const H264Picture* b) const {
    751     return a->long_term_pic_num < b->long_term_pic_num;
    752   }
    753 };
    754 
    755 void VaapiH264Decoder::ConstructReferencePicListsP(
    756     media::H264SliceHeader* slice_hdr) {
    757   // RefPicList0 (8.2.4.2.1) [[1] [2]], where:
    758   // [1] shortterm ref pics sorted by descending pic_num,
    759   // [2] longterm ref pics by ascending long_term_pic_num.
    760   DCHECK(ref_pic_list0_.empty() && ref_pic_list1_.empty());
    761   // First get the short ref pics...
    762   dpb_.GetShortTermRefPicsAppending(ref_pic_list0_);
    763   size_t num_short_refs = ref_pic_list0_.size();
    764 
    765   // and sort them to get [1].
    766   std::sort(ref_pic_list0_.begin(), ref_pic_list0_.end(), PicNumDescCompare());
    767 
    768   // Now get long term pics and sort them by long_term_pic_num to get [2].
    769   dpb_.GetLongTermRefPicsAppending(ref_pic_list0_);
    770   std::sort(ref_pic_list0_.begin() + num_short_refs, ref_pic_list0_.end(),
    771             LongTermPicNumAscCompare());
    772 
    773   // Cut off if we have more than requested in slice header.
    774   ref_pic_list0_.resize(slice_hdr->num_ref_idx_l0_active_minus1 + 1);
    775 }
    776 
    777 struct POCAscCompare {
    778   bool operator()(const H264Picture* a, const H264Picture* b) const {
    779     return a->pic_order_cnt < b->pic_order_cnt;
    780   }
    781 };
    782 
    783 struct POCDescCompare {
    784   bool operator()(const H264Picture* a, const H264Picture* b) const {
    785     return a->pic_order_cnt > b->pic_order_cnt;
    786   }
    787 };
    788 
    789 void VaapiH264Decoder::ConstructReferencePicListsB(
    790     media::H264SliceHeader* slice_hdr) {
    791   // RefPicList0 (8.2.4.2.3) [[1] [2] [3]], where:
    792   // [1] shortterm ref pics with POC < curr_pic's POC sorted by descending POC,
    793   // [2] shortterm ref pics with POC > curr_pic's POC by ascending POC,
    794   // [3] longterm ref pics by ascending long_term_pic_num.
    795   DCHECK(ref_pic_list0_.empty() && ref_pic_list1_.empty());
    796   dpb_.GetShortTermRefPicsAppending(ref_pic_list0_);
    797   size_t num_short_refs = ref_pic_list0_.size();
    798 
    799   // First sort ascending, this will put [1] in right place and finish [2].
    800   std::sort(ref_pic_list0_.begin(), ref_pic_list0_.end(), POCAscCompare());
    801 
    802   // Find first with POC > curr_pic's POC to get first element in [2]...
    803   H264Picture::PtrVector::iterator iter;
    804   iter = std::upper_bound(ref_pic_list0_.begin(), ref_pic_list0_.end(),
    805                           curr_pic_.get(), POCAscCompare());
    806 
    807   // and sort [1] descending, thus finishing sequence [1] [2].
    808   std::sort(ref_pic_list0_.begin(), iter, POCDescCompare());
    809 
    810   // Now add [3] and sort by ascending long_term_pic_num.
    811   dpb_.GetLongTermRefPicsAppending(ref_pic_list0_);
    812   std::sort(ref_pic_list0_.begin() + num_short_refs, ref_pic_list0_.end(),
    813             LongTermPicNumAscCompare());
    814 
    815   // RefPicList1 (8.2.4.2.4) [[1] [2] [3]], where:
    816   // [1] shortterm ref pics with POC > curr_pic's POC sorted by ascending POC,
    817   // [2] shortterm ref pics with POC < curr_pic's POC by descending POC,
    818   // [3] longterm ref pics by ascending long_term_pic_num.
    819 
    820   dpb_.GetShortTermRefPicsAppending(ref_pic_list1_);
    821   num_short_refs = ref_pic_list1_.size();
    822 
    823   // First sort by descending POC.
    824   std::sort(ref_pic_list1_.begin(), ref_pic_list1_.end(), POCDescCompare());
    825 
    826   // Find first with POC < curr_pic's POC to get first element in [2]...
    827   iter = std::upper_bound(ref_pic_list1_.begin(), ref_pic_list1_.end(),
    828                           curr_pic_.get(), POCDescCompare());
    829 
    830   // and sort [1] ascending.
    831   std::sort(ref_pic_list1_.begin(), iter, POCAscCompare());
    832 
    833   // Now add [3] and sort by ascending long_term_pic_num
    834   dpb_.GetShortTermRefPicsAppending(ref_pic_list1_);
    835   std::sort(ref_pic_list1_.begin() + num_short_refs, ref_pic_list1_.end(),
    836             LongTermPicNumAscCompare());
    837 
    838   // If lists identical, swap first two entries in RefPicList1 (spec 8.2.4.2.3)
    839   if (ref_pic_list1_.size() > 1 &&
    840       std::equal(ref_pic_list0_.begin(), ref_pic_list0_.end(),
    841                  ref_pic_list1_.begin()))
    842     std::swap(ref_pic_list1_[0], ref_pic_list1_[1]);
    843 
    844   // Per 8.2.4.2 it's possible for num_ref_idx_lX_active_minus1 to indicate
    845   // there should be more ref pics on list than we constructed.
    846   // Those superfluous ones should be treated as non-reference.
    847   ref_pic_list0_.resize(slice_hdr->num_ref_idx_l0_active_minus1 + 1);
    848   ref_pic_list1_.resize(slice_hdr->num_ref_idx_l1_active_minus1 + 1);
    849 }
    850 
    851 // See 8.2.4
    852 int VaapiH264Decoder::PicNumF(H264Picture *pic) {
    853   if (!pic)
    854       return -1;
    855 
    856   if (!pic->long_term)
    857       return pic->pic_num;
    858   else
    859       return max_pic_num_;
    860 }
    861 
    862 // See 8.2.4
    863 int VaapiH264Decoder::LongTermPicNumF(H264Picture *pic) {
    864   if (pic->ref && pic->long_term)
    865     return pic->long_term_pic_num;
    866   else
    867     return 2 * (max_long_term_frame_idx_ + 1);
    868 }
    869 
    870 // Shift elements on the |v| starting from |from| to |to|, inclusive,
    871 // one position to the right and insert pic at |from|.
    872 static void ShiftRightAndInsert(H264Picture::PtrVector *v,
    873                                 int from,
    874                                 int to,
    875                                 H264Picture* pic) {
    876   // Security checks, do not disable in Debug mode.
    877   CHECK(from <= to);
    878   CHECK(to <= std::numeric_limits<int>::max() - 2);
    879   // Additional checks. Debug mode ok.
    880   DCHECK(v);
    881   DCHECK(pic);
    882   DCHECK((to + 1 == static_cast<int>(v->size())) ||
    883          (to + 2 == static_cast<int>(v->size())));
    884 
    885   v->resize(to + 2);
    886 
    887   for (int i = to + 1; i > from; --i)
    888     (*v)[i] = (*v)[i - 1];
    889 
    890   (*v)[from] = pic;
    891 }
    892 
    893 bool VaapiH264Decoder::ModifyReferencePicList(media::H264SliceHeader* slice_hdr,
    894                                               int list) {
    895   int num_ref_idx_lX_active_minus1;
    896   H264Picture::PtrVector* ref_pic_listx;
    897   media::H264ModificationOfPicNum* list_mod;
    898 
    899   // This can process either ref_pic_list0 or ref_pic_list1, depending on
    900   // the list argument. Set up pointers to proper list to be processed here.
    901   if (list == 0) {
    902     if (!slice_hdr->ref_pic_list_modification_flag_l0)
    903       return true;
    904 
    905     list_mod = slice_hdr->ref_list_l0_modifications;
    906     num_ref_idx_lX_active_minus1 = ref_pic_list0_.size() - 1;
    907 
    908     ref_pic_listx = &ref_pic_list0_;
    909   } else {
    910     if (!slice_hdr->ref_pic_list_modification_flag_l1)
    911       return true;
    912 
    913     list_mod = slice_hdr->ref_list_l1_modifications;
    914     num_ref_idx_lX_active_minus1 = ref_pic_list1_.size() - 1;
    915 
    916     ref_pic_listx = &ref_pic_list1_;
    917   }
    918 
    919   DCHECK_GE(num_ref_idx_lX_active_minus1, 0);
    920 
    921   // Spec 8.2.4.3:
    922   // Reorder pictures on the list in a way specified in the stream.
    923   int pic_num_lx_pred = curr_pic_->pic_num;
    924   int ref_idx_lx = 0;
    925   int pic_num_lx_no_wrap;
    926   int pic_num_lx;
    927   bool done = false;
    928   H264Picture* pic;
    929   for (int i = 0; i < media::H264SliceHeader::kRefListModSize && !done; ++i) {
    930     switch (list_mod->modification_of_pic_nums_idc) {
    931       case 0:
    932       case 1:
    933         // Modify short reference picture position.
    934         if (list_mod->modification_of_pic_nums_idc == 0) {
    935           // Subtract given value from predicted PicNum.
    936           pic_num_lx_no_wrap = pic_num_lx_pred -
    937               (static_cast<int>(list_mod->abs_diff_pic_num_minus1) + 1);
    938           // Wrap around max_pic_num_ if it becomes < 0 as result
    939           // of subtraction.
    940           if (pic_num_lx_no_wrap < 0)
    941             pic_num_lx_no_wrap += max_pic_num_;
    942         } else {
    943           // Add given value to predicted PicNum.
    944           pic_num_lx_no_wrap = pic_num_lx_pred +
    945               (static_cast<int>(list_mod->abs_diff_pic_num_minus1) + 1);
    946           // Wrap around max_pic_num_ if it becomes >= max_pic_num_ as result
    947           // of the addition.
    948           if (pic_num_lx_no_wrap >= max_pic_num_)
    949             pic_num_lx_no_wrap -= max_pic_num_;
    950         }
    951 
    952         // For use in next iteration.
    953         pic_num_lx_pred = pic_num_lx_no_wrap;
    954 
    955         if (pic_num_lx_no_wrap > curr_pic_->pic_num)
    956           pic_num_lx = pic_num_lx_no_wrap - max_pic_num_;
    957         else
    958           pic_num_lx = pic_num_lx_no_wrap;
    959 
    960         DCHECK_LT(num_ref_idx_lX_active_minus1 + 1,
    961                   media::H264SliceHeader::kRefListModSize);
    962         pic = dpb_.GetShortRefPicByPicNum(pic_num_lx);
    963         if (!pic) {
    964           DVLOG(1) << "Malformed stream, no pic num " << pic_num_lx;
    965           return false;
    966         }
    967         ShiftRightAndInsert(ref_pic_listx, ref_idx_lx,
    968                             num_ref_idx_lX_active_minus1, pic);
    969         ref_idx_lx++;
    970 
    971         for (int src = ref_idx_lx, dst = ref_idx_lx;
    972              src <= num_ref_idx_lX_active_minus1 + 1; ++src) {
    973           if (PicNumF((*ref_pic_listx)[src]) != pic_num_lx)
    974             (*ref_pic_listx)[dst++] = (*ref_pic_listx)[src];
    975         }
    976         break;
    977 
    978       case 2:
    979         // Modify long term reference picture position.
    980         DCHECK_LT(num_ref_idx_lX_active_minus1 + 1,
    981                   media::H264SliceHeader::kRefListModSize);
    982         pic = dpb_.GetLongRefPicByLongTermPicNum(list_mod->long_term_pic_num);
    983         if (!pic) {
    984           DVLOG(1) << "Malformed stream, no pic num "
    985                    << list_mod->long_term_pic_num;
    986           return false;
    987         }
    988         ShiftRightAndInsert(ref_pic_listx, ref_idx_lx,
    989                             num_ref_idx_lX_active_minus1, pic);
    990         ref_idx_lx++;
    991 
    992         for (int src = ref_idx_lx, dst = ref_idx_lx;
    993              src <= num_ref_idx_lX_active_minus1 + 1; ++src) {
    994           if (LongTermPicNumF((*ref_pic_listx)[src])
    995               != static_cast<int>(list_mod->long_term_pic_num))
    996             (*ref_pic_listx)[dst++] = (*ref_pic_listx)[src];
    997         }
    998         break;
    999 
   1000       case 3:
   1001         // End of modification list.
   1002         done = true;
   1003         break;
   1004 
   1005       default:
   1006         // May be recoverable.
   1007         DVLOG(1) << "Invalid modification_of_pic_nums_idc="
   1008                  << list_mod->modification_of_pic_nums_idc
   1009                  << " in position " << i;
   1010         break;
   1011     }
   1012 
   1013     ++list_mod;
   1014   }
   1015 
   1016   // Per NOTE 2 in 8.2.4.3.2, the ref_pic_listx size in the above loop is
   1017   // temporarily made one element longer than the required final list.
   1018   // Resize the list back to its required size.
   1019   ref_pic_listx->resize(num_ref_idx_lX_active_minus1 + 1);
   1020 
   1021   return true;
   1022 }
   1023 
   1024 bool VaapiH264Decoder::OutputPic(H264Picture* pic) {
   1025   DCHECK(!pic->outputted);
   1026   pic->outputted = true;
   1027   last_output_poc_ = pic->pic_order_cnt;
   1028 
   1029   DecodeSurface* dec_surface = DecodeSurfaceByPoC(pic->pic_order_cnt);
   1030   if (!dec_surface)
   1031     return false;
   1032 
   1033   DCHECK_GE(dec_surface->input_id(), 0);
   1034   DVLOG(4) << "Posting output task for POC: " << pic->pic_order_cnt
   1035            << " input_id: " << dec_surface->input_id();
   1036   output_pic_cb_.Run(dec_surface->input_id(), dec_surface->va_surface());
   1037 
   1038   return true;
   1039 }
   1040 
   1041 void VaapiH264Decoder::ClearDPB() {
   1042   // Clear DPB contents, marking the pictures as unused first.
   1043   for (H264DPB::Pictures::iterator it = dpb_.begin(); it != dpb_.end(); ++it)
   1044     UnassignSurfaceFromPoC((*it)->pic_order_cnt);
   1045 
   1046   dpb_.Clear();
   1047   last_output_poc_ = std::numeric_limits<int>::min();
   1048 }
   1049 
   1050 bool VaapiH264Decoder::OutputAllRemainingPics() {
   1051   // Output all pictures that are waiting to be outputted.
   1052   FinishPrevFrameIfPresent();
   1053   H264Picture::PtrVector to_output;
   1054   dpb_.GetNotOutputtedPicsAppending(to_output);
   1055   // Sort them by ascending POC to output in order.
   1056   std::sort(to_output.begin(), to_output.end(), POCAscCompare());
   1057 
   1058   H264Picture::PtrVector::iterator it;
   1059   for (it = to_output.begin(); it != to_output.end(); ++it) {
   1060     if (!OutputPic(*it)) {
   1061       DVLOG(1) << "Failed to output pic POC: " << (*it)->pic_order_cnt;
   1062       return false;
   1063     }
   1064   }
   1065 
   1066   return true;
   1067 }
   1068 
   1069 bool VaapiH264Decoder::Flush() {
   1070   DVLOG(2) << "Decoder flush";
   1071 
   1072   if (!OutputAllRemainingPics())
   1073     return false;
   1074 
   1075   ClearDPB();
   1076 
   1077   DCHECK(decode_surfaces_in_use_.empty());
   1078   return true;
   1079 }
   1080 
   1081 bool VaapiH264Decoder::StartNewFrame(media::H264SliceHeader* slice_hdr) {
   1082   // TODO posciak: add handling of max_num_ref_frames per spec.
   1083 
   1084   // If the new frame is an IDR, output what's left to output and clear DPB
   1085   if (slice_hdr->idr_pic_flag) {
   1086     // (unless we are explicitly instructed not to do so).
   1087     if (!slice_hdr->no_output_of_prior_pics_flag) {
   1088       // Output DPB contents.
   1089       if (!Flush())
   1090         return false;
   1091     }
   1092     dpb_.Clear();
   1093     last_output_poc_ = std::numeric_limits<int>::min();
   1094   }
   1095 
   1096   // curr_pic_ should have either been added to DPB or discarded when finishing
   1097   // the last frame. DPB is responsible for releasing that memory once it's
   1098   // not needed anymore.
   1099   DCHECK(!curr_pic_.get());
   1100   curr_pic_.reset(new H264Picture);
   1101   CHECK(curr_pic_.get());
   1102 
   1103   if (!InitCurrPicture(slice_hdr))
   1104     return false;
   1105 
   1106   DCHECK_GT(max_frame_num_, 0);
   1107 
   1108   UpdatePicNums();
   1109 
   1110   // Send parameter buffers before each new picture, before the first slice.
   1111   if (!SendPPS())
   1112     return false;
   1113 
   1114   if (!SendIQMatrix())
   1115     return false;
   1116 
   1117   if (!QueueSlice(slice_hdr))
   1118     return false;
   1119 
   1120   return true;
   1121 }
   1122 
   1123 bool VaapiH264Decoder::HandleMemoryManagementOps() {
   1124   // 8.2.5.4
   1125   for (unsigned int i = 0; i < arraysize(curr_pic_->ref_pic_marking); ++i) {
   1126     // Code below does not support interlaced stream (per-field pictures).
   1127     media::H264DecRefPicMarking* ref_pic_marking =
   1128         &curr_pic_->ref_pic_marking[i];
   1129     H264Picture* to_mark;
   1130     int pic_num_x;
   1131 
   1132     switch (ref_pic_marking->memory_mgmnt_control_operation) {
   1133       case 0:
   1134         // Normal end of operations' specification.
   1135         return true;
   1136 
   1137       case 1:
   1138         // Mark a short term reference picture as unused so it can be removed
   1139         // if outputted.
   1140         pic_num_x = curr_pic_->pic_num -
   1141             (ref_pic_marking->difference_of_pic_nums_minus1 + 1);
   1142         to_mark = dpb_.GetShortRefPicByPicNum(pic_num_x);
   1143         if (to_mark) {
   1144           to_mark->ref = false;
   1145         } else {
   1146           DVLOG(1) << "Invalid short ref pic num to unmark";
   1147           return false;
   1148         }
   1149         break;
   1150 
   1151       case 2:
   1152         // Mark a long term reference picture as unused so it can be removed
   1153         // if outputted.
   1154         to_mark = dpb_.GetLongRefPicByLongTermPicNum(
   1155             ref_pic_marking->long_term_pic_num);
   1156         if (to_mark) {
   1157           to_mark->ref = false;
   1158         } else {
   1159           DVLOG(1) << "Invalid long term ref pic num to unmark";
   1160           return false;
   1161         }
   1162         break;
   1163 
   1164       case 3:
   1165         // Mark a short term reference picture as long term reference.
   1166         pic_num_x = curr_pic_->pic_num -
   1167             (ref_pic_marking->difference_of_pic_nums_minus1 + 1);
   1168         to_mark = dpb_.GetShortRefPicByPicNum(pic_num_x);
   1169         if (to_mark) {
   1170           DCHECK(to_mark->ref && !to_mark->long_term);
   1171           to_mark->long_term = true;
   1172           to_mark->long_term_frame_idx = ref_pic_marking->long_term_frame_idx;
   1173         } else {
   1174           DVLOG(1) << "Invalid short term ref pic num to mark as long ref";
   1175           return false;
   1176         }
   1177         break;
   1178 
   1179       case 4: {
   1180         // Unmark all reference pictures with long_term_frame_idx over new max.
   1181         max_long_term_frame_idx_
   1182             = ref_pic_marking->max_long_term_frame_idx_plus1 - 1;
   1183         H264Picture::PtrVector long_terms;
   1184         dpb_.GetLongTermRefPicsAppending(long_terms);
   1185         for (size_t i = 0; i < long_terms.size(); ++i) {
   1186           H264Picture* pic = long_terms[i];
   1187           DCHECK(pic->ref && pic->long_term);
   1188           // Ok to cast, max_long_term_frame_idx is much smaller than 16bit.
   1189           if (pic->long_term_frame_idx >
   1190               static_cast<int>(max_long_term_frame_idx_))
   1191             pic->ref = false;
   1192         }
   1193         break;
   1194       }
   1195 
   1196       case 5:
   1197         // Unmark all reference pictures.
   1198         dpb_.MarkAllUnusedForRef();
   1199         max_long_term_frame_idx_ = -1;
   1200         curr_pic_->mem_mgmt_5 = true;
   1201         break;
   1202 
   1203       case 6: {
   1204         // Replace long term reference pictures with current picture.
   1205         // First unmark if any existing with this long_term_frame_idx...
   1206         H264Picture::PtrVector long_terms;
   1207         dpb_.GetLongTermRefPicsAppending(long_terms);
   1208         for (size_t i = 0; i < long_terms.size(); ++i) {
   1209           H264Picture* pic = long_terms[i];
   1210           DCHECK(pic->ref && pic->long_term);
   1211           // Ok to cast, long_term_frame_idx is much smaller than 16bit.
   1212           if (pic->long_term_frame_idx ==
   1213               static_cast<int>(ref_pic_marking->long_term_frame_idx))
   1214             pic->ref = false;
   1215         }
   1216 
   1217         // and mark the current one instead.
   1218         curr_pic_->ref = true;
   1219         curr_pic_->long_term = true;
   1220         curr_pic_->long_term_frame_idx = ref_pic_marking->long_term_frame_idx;
   1221         break;
   1222       }
   1223 
   1224       default:
   1225         // Would indicate a bug in parser.
   1226         NOTREACHED();
   1227     }
   1228   }
   1229 
   1230   return true;
   1231 }
   1232 
   1233 // This method ensures that DPB does not overflow, either by removing
   1234 // reference pictures as specified in the stream, or using a sliding window
   1235 // procedure to remove the oldest one.
   1236 // It also performs marking and unmarking pictures as reference.
   1237 // See spac 8.2.5.1.
   1238 void VaapiH264Decoder::ReferencePictureMarking() {
   1239   if (curr_pic_->idr) {
   1240     // If current picture is an IDR, all reference pictures are unmarked.
   1241     dpb_.MarkAllUnusedForRef();
   1242 
   1243     if (curr_pic_->long_term_reference_flag) {
   1244       curr_pic_->long_term = true;
   1245       curr_pic_->long_term_frame_idx = 0;
   1246       max_long_term_frame_idx_ = 0;
   1247     } else {
   1248       curr_pic_->long_term = false;
   1249       max_long_term_frame_idx_ = -1;
   1250     }
   1251   } else {
   1252     if (!curr_pic_->adaptive_ref_pic_marking_mode_flag) {
   1253       // If non-IDR, and the stream does not indicate what we should do to
   1254       // ensure DPB doesn't overflow, discard oldest picture.
   1255       // See spec 8.2.5.3.
   1256       if (curr_pic_->field == H264Picture::FIELD_NONE) {
   1257         DCHECK_LE(dpb_.CountRefPics(),
   1258             std::max<int>(parser_.GetSPS(curr_sps_id_)->max_num_ref_frames,
   1259                           1));
   1260         if (dpb_.CountRefPics() ==
   1261             std::max<int>(parser_.GetSPS(curr_sps_id_)->max_num_ref_frames,
   1262                           1)) {
   1263           // Max number of reference pics reached,
   1264           // need to remove one of the short term ones.
   1265           // Find smallest frame_num_wrap short reference picture and mark
   1266           // it as unused.
   1267           H264Picture* to_unmark = dpb_.GetLowestFrameNumWrapShortRefPic();
   1268           if (to_unmark == NULL) {
   1269             DVLOG(1) << "Couldn't find a short ref picture to unmark";
   1270             return;
   1271           }
   1272           to_unmark->ref = false;
   1273         }
   1274       } else {
   1275         // Shouldn't get here.
   1276         DVLOG(1) << "Interlaced video not supported.";
   1277         report_error_to_uma_cb_.Run(INTERLACED_STREAM);
   1278       }
   1279     } else {
   1280       // Stream has instructions how to discard pictures from DPB and how
   1281       // to mark/unmark existing reference pictures. Do it.
   1282       // Spec 8.2.5.4.
   1283       if (curr_pic_->field == H264Picture::FIELD_NONE) {
   1284         HandleMemoryManagementOps();
   1285       } else {
   1286         // Shouldn't get here.
   1287         DVLOG(1) << "Interlaced video not supported.";
   1288         report_error_to_uma_cb_.Run(INTERLACED_STREAM);
   1289       }
   1290     }
   1291   }
   1292 }
   1293 
   1294 bool VaapiH264Decoder::FinishPicture() {
   1295   DCHECK(curr_pic_.get());
   1296 
   1297   // Finish processing previous picture.
   1298   // Start by storing previous reference picture data for later use,
   1299   // if picture being finished is a reference picture.
   1300   if (curr_pic_->ref) {
   1301     ReferencePictureMarking();
   1302     prev_ref_has_memmgmnt5_ = curr_pic_->mem_mgmt_5;
   1303     prev_ref_top_field_order_cnt_ = curr_pic_->top_field_order_cnt;
   1304     prev_ref_pic_order_cnt_msb_ = curr_pic_->pic_order_cnt_msb;
   1305     prev_ref_pic_order_cnt_lsb_ = curr_pic_->pic_order_cnt_lsb;
   1306     prev_ref_field_ = curr_pic_->field;
   1307   }
   1308   prev_has_memmgmnt5_ = curr_pic_->mem_mgmt_5;
   1309   prev_frame_num_offset_ = curr_pic_->frame_num_offset;
   1310 
   1311   // Remove unused (for reference or later output) pictures from DPB, marking
   1312   // them as such.
   1313   for (H264DPB::Pictures::iterator it = dpb_.begin(); it != dpb_.end(); ++it) {
   1314     if ((*it)->outputted && !(*it)->ref)
   1315       UnassignSurfaceFromPoC((*it)->pic_order_cnt);
   1316   }
   1317   dpb_.DeleteUnused();
   1318 
   1319   DVLOG(4) << "Finishing picture, entries in DPB: " << dpb_.size();
   1320 
   1321   // Whatever happens below, curr_pic_ will stop managing the pointer to the
   1322   // picture after this function returns. The ownership will either be
   1323   // transferred to DPB, if the image is still needed (for output and/or
   1324   // reference), or the memory will be released if we manage to output it here
   1325   // without having to store it for future reference.
   1326   scoped_ptr<H264Picture> pic(curr_pic_.release());
   1327 
   1328   // Get all pictures that haven't been outputted yet.
   1329   H264Picture::PtrVector not_outputted;
   1330   // TODO(posciak): pass as pointer, not reference (violates coding style).
   1331   dpb_.GetNotOutputtedPicsAppending(not_outputted);
   1332   // Include the one we've just decoded.
   1333   not_outputted.push_back(pic.get());
   1334 
   1335   // Sort in output order.
   1336   std::sort(not_outputted.begin(), not_outputted.end(), POCAscCompare());
   1337 
   1338   // Try to output as many pictures as we can. A picture can be output,
   1339   // if the number of decoded and not yet outputted pictures that would remain
   1340   // in DPB afterwards would at least be equal to max_num_reorder_frames.
   1341   // If the outputted picture is not a reference picture, it doesn't have
   1342   // to remain in the DPB and can be removed.
   1343   H264Picture::PtrVector::iterator output_candidate = not_outputted.begin();
   1344   size_t num_remaining = not_outputted.size();
   1345   while (num_remaining > max_num_reorder_frames_) {
   1346     int poc = (*output_candidate)->pic_order_cnt;
   1347     DCHECK_GE(poc, last_output_poc_);
   1348     if (!OutputPic(*output_candidate))
   1349       return false;
   1350 
   1351     if (!(*output_candidate)->ref) {
   1352       // Current picture hasn't been inserted into DPB yet, so don't remove it
   1353       // if we managed to output it immediately.
   1354       if (*output_candidate != pic)
   1355         dpb_.DeleteByPOC(poc);
   1356       // Mark as unused.
   1357       UnassignSurfaceFromPoC(poc);
   1358     }
   1359 
   1360     ++output_candidate;
   1361     --num_remaining;
   1362   }
   1363 
   1364   // If we haven't managed to output the picture that we just decoded, or if
   1365   // it's a reference picture, we have to store it in DPB.
   1366   if (!pic->outputted || pic->ref) {
   1367     if (dpb_.IsFull()) {
   1368       // If we haven't managed to output anything to free up space in DPB
   1369       // to store this picture, it's an error in the stream.
   1370       DVLOG(1) << "Could not free up space in DPB!";
   1371       return false;
   1372     }
   1373 
   1374     dpb_.StorePic(pic.release());
   1375   }
   1376 
   1377   return true;
   1378 }
   1379 
   1380 static int LevelToMaxDpbMbs(int level) {
   1381   // See table A-1 in spec.
   1382   switch (level) {
   1383     case 10: return 396;
   1384     case 11: return 900;
   1385     case 12: //  fallthrough
   1386     case 13: //  fallthrough
   1387     case 20: return 2376;
   1388     case 21: return 4752;
   1389     case 22: //  fallthrough
   1390     case 30: return 8100;
   1391     case 31: return 18000;
   1392     case 32: return 20480;
   1393     case 40: //  fallthrough
   1394     case 41: return 32768;
   1395     case 42: return 34816;
   1396     case 50: return 110400;
   1397     case 51: //  fallthrough
   1398     case 52: return 184320;
   1399     default:
   1400       DVLOG(1) << "Invalid codec level (" << level << ")";
   1401       return 0;
   1402   }
   1403 }
   1404 
   1405 bool VaapiH264Decoder::UpdateMaxNumReorderFrames(const media::H264SPS* sps) {
   1406   if (sps->vui_parameters_present_flag && sps->bitstream_restriction_flag) {
   1407     max_num_reorder_frames_ =
   1408         base::checked_cast<size_t>(sps->max_num_reorder_frames);
   1409     if (max_num_reorder_frames_ > dpb_.max_num_pics()) {
   1410       DVLOG(1)
   1411           << "max_num_reorder_frames present, but larger than MaxDpbFrames ("
   1412           << max_num_reorder_frames_ << " > " << dpb_.max_num_pics() << ")";
   1413       max_num_reorder_frames_ = 0;
   1414       return false;
   1415     }
   1416     return true;
   1417   }
   1418 
   1419   // max_num_reorder_frames not present, infer from profile/constraints
   1420   // (see VUI semantics in spec).
   1421   if (sps->constraint_set3_flag) {
   1422     switch (sps->profile_idc) {
   1423       case 44:
   1424       case 86:
   1425       case 100:
   1426       case 110:
   1427       case 122:
   1428       case 244:
   1429         max_num_reorder_frames_ = 0;
   1430         break;
   1431       default:
   1432         max_num_reorder_frames_ = dpb_.max_num_pics();
   1433         break;
   1434     }
   1435   } else {
   1436     max_num_reorder_frames_ = dpb_.max_num_pics();
   1437   }
   1438 
   1439   return true;
   1440 }
   1441 
   1442 bool VaapiH264Decoder::ProcessSPS(int sps_id, bool* need_new_buffers) {
   1443   const media::H264SPS* sps = parser_.GetSPS(sps_id);
   1444   DCHECK(sps);
   1445   DVLOG(4) << "Processing SPS";
   1446 
   1447   *need_new_buffers = false;
   1448 
   1449   if (sps->frame_mbs_only_flag == 0) {
   1450     DVLOG(1) << "frame_mbs_only_flag != 1 not supported";
   1451     report_error_to_uma_cb_.Run(FRAME_MBS_ONLY_FLAG_NOT_ONE);
   1452     return false;
   1453   }
   1454 
   1455   if (sps->gaps_in_frame_num_value_allowed_flag) {
   1456     DVLOG(1) << "Gaps in frame numbers not supported";
   1457     report_error_to_uma_cb_.Run(GAPS_IN_FRAME_NUM);
   1458     return false;
   1459   }
   1460 
   1461   curr_sps_id_ = sps->seq_parameter_set_id;
   1462 
   1463   // Calculate picture height/width in macroblocks and pixels
   1464   // (spec 7.4.2.1.1, 7.4.3).
   1465   int width_mb = sps->pic_width_in_mbs_minus1 + 1;
   1466   int height_mb = (2 - sps->frame_mbs_only_flag) *
   1467       (sps->pic_height_in_map_units_minus1 + 1);
   1468 
   1469   gfx::Size new_pic_size(16 * width_mb, 16 * height_mb);
   1470   if (new_pic_size.IsEmpty()) {
   1471     DVLOG(1) << "Invalid picture size: " << new_pic_size.ToString();
   1472     return false;
   1473   }
   1474 
   1475   if (!pic_size_.IsEmpty() && new_pic_size == pic_size_) {
   1476     // Already have surfaces and this SPS keeps the same resolution,
   1477     // no need to request a new set.
   1478     return true;
   1479   }
   1480 
   1481   pic_size_ = new_pic_size;
   1482   DVLOG(1) << "New picture size: " << pic_size_.ToString();
   1483 
   1484   max_pic_order_cnt_lsb_ = 1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4);
   1485   max_frame_num_ = 1 << (sps->log2_max_frame_num_minus4 + 4);
   1486 
   1487   int level = sps->level_idc;
   1488   int max_dpb_mbs = LevelToMaxDpbMbs(level);
   1489   if (max_dpb_mbs == 0)
   1490     return false;
   1491 
   1492   size_t max_dpb_size = std::min(max_dpb_mbs / (width_mb * height_mb),
   1493                                  static_cast<int>(H264DPB::kDPBMaxSize));
   1494   DVLOG(1) << "Codec level: " << level << ", DPB size: " << max_dpb_size;
   1495   if (max_dpb_size == 0) {
   1496     DVLOG(1) << "Invalid DPB Size";
   1497     return false;
   1498   }
   1499 
   1500   dpb_.set_max_num_pics(max_dpb_size);
   1501 
   1502   if (!UpdateMaxNumReorderFrames(sps))
   1503     return false;
   1504   DVLOG(1) << "max_num_reorder_frames: " << max_num_reorder_frames_;
   1505 
   1506   *need_new_buffers = true;
   1507   return true;
   1508 }
   1509 
   1510 bool VaapiH264Decoder::ProcessPPS(int pps_id) {
   1511   const media::H264PPS* pps = parser_.GetPPS(pps_id);
   1512   DCHECK(pps);
   1513 
   1514   curr_pps_id_ = pps->pic_parameter_set_id;
   1515 
   1516   return true;
   1517 }
   1518 
   1519 bool VaapiH264Decoder::FinishPrevFrameIfPresent() {
   1520   // If we already have a frame waiting to be decoded, decode it and finish.
   1521   if (curr_pic_ != NULL) {
   1522     if (!DecodePicture())
   1523       return false;
   1524     return FinishPicture();
   1525   }
   1526 
   1527   return true;
   1528 }
   1529 
   1530 bool VaapiH264Decoder::ProcessSlice(media::H264SliceHeader* slice_hdr) {
   1531   prev_frame_num_ = frame_num_;
   1532   frame_num_ = slice_hdr->frame_num;
   1533 
   1534   if (prev_frame_num_ > 0 && prev_frame_num_ < frame_num_ - 1) {
   1535     DVLOG(1) << "Gap in frame_num!";
   1536     report_error_to_uma_cb_.Run(GAPS_IN_FRAME_NUM);
   1537     return false;
   1538   }
   1539 
   1540   if (slice_hdr->field_pic_flag == 0)
   1541     max_pic_num_ = max_frame_num_;
   1542   else
   1543     max_pic_num_ = 2 * max_frame_num_;
   1544 
   1545   // TODO posciak: switch to new picture detection per 7.4.1.2.4.
   1546   if (curr_pic_ != NULL && slice_hdr->first_mb_in_slice != 0) {
   1547     // This is just some more slice data of the current picture, so
   1548     // just queue it and return.
   1549     QueueSlice(slice_hdr);
   1550     return true;
   1551   } else {
   1552     // A new frame, so first finish the previous one before processing it...
   1553     if (!FinishPrevFrameIfPresent())
   1554       return false;
   1555 
   1556     // and then start a new one.
   1557     return StartNewFrame(slice_hdr);
   1558   }
   1559 }
   1560 
   1561 #define SET_ERROR_AND_RETURN()             \
   1562   do {                                     \
   1563     DVLOG(1) << "Error during decode";     \
   1564     state_ = kError;                       \
   1565     return VaapiH264Decoder::kDecodeError; \
   1566   } while (0)
   1567 
   1568 void VaapiH264Decoder::SetStream(const uint8* ptr,
   1569                                  size_t size,
   1570                                  int32 input_id) {
   1571   DCHECK(ptr);
   1572   DCHECK(size);
   1573 
   1574   // Got new input stream data from the client.
   1575   DVLOG(4) << "New input stream id: " << input_id << " at: " << (void*) ptr
   1576            << " size:  " << size;
   1577   parser_.SetStream(ptr, size);
   1578   curr_input_id_ = input_id;
   1579 }
   1580 
   1581 VaapiH264Decoder::DecResult VaapiH264Decoder::Decode() {
   1582   media::H264Parser::Result par_res;
   1583   media::H264NALU nalu;
   1584   DCHECK_NE(state_, kError);
   1585 
   1586   while (1) {
   1587     // If we've already decoded some of the stream (after reset, i.e. we are
   1588     // not in kNeedStreamMetadata state), we may be able to go back into
   1589     // decoding state not only starting at/resuming from an SPS, but also from
   1590     // other resume points, such as IDRs. In the latter case we need an output
   1591     // surface, because we will end up decoding that IDR in the process.
   1592     // Otherwise we just look for an SPS and don't produce any output frames.
   1593     if (state_ != kNeedStreamMetadata && available_va_surfaces_.empty()) {
   1594       DVLOG(4) << "No output surfaces available";
   1595       return kRanOutOfSurfaces;
   1596     }
   1597 
   1598     par_res = parser_.AdvanceToNextNALU(&nalu);
   1599     if (par_res == media::H264Parser::kEOStream)
   1600       return kRanOutOfStreamData;
   1601     else if (par_res != media::H264Parser::kOk)
   1602       SET_ERROR_AND_RETURN();
   1603 
   1604     DVLOG(4) << "NALU found: " << static_cast<int>(nalu.nal_unit_type);
   1605 
   1606     switch (nalu.nal_unit_type) {
   1607       case media::H264NALU::kNonIDRSlice:
   1608         // We can't resume from a non-IDR slice.
   1609         if (state_ != kDecoding)
   1610           break;
   1611         // else fallthrough
   1612       case media::H264NALU::kIDRSlice: {
   1613         // TODO(posciak): the IDR may require an SPS that we don't have
   1614         // available. For now we'd fail if that happens, but ideally we'd like
   1615         // to keep going until the next SPS in the stream.
   1616         if (state_ == kNeedStreamMetadata) {
   1617           // We need an SPS, skip this IDR and keep looking.
   1618           break;
   1619         }
   1620 
   1621         // If after reset, we should be able to recover from an IDR.
   1622         media::H264SliceHeader slice_hdr;
   1623 
   1624         par_res = parser_.ParseSliceHeader(nalu, &slice_hdr);
   1625         if (par_res != media::H264Parser::kOk)
   1626           SET_ERROR_AND_RETURN();
   1627 
   1628         if (!ProcessSlice(&slice_hdr))
   1629           SET_ERROR_AND_RETURN();
   1630 
   1631         state_ = kDecoding;
   1632         break;
   1633       }
   1634 
   1635       case media::H264NALU::kSPS: {
   1636         int sps_id;
   1637 
   1638         if (!FinishPrevFrameIfPresent())
   1639           SET_ERROR_AND_RETURN();
   1640 
   1641         par_res = parser_.ParseSPS(&sps_id);
   1642         if (par_res != media::H264Parser::kOk)
   1643           SET_ERROR_AND_RETURN();
   1644 
   1645         bool need_new_buffers = false;
   1646         if (!ProcessSPS(sps_id, &need_new_buffers))
   1647           SET_ERROR_AND_RETURN();
   1648 
   1649         state_ = kDecoding;
   1650 
   1651         if (need_new_buffers) {
   1652           if (!Flush())
   1653             return kDecodeError;
   1654 
   1655           available_va_surfaces_.clear();
   1656           return kAllocateNewSurfaces;
   1657         }
   1658         break;
   1659       }
   1660 
   1661       case media::H264NALU::kPPS: {
   1662         if (state_ != kDecoding)
   1663           break;
   1664 
   1665         int pps_id;
   1666 
   1667         if (!FinishPrevFrameIfPresent())
   1668           SET_ERROR_AND_RETURN();
   1669 
   1670         par_res = parser_.ParsePPS(&pps_id);
   1671         if (par_res != media::H264Parser::kOk)
   1672           SET_ERROR_AND_RETURN();
   1673 
   1674         if (!ProcessPPS(pps_id))
   1675           SET_ERROR_AND_RETURN();
   1676         break;
   1677       }
   1678 
   1679       default:
   1680         DVLOG(4) << "Skipping NALU type: " << nalu.nal_unit_type;
   1681         break;
   1682     }
   1683   }
   1684 }
   1685 
   1686 size_t VaapiH264Decoder::GetRequiredNumOfPictures() {
   1687   return dpb_.max_num_pics() + kPicsInPipeline;
   1688 }
   1689 
   1690 }  // namespace content
   1691