Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / content / common / gpu / media / vaapi_h264_decoder.cc
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       case media::H264NALU::kAUD:
1680       case media::H264NALU::kEOSeq:
1681       case media::H264NALU::kEOStream:
1682         if (state_ != kDecoding)
1683           break;
1684         if (!FinishPrevFrameIfPresent())
1685           SET_ERROR_AND_RETURN();
1686
1687         break;
1688
1689       default:
1690         DVLOG(4) << "Skipping NALU type: " << nalu.nal_unit_type;
1691         break;
1692     }
1693   }
1694 }
1695
1696 size_t VaapiH264Decoder::GetRequiredNumOfPictures() {
1697   return dpb_.max_num_pics() + kPicsInPipeline;
1698 }
1699
1700 }  // namespace content