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