- add sources.
[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/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     int poc = (*output_candidate)->pic_order_cnt;
1337     DCHECK_GE(poc, last_output_poc_);
1338     if (!OutputPic(*output_candidate))
1339       return false;
1340
1341     if (!(*output_candidate)->ref) {
1342       // Current picture hasn't been inserted into DPB yet, so don't remove it
1343       // if we managed to output it immediately.
1344       if (*output_candidate != pic)
1345         dpb_.DeleteByPOC(poc);
1346       // Mark as unused.
1347       UnassignSurfaceFromPoC(poc);
1348     }
1349   }
1350
1351   // If we haven't managed to output the picture that we just decoded, or if
1352   // it's a reference picture, we have to store it in DPB.
1353   if (!pic->outputted || pic->ref) {
1354     if (dpb_.IsFull()) {
1355       // If we haven't managed to output anything to free up space in DPB
1356       // to store this picture, it's an error in the stream.
1357       DVLOG(1) << "Could not free up space in DPB!";
1358       return false;
1359     }
1360
1361     dpb_.StorePic(pic.release());
1362   }
1363
1364   return true;
1365 }
1366
1367 static int LevelToMaxDpbMbs(int level) {
1368   // See table A-1 in spec.
1369   switch (level) {
1370     case 10: return 396;
1371     case 11: return 900;
1372     case 12: //  fallthrough
1373     case 13: //  fallthrough
1374     case 20: return 2376;
1375     case 21: return 4752;
1376     case 22: //  fallthrough
1377     case 30: return 8100;
1378     case 31: return 18000;
1379     case 32: return 20480;
1380     case 40: //  fallthrough
1381     case 41: return 32768;
1382     case 42: return 34816;
1383     case 50: return 110400;
1384     case 51: //  fallthrough
1385     case 52: return 184320;
1386     default:
1387       DVLOG(1) << "Invalid codec level (" << level << ")";
1388       return 0;
1389   }
1390 }
1391
1392 bool VaapiH264Decoder::ProcessSPS(int sps_id, bool* need_new_buffers) {
1393   const H264SPS* sps = parser_.GetSPS(sps_id);
1394   DCHECK(sps);
1395   DVLOG(4) << "Processing SPS";
1396
1397   *need_new_buffers = false;
1398
1399   if (sps->frame_mbs_only_flag == 0) {
1400     DVLOG(1) << "frame_mbs_only_flag != 1 not supported";
1401     report_error_to_uma_cb_.Run(FRAME_MBS_ONLY_FLAG_NOT_ONE);
1402     return false;
1403   }
1404
1405   if (sps->gaps_in_frame_num_value_allowed_flag) {
1406     DVLOG(1) << "Gaps in frame numbers not supported";
1407     report_error_to_uma_cb_.Run(GAPS_IN_FRAME_NUM);
1408     return false;
1409   }
1410
1411   curr_sps_id_ = sps->seq_parameter_set_id;
1412
1413   // Calculate picture height/width in macroblocks and pixels
1414   // (spec 7.4.2.1.1, 7.4.3).
1415   int width_mb = sps->pic_width_in_mbs_minus1 + 1;
1416   int height_mb = (2 - sps->frame_mbs_only_flag) *
1417       (sps->pic_height_in_map_units_minus1 + 1);
1418
1419   gfx::Size new_pic_size(16 * width_mb, 16 * height_mb);
1420   if (new_pic_size.IsEmpty()) {
1421     DVLOG(1) << "Invalid picture size: " << new_pic_size.ToString();
1422     return false;
1423   }
1424
1425   if (!pic_size_.IsEmpty() && new_pic_size == pic_size_) {
1426     // Already have surfaces and this SPS keeps the same resolution,
1427     // no need to request a new set.
1428     return true;
1429   }
1430
1431   pic_size_ = new_pic_size;
1432   DVLOG(1) << "New picture size: " << pic_size_.ToString();
1433
1434   max_pic_order_cnt_lsb_ = 1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4);
1435   max_frame_num_ = 1 << (sps->log2_max_frame_num_minus4 + 4);
1436
1437   int level = sps->level_idc;
1438   int max_dpb_mbs = LevelToMaxDpbMbs(level);
1439   if (max_dpb_mbs == 0)
1440     return false;
1441
1442   size_t max_dpb_size = std::min(max_dpb_mbs / (width_mb * height_mb),
1443                                  static_cast<int>(H264DPB::kDPBMaxSize));
1444   DVLOG(1) << "Codec level: " << level << ", DPB size: " << max_dpb_size;
1445   if (max_dpb_size == 0) {
1446     DVLOG(1) << "Invalid DPB Size";
1447     return false;
1448   }
1449
1450   dpb_.set_max_num_pics(max_dpb_size);
1451
1452   *need_new_buffers = true;
1453   return true;
1454 }
1455
1456 bool VaapiH264Decoder::ProcessPPS(int pps_id) {
1457   const H264PPS* pps = parser_.GetPPS(pps_id);
1458   DCHECK(pps);
1459
1460   curr_pps_id_ = pps->pic_parameter_set_id;
1461
1462   return true;
1463 }
1464
1465 bool VaapiH264Decoder::FinishPrevFrameIfPresent() {
1466   // If we already have a frame waiting to be decoded, decode it and finish.
1467   if (curr_pic_ != NULL) {
1468     if (!DecodePicture())
1469       return false;
1470     return FinishPicture();
1471   }
1472
1473   return true;
1474 }
1475
1476 bool VaapiH264Decoder::ProcessSlice(H264SliceHeader* slice_hdr) {
1477   prev_frame_num_ = frame_num_;
1478   frame_num_ = slice_hdr->frame_num;
1479
1480   if (prev_frame_num_ > 0 && prev_frame_num_ < frame_num_ - 1) {
1481     DVLOG(1) << "Gap in frame_num!";
1482     report_error_to_uma_cb_.Run(GAPS_IN_FRAME_NUM);
1483     return false;
1484   }
1485
1486   if (slice_hdr->field_pic_flag == 0)
1487     max_pic_num_ = max_frame_num_;
1488   else
1489     max_pic_num_ = 2 * max_frame_num_;
1490
1491   // TODO posciak: switch to new picture detection per 7.4.1.2.4.
1492   if (curr_pic_ != NULL && slice_hdr->first_mb_in_slice != 0) {
1493     // This is just some more slice data of the current picture, so
1494     // just queue it and return.
1495     QueueSlice(slice_hdr);
1496     return true;
1497   } else {
1498     // A new frame, so first finish the previous one before processing it...
1499     if (!FinishPrevFrameIfPresent())
1500       return false;
1501
1502     // and then start a new one.
1503     return StartNewFrame(slice_hdr);
1504   }
1505 }
1506
1507 #define SET_ERROR_AND_RETURN()             \
1508   do {                                     \
1509     DVLOG(1) << "Error during decode";     \
1510     state_ = kError;                       \
1511     return VaapiH264Decoder::kDecodeError; \
1512   } while (0)
1513
1514 void VaapiH264Decoder::SetStream(uint8* ptr, size_t size, int32 input_id) {
1515   DCHECK(ptr);
1516   DCHECK(size);
1517
1518   // Got new input stream data from the client.
1519   DVLOG(4) << "New input stream id: " << input_id << " at: " << (void*) ptr
1520            << " size:  " << size;
1521   parser_.SetStream(ptr, size);
1522   curr_input_id_ = input_id;
1523 }
1524
1525 VaapiH264Decoder::DecResult VaapiH264Decoder::Decode() {
1526   H264Parser::Result par_res;
1527   H264NALU nalu;
1528   DCHECK_NE(state_, kError);
1529
1530   while (1) {
1531     // If we've already decoded some of the stream (after reset, i.e. we are
1532     // not in kNeedStreamMetadata state), we may be able to go back into
1533     // decoding state not only starting at/resuming from an SPS, but also from
1534     // other resume points, such as IDRs. In the latter case we need an output
1535     // surface, because we will end up decoding that IDR in the process.
1536     // Otherwise we just look for an SPS and don't produce any output frames.
1537     if (state_ != kNeedStreamMetadata && available_va_surfaces_.empty()) {
1538       DVLOG(4) << "No output surfaces available";
1539       return kRanOutOfSurfaces;
1540     }
1541
1542     par_res = parser_.AdvanceToNextNALU(&nalu);
1543     if (par_res == H264Parser::kEOStream)
1544       return kRanOutOfStreamData;
1545     else if (par_res != H264Parser::kOk)
1546       SET_ERROR_AND_RETURN();
1547
1548     DVLOG(4) << "NALU found: " << static_cast<int>(nalu.nal_unit_type);
1549
1550     switch (nalu.nal_unit_type) {
1551       case H264NALU::kNonIDRSlice:
1552         // We can't resume from a non-IDR slice.
1553         if (state_ != kDecoding)
1554           break;
1555         // else fallthrough
1556       case H264NALU::kIDRSlice: {
1557         // TODO(posciak): the IDR may require an SPS that we don't have
1558         // available. For now we'd fail if that happens, but ideally we'd like
1559         // to keep going until the next SPS in the stream.
1560         if (state_ == kNeedStreamMetadata) {
1561           // We need an SPS, skip this IDR and keep looking.
1562           break;
1563         }
1564
1565         // If after reset, we should be able to recover from an IDR.
1566         H264SliceHeader slice_hdr;
1567
1568         par_res = parser_.ParseSliceHeader(nalu, &slice_hdr);
1569         if (par_res != H264Parser::kOk)
1570           SET_ERROR_AND_RETURN();
1571
1572         if (!ProcessSlice(&slice_hdr))
1573           SET_ERROR_AND_RETURN();
1574
1575         state_ = kDecoding;
1576         break;
1577       }
1578
1579       case H264NALU::kSPS: {
1580         int sps_id;
1581
1582         if (!FinishPrevFrameIfPresent())
1583           SET_ERROR_AND_RETURN();
1584
1585         par_res = parser_.ParseSPS(&sps_id);
1586         if (par_res != H264Parser::kOk)
1587           SET_ERROR_AND_RETURN();
1588
1589         bool need_new_buffers = false;
1590         if (!ProcessSPS(sps_id, &need_new_buffers))
1591           SET_ERROR_AND_RETURN();
1592
1593         state_ = kDecoding;
1594
1595         if (need_new_buffers) {
1596           if (!Flush())
1597             return kDecodeError;
1598
1599           available_va_surfaces_.clear();
1600           return kAllocateNewSurfaces;
1601         }
1602         break;
1603       }
1604
1605       case H264NALU::kPPS: {
1606         if (state_ != kDecoding)
1607           break;
1608
1609         int pps_id;
1610
1611         if (!FinishPrevFrameIfPresent())
1612           SET_ERROR_AND_RETURN();
1613
1614         par_res = parser_.ParsePPS(&pps_id);
1615         if (par_res != H264Parser::kOk)
1616           SET_ERROR_AND_RETURN();
1617
1618         if (!ProcessPPS(pps_id))
1619           SET_ERROR_AND_RETURN();
1620         break;
1621       }
1622
1623       default:
1624         DVLOG(4) << "Skipping NALU type: " << nalu.nal_unit_type;;
1625         break;
1626     }
1627   }
1628 }
1629
1630 size_t VaapiH264Decoder::GetRequiredNumOfPictures() {
1631   return dpb_.max_num_pics() + kPicsInPipeline;
1632 }
1633
1634 }  // namespace content