15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <limits>
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h"
10a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/numerics/safe_conversions.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/gpu/media/vaapi_h264_decoder.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content {
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Decode surface, used for decoding and reference. input_id comes from client
17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// and is associated with the surface that was produced as the result
18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// of decoding a bitstream buffer with that id.
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class VaapiH264Decoder::DecodeSurface {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DecodeSurface(int poc,
22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                int32 input_id,
23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                const scoped_refptr<VASurface>& va_surface);
24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DecodeSurface(int poc, const scoped_refptr<DecodeSurface>& dec_surface);
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~DecodeSurface();
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int poc() {
28868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return poc_;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_refptr<VASurface> va_surface() {
32868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return va_surface_;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 input_id() {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return input_id_;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int poc_;
41868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int32 input_id_;
42868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_refptr<VASurface> va_surface_;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)VaapiH264Decoder::DecodeSurface::DecodeSurface(
46868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int poc,
47868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int32 input_id,
48868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const scoped_refptr<VASurface>& va_surface)
49868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    : poc_(poc),
50868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      input_id_(input_id),
51868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      va_surface_(va_surface) {
52868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(va_surface_.get());
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)VaapiH264Decoder::DecodeSurface::~DecodeSurface() {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
58868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)VaapiH264Decoder::VaapiH264Decoder(
59868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    VaapiWrapper* vaapi_wrapper,
60868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const OutputPicCB& output_pic_cb,
61868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const ReportErrorToUmaCB& report_error_to_uma_cb)
62868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    : max_pic_order_cnt_lsb_(0),
63868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      max_frame_num_(0),
64868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      max_pic_num_(0),
65868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      max_long_term_frame_idx_(0),
66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      max_num_reorder_frames_(0),
67868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      curr_sps_id_(-1),
68868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      curr_pps_id_(-1),
69868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      vaapi_wrapper_(vaapi_wrapper),
70868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      output_pic_cb_(output_pic_cb),
71868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      report_error_to_uma_cb_(report_error_to_uma_cb) {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Reset();
73868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  state_ = kNeedStreamMetadata;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)VaapiH264Decoder::~VaapiH264Decoder() {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VaapiH264Decoder::Reset() {
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  curr_pic_.reset();
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
82868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  curr_input_id_ = -1;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  frame_num_ = 0;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  prev_frame_num_ = -1;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  prev_frame_num_offset_ = -1;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  prev_ref_has_memmgmnt5_ = false;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  prev_ref_top_field_order_cnt_ = -1;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  prev_ref_pic_order_cnt_msb_ = -1;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  prev_ref_pic_order_cnt_lsb_ = -1;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  prev_ref_field_ = H264Picture::FIELD_NONE;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
93868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  vaapi_wrapper_->DestroyPendingBuffers();
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ref_pic_list0_.clear();
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ref_pic_list1_.clear();
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
98868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (DecSurfacesInUse::iterator it = decode_surfaces_in_use_.begin();
99868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)       it != decode_surfaces_in_use_.end(); ) {
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int poc = it->second->poc();
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Must be incremented before UnassignSurfaceFromPoC as this call
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // invalidates |it|.
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++it;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UnassignSurfaceFromPoC(poc);
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
106868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(decode_surfaces_in_use_.empty());
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dpb_.Clear();
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parser_.Reset();
110a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  last_output_poc_ = std::numeric_limits<int>::min();
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
112a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // If we are in kDecoding, we can resume without processing an SPS.
113a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (state_ == kDecoding)
114a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    state_ = kAfterReset;
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
117868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void VaapiH264Decoder::ReuseSurface(
118868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const scoped_refptr<VASurface>& va_surface) {
119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  available_va_surfaces_.push_back(va_surface);
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Fill |va_pic| with default/neutral values.
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void InitVAPicture(VAPictureH264* va_pic) {
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(va_pic, 0, sizeof(*va_pic));
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  va_pic->picture_id = VA_INVALID_ID;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  va_pic->flags = VA_PICTURE_H264_INVALID;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VaapiH264Decoder::FillVAPicture(VAPictureH264 *va_pic, H264Picture* pic) {
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(pic);
131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
132868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DecodeSurface* dec_surface = DecodeSurfaceByPoC(pic->pic_order_cnt);
133868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!dec_surface) {
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Cannot provide a ref picture, will corrupt output, but may be able
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // to recover.
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InitVAPicture(va_pic);
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
140868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  va_pic->picture_id = dec_surface->va_surface()->id();
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  va_pic->frame_idx = pic->frame_num;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  va_pic->flags = 0;
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (pic->field) {
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case H264Picture::FIELD_NONE:
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case H264Picture::FIELD_TOP:
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      va_pic->flags |= VA_PICTURE_H264_TOP_FIELD;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case H264Picture::FIELD_BOTTOM:
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      va_pic->flags |= VA_PICTURE_H264_BOTTOM_FIELD;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pic->ref) {
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    va_pic->flags |= pic->long_term ? VA_PICTURE_H264_LONG_TERM_REFERENCE
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    : VA_PICTURE_H264_SHORT_TERM_REFERENCE;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  va_pic->TopFieldOrderCnt = pic->top_field_order_cnt;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  va_pic->BottomFieldOrderCnt = pic->bottom_field_order_cnt;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int VaapiH264Decoder::FillVARefFramesFromDPB(VAPictureH264 *va_pics,
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             int num_pics) {
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  H264DPB::Pictures::reverse_iterator rit;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Return reference frames in reverse order of insertion.
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Libva does not document this, but other implementations (e.g. mplayer)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // do it this way as well.
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (rit = dpb_.rbegin(), i = 0; rit != dpb_.rend() && i < num_pics; ++rit) {
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((*rit)->ref)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FillVAPicture(&va_pics[i++], *rit);
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return i;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
180868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)VaapiH264Decoder::DecodeSurface* VaapiH264Decoder::DecodeSurfaceByPoC(int poc) {
181868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DecSurfacesInUse::iterator iter = decode_surfaces_in_use_.find(poc);
182868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (iter == decode_surfaces_in_use_.end()) {
183868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DVLOG(1) << "Could not find surface assigned to POC: " << poc;
184868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return NULL;
185868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
187868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return iter->second.get();
188868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
190868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool VaapiH264Decoder::AssignSurfaceToPoC(int32 input_id, int poc) {
191868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (available_va_surfaces_.empty()) {
192868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DVLOG(1) << "No VA Surfaces available";
193868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
196868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  linked_ptr<DecodeSurface> dec_surface(new DecodeSurface(
197868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      poc, input_id, available_va_surfaces_.back()));
198868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  available_va_surfaces_.pop_back();
199868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
200868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DVLOG(4) << "POC " << poc
201868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)           << " will use surface " << dec_surface->va_surface()->id();
202868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
203868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool inserted = decode_surfaces_in_use_.insert(
204868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      std::make_pair(poc, dec_surface)).second;
205868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(inserted);
206868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
207868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return true;
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VaapiH264Decoder::UnassignSurfaceFromPoC(int poc) {
211868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DecSurfacesInUse::iterator it = decode_surfaces_in_use_.find(poc);
212868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (it == decode_surfaces_in_use_.end()) {
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "Asked to unassign an unassigned POC " << poc;
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
216868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
217868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DVLOG(4) << "POC " << poc << " no longer using VA surface "
218868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)           << it->second->va_surface()->id();
219868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
220868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  decode_surfaces_in_use_.erase(it);
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VaapiH264Decoder::SendPPS() {
2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const media::H264PPS* pps = parser_.GetPPS(curr_pps_id_);
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(pps);
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const media::H264SPS* sps = parser_.GetSPS(pps->seq_parameter_set_id);
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(sps);
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(curr_pic_.get());
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VAPictureParameterBufferH264 pic_param;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&pic_param, 0, sizeof(VAPictureParameterBufferH264));
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define FROM_SPS_TO_PP(a) pic_param.a = sps->a;
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define FROM_SPS_TO_PP2(a, b) pic_param.b = sps->a;
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FROM_SPS_TO_PP2(pic_width_in_mbs_minus1, picture_width_in_mbs_minus1);
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This assumes non-interlaced video
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FROM_SPS_TO_PP2(pic_height_in_map_units_minus1,
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  picture_height_in_mbs_minus1);
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FROM_SPS_TO_PP(bit_depth_luma_minus8);
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FROM_SPS_TO_PP(bit_depth_chroma_minus8);
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef FROM_SPS_TO_PP
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef FROM_SPS_TO_PP2
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define FROM_SPS_TO_PP_SF(a) pic_param.seq_fields.bits.a = sps->a;
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define FROM_SPS_TO_PP_SF2(a, b) pic_param.seq_fields.bits.b = sps->a;
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FROM_SPS_TO_PP_SF(chroma_format_idc);
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FROM_SPS_TO_PP_SF2(separate_colour_plane_flag,
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     residual_colour_transform_flag);
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FROM_SPS_TO_PP_SF(gaps_in_frame_num_value_allowed_flag);
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FROM_SPS_TO_PP_SF(frame_mbs_only_flag);
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FROM_SPS_TO_PP_SF(mb_adaptive_frame_field_flag);
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FROM_SPS_TO_PP_SF(direct_8x8_inference_flag);
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pic_param.seq_fields.bits.MinLumaBiPredSize8x8 = (sps->level_idc >= 31);
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FROM_SPS_TO_PP_SF(log2_max_frame_num_minus4);
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FROM_SPS_TO_PP_SF(pic_order_cnt_type);
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FROM_SPS_TO_PP_SF(log2_max_pic_order_cnt_lsb_minus4);
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FROM_SPS_TO_PP_SF(delta_pic_order_always_zero_flag);
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef FROM_SPS_TO_PP_SF
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef FROM_SPS_TO_PP_SF2
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define FROM_PPS_TO_PP(a) pic_param.a = pps->a;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FROM_PPS_TO_PP(num_slice_groups_minus1);
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pic_param.slice_group_map_type = 0;
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pic_param.slice_group_change_rate_minus1 = 0;
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FROM_PPS_TO_PP(pic_init_qp_minus26);
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FROM_PPS_TO_PP(pic_init_qs_minus26);
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FROM_PPS_TO_PP(chroma_qp_index_offset);
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FROM_PPS_TO_PP(second_chroma_qp_index_offset);
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef FROM_PPS_TO_PP
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define FROM_PPS_TO_PP_PF(a) pic_param.pic_fields.bits.a = pps->a;
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define FROM_PPS_TO_PP_PF2(a, b) pic_param.pic_fields.bits.b = pps->a;
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FROM_PPS_TO_PP_PF(entropy_coding_mode_flag);
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FROM_PPS_TO_PP_PF(weighted_pred_flag);
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FROM_PPS_TO_PP_PF(weighted_bipred_idc);
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FROM_PPS_TO_PP_PF(transform_8x8_mode_flag);
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pic_param.pic_fields.bits.field_pic_flag = 0;
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FROM_PPS_TO_PP_PF(constrained_intra_pred_flag);
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FROM_PPS_TO_PP_PF2(bottom_field_pic_order_in_frame_present_flag,
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                pic_order_present_flag);
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FROM_PPS_TO_PP_PF(deblocking_filter_control_present_flag);
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FROM_PPS_TO_PP_PF(redundant_pic_cnt_present_flag);
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pic_param.pic_fields.bits.reference_pic_flag = curr_pic_->ref;
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef FROM_PPS_TO_PP_PF
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef FROM_PPS_TO_PP_PF2
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pic_param.frame_num = curr_pic_->frame_num;
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InitVAPicture(&pic_param.CurrPic);
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FillVAPicture(&pic_param.CurrPic, curr_pic_.get());
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Init reference pictures' array.
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < 16; ++i)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InitVAPicture(&pic_param.ReferenceFrames[i]);
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // And fill it with picture info from DPB.
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FillVARefFramesFromDPB(pic_param.ReferenceFrames,
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         arraysize(pic_param.ReferenceFrames));
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pic_param.num_ref_frames = sps->max_num_ref_frames;
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return vaapi_wrapper_->SubmitBuffer(VAPictureParameterBufferType,
306868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                      sizeof(VAPictureParameterBufferH264),
307868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                      &pic_param);
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VaapiH264Decoder::SendIQMatrix() {
3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const media::H264PPS* pps = parser_.GetPPS(curr_pps_id_);
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(pps);
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VAIQMatrixBufferH264 iq_matrix_buf;
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&iq_matrix_buf, 0, sizeof(VAIQMatrixBufferH264));
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pps->pic_scaling_matrix_present_flag) {
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < 6; ++i) {
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (int j = 0; j < 16; ++j)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        iq_matrix_buf.ScalingList4x4[i][j] = pps->scaling_list4x4[i][j];
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < 2; ++i) {
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (int j = 0; j < 64; ++j)
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        iq_matrix_buf.ScalingList8x8[i][j] = pps->scaling_list8x8[i][j];
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const media::H264SPS* sps = parser_.GetSPS(pps->seq_parameter_set_id);
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(sps);
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < 6; ++i) {
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (int j = 0; j < 16; ++j)
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        iq_matrix_buf.ScalingList4x4[i][j] = sps->scaling_list4x4[i][j];
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < 2; ++i) {
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (int j = 0; j < 64; ++j)
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        iq_matrix_buf.ScalingList8x8[i][j] = sps->scaling_list8x8[i][j];
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
341868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return vaapi_wrapper_->SubmitBuffer(VAIQMatrixBufferType,
342868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                      sizeof(VAIQMatrixBufferH264),
343868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                      &iq_matrix_buf);
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool VaapiH264Decoder::SendVASliceParam(media::H264SliceHeader* slice_hdr) {
3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const media::H264PPS* pps = parser_.GetPPS(slice_hdr->pic_parameter_set_id);
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(pps);
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const media::H264SPS* sps = parser_.GetSPS(pps->seq_parameter_set_id);
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(sps);
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VASliceParameterBufferH264 slice_param;
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&slice_param, 0, sizeof(VASliceParameterBufferH264));
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  slice_param.slice_data_size = slice_hdr->nalu_size;
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  slice_param.slice_data_offset = 0;
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  slice_param.slice_data_flag = VA_SLICE_DATA_FLAG_ALL;
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  slice_param.slice_data_bit_offset = slice_hdr->header_bit_size;
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SHDRToSP(a) slice_param.a = slice_hdr->a;
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SHDRToSP(first_mb_in_slice);
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  slice_param.slice_type = slice_hdr->slice_type % 5;
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SHDRToSP(direct_spatial_mv_pred_flag);
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO posciak: make sure parser sets those even when override flags
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // in slice header is off.
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SHDRToSP(num_ref_idx_l0_active_minus1);
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SHDRToSP(num_ref_idx_l1_active_minus1);
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SHDRToSP(cabac_init_idc);
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SHDRToSP(slice_qp_delta);
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SHDRToSP(disable_deblocking_filter_idc);
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SHDRToSP(slice_alpha_c0_offset_div2);
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SHDRToSP(slice_beta_offset_div2);
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (((slice_hdr->IsPSlice() || slice_hdr->IsSPSlice()) &&
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       pps->weighted_pred_flag) ||
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (slice_hdr->IsBSlice() && pps->weighted_bipred_idc == 1)) {
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SHDRToSP(luma_log2_weight_denom);
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SHDRToSP(chroma_log2_weight_denom);
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SHDRToSP(luma_weight_l0_flag);
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SHDRToSP(luma_weight_l1_flag);
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SHDRToSP(chroma_weight_l0_flag);
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SHDRToSP(chroma_weight_l1_flag);
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i <= slice_param.num_ref_idx_l0_active_minus1; ++i) {
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      slice_param.luma_weight_l0[i] =
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          slice_hdr->pred_weight_table_l0.luma_weight[i];
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      slice_param.luma_offset_l0[i] =
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          slice_hdr->pred_weight_table_l0.luma_offset[i];
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (int j = 0; j < 2; ++j) {
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        slice_param.chroma_weight_l0[i][j] =
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            slice_hdr->pred_weight_table_l0.chroma_weight[i][j];
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        slice_param.chroma_offset_l0[i][j] =
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            slice_hdr->pred_weight_table_l0.chroma_offset[i][j];
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (slice_hdr->IsBSlice()) {
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (int i = 0; i <= slice_param.num_ref_idx_l1_active_minus1; ++i) {
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        slice_param.luma_weight_l1[i] =
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            slice_hdr->pred_weight_table_l1.luma_weight[i];
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        slice_param.luma_offset_l1[i] =
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            slice_hdr->pred_weight_table_l1.luma_offset[i];
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for (int j = 0; j < 2; ++j) {
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          slice_param.chroma_weight_l1[i][j] =
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              slice_hdr->pred_weight_table_l1.chroma_weight[i][j];
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          slice_param.chroma_offset_l1[i][j] =
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              slice_hdr->pred_weight_table_l1.chroma_offset[i][j];
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < 32; ++i) {
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InitVAPicture(&slice_param.RefPicList0[i]);
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InitVAPicture(&slice_param.RefPicList1[i]);
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i;
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  H264Picture::PtrVector::iterator it;
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (it = ref_pic_list0_.begin(), i = 0; it != ref_pic_list0_.end() && *it;
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++it, ++i)
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FillVAPicture(&slice_param.RefPicList0[i], *it);
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (it = ref_pic_list1_.begin(), i = 0; it != ref_pic_list1_.end() && *it;
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++it, ++i)
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FillVAPicture(&slice_param.RefPicList1[i], *it);
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
433868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return vaapi_wrapper_->SubmitBuffer(VASliceParameterBufferType,
434868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                      sizeof(VASliceParameterBufferH264),
435868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                      &slice_param);
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VaapiH264Decoder::SendSliceData(const uint8* ptr, size_t size) {
439868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Can't help it, blame libva...
440868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void* non_const_ptr = const_cast<uint8*>(ptr);
441868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return vaapi_wrapper_->SubmitBuffer(VASliceDataBufferType, size,
442868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                      non_const_ptr);
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool VaapiH264Decoder::PrepareRefPicLists(media::H264SliceHeader* slice_hdr) {
446f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ref_pic_list0_.clear();
447f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ref_pic_list1_.clear();
448f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
449f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Fill reference picture lists for B and S/SP slices.
450f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (slice_hdr->IsPSlice() || slice_hdr->IsSPSlice()) {
451f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    ConstructReferencePicListsP(slice_hdr);
452f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return ModifyReferencePicList(slice_hdr, 0);
453f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
454f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
455f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (slice_hdr->IsBSlice()) {
456f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    ConstructReferencePicListsB(slice_hdr);
457f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return ModifyReferencePicList(slice_hdr, 0) &&
458f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        ModifyReferencePicList(slice_hdr, 1);
459f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
460f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
461f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return true;
462f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
463f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
4645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool VaapiH264Decoder::QueueSlice(media::H264SliceHeader* slice_hdr) {
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(curr_pic_.get());
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
467f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!PrepareRefPicLists(slice_hdr))
468f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return false;
469f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!SendVASliceParam(slice_hdr))
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!SendSliceData(slice_hdr->nalu_data, slice_hdr->nalu_size))
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
479868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// TODO(posciak) start using vaMapBuffer instead of vaCreateBuffer wherever
480868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// possible.
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VaapiH264Decoder::DecodePicture() {
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(curr_pic_.get());
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
484868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DVLOG(4) << "Decoding POC " << curr_pic_->pic_order_cnt;
485868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DecodeSurface* dec_surface = DecodeSurfaceByPoC(curr_pic_->pic_order_cnt);
486868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!dec_surface) {
487868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DVLOG(1) << "Asked to decode an invalid POC " << curr_pic_->pic_order_cnt;
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
491116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!vaapi_wrapper_->ExecuteAndDestroyPendingBuffers(
492116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          dec_surface->va_surface()->id())) {
493868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DVLOG(1) << "Failed decoding picture";
494868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
497868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return true;
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool VaapiH264Decoder::InitCurrPicture(media::H264SliceHeader* slice_hdr) {
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(curr_pic_.get());
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(curr_pic_.get(), 0, sizeof(H264Picture));
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  curr_pic_->idr = slice_hdr->idr_pic_flag;
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (slice_hdr->field_pic_flag) {
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    curr_pic_->field = slice_hdr->bottom_field_flag ? H264Picture::FIELD_BOTTOM
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                    : H264Picture::FIELD_TOP;
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    curr_pic_->field = H264Picture::FIELD_NONE;
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  curr_pic_->ref = slice_hdr->nal_ref_idc != 0;
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This assumes non-interlaced stream.
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  curr_pic_->frame_num = curr_pic_->pic_num = slice_hdr->frame_num;
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!CalculatePicOrderCounts(slice_hdr))
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Try to get an empty surface to decode this picture to.
522868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!AssignSurfaceToPoC(curr_input_id_, curr_pic_->pic_order_cnt)) {
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "Failed getting a free surface for a picture";
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  curr_pic_->long_term_reference_flag = slice_hdr->long_term_reference_flag;
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  curr_pic_->adaptive_ref_pic_marking_mode_flag =
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      slice_hdr->adaptive_ref_pic_marking_mode_flag;
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the slice header indicates we will have to perform reference marking
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // process after this picture is decoded, store required data for that
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // purpose.
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (slice_hdr->adaptive_ref_pic_marking_mode_flag) {
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    COMPILE_ASSERT(sizeof(curr_pic_->ref_pic_marking) ==
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   sizeof(slice_hdr->ref_pic_marking),
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   ref_pic_marking_array_sizes_do_not_match);
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(curr_pic_->ref_pic_marking, slice_hdr->ref_pic_marking,
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           sizeof(curr_pic_->ref_pic_marking));
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool VaapiH264Decoder::CalculatePicOrderCounts(
5465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    media::H264SliceHeader* slice_hdr) {
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(curr_sps_id_, -1);
5485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const media::H264SPS* sps = parser_.GetSPS(curr_sps_id_);
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int pic_order_cnt_lsb = slice_hdr->pic_order_cnt_lsb;
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  curr_pic_->pic_order_cnt_lsb = pic_order_cnt_lsb;
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (sps->pic_order_cnt_type) {
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 0:
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // See spec 8.2.1.1.
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int prev_pic_order_cnt_msb, prev_pic_order_cnt_lsb;
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (slice_hdr->idr_pic_flag) {
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        prev_pic_order_cnt_msb = prev_pic_order_cnt_lsb = 0;
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (prev_ref_has_memmgmnt5_) {
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (prev_ref_field_ != H264Picture::FIELD_BOTTOM) {
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            prev_pic_order_cnt_msb = 0;
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            prev_pic_order_cnt_lsb = prev_ref_top_field_order_cnt_;
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          } else {
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            prev_pic_order_cnt_msb = 0;
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            prev_pic_order_cnt_lsb = 0;
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          prev_pic_order_cnt_msb = prev_ref_pic_order_cnt_msb_;
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          prev_pic_order_cnt_lsb = prev_ref_pic_order_cnt_lsb_;
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK_NE(max_pic_order_cnt_lsb_, 0);
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if ((pic_order_cnt_lsb < prev_pic_order_cnt_lsb) &&
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (prev_pic_order_cnt_lsb - pic_order_cnt_lsb >=
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           max_pic_order_cnt_lsb_ / 2)) {
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        curr_pic_->pic_order_cnt_msb = prev_pic_order_cnt_msb +
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          max_pic_order_cnt_lsb_;
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if ((pic_order_cnt_lsb > prev_pic_order_cnt_lsb) &&
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (pic_order_cnt_lsb - prev_pic_order_cnt_lsb >
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           max_pic_order_cnt_lsb_ / 2)) {
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        curr_pic_->pic_order_cnt_msb = prev_pic_order_cnt_msb -
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          max_pic_order_cnt_lsb_;
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        curr_pic_->pic_order_cnt_msb = prev_pic_order_cnt_msb;
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (curr_pic_->field != H264Picture::FIELD_BOTTOM) {
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        curr_pic_->top_field_order_cnt = curr_pic_->pic_order_cnt_msb +
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          pic_order_cnt_lsb;
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (curr_pic_->field != H264Picture::FIELD_TOP) {
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // TODO posciak: perhaps replace with pic->field?
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!slice_hdr->field_pic_flag) {
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          curr_pic_->bottom_field_order_cnt = curr_pic_->top_field_order_cnt +
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            slice_hdr->delta_pic_order_cnt_bottom;
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          curr_pic_->bottom_field_order_cnt = curr_pic_->pic_order_cnt_msb +
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            pic_order_cnt_lsb;
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 1: {
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // See spec 8.2.1.2.
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (prev_has_memmgmnt5_)
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        prev_frame_num_offset_ = 0;
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (slice_hdr->idr_pic_flag)
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        curr_pic_->frame_num_offset = 0;
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else if (prev_frame_num_ > slice_hdr->frame_num)
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        curr_pic_->frame_num_offset = prev_frame_num_offset_ + max_frame_num_;
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        curr_pic_->frame_num_offset = prev_frame_num_offset_;
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int abs_frame_num = 0;
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (sps->num_ref_frames_in_pic_order_cnt_cycle != 0)
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        abs_frame_num = curr_pic_->frame_num_offset + slice_hdr->frame_num;
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        abs_frame_num = 0;
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (slice_hdr->nal_ref_idc == 0 && abs_frame_num > 0)
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        --abs_frame_num;
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int expected_pic_order_cnt = 0;
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (abs_frame_num > 0) {
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (sps->num_ref_frames_in_pic_order_cnt_cycle == 0) {
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          DVLOG(1) << "Invalid num_ref_frames_in_pic_order_cnt_cycle "
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   << "in stream";
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return false;
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int pic_order_cnt_cycle_cnt = (abs_frame_num - 1) /
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            sps->num_ref_frames_in_pic_order_cnt_cycle;
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int frame_num_in_pic_order_cnt_cycle = (abs_frame_num - 1) %
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            sps->num_ref_frames_in_pic_order_cnt_cycle;
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        expected_pic_order_cnt = pic_order_cnt_cycle_cnt *
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            sps->expected_delta_per_pic_order_cnt_cycle;
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // frame_num_in_pic_order_cnt_cycle is verified < 255 in parser
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for (int i = 0; i <= frame_num_in_pic_order_cnt_cycle; ++i)
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          expected_pic_order_cnt += sps->offset_for_ref_frame[i];
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!slice_hdr->nal_ref_idc)
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        expected_pic_order_cnt += sps->offset_for_non_ref_pic;
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!slice_hdr->field_pic_flag) {
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        curr_pic_->top_field_order_cnt = expected_pic_order_cnt +
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            slice_hdr->delta_pic_order_cnt[0];
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        curr_pic_->bottom_field_order_cnt = curr_pic_->top_field_order_cnt +
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            sps->offset_for_top_to_bottom_field +
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            slice_hdr->delta_pic_order_cnt[1];
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (!slice_hdr->bottom_field_flag) {
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        curr_pic_->top_field_order_cnt = expected_pic_order_cnt +
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            slice_hdr->delta_pic_order_cnt[0];
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        curr_pic_->bottom_field_order_cnt = expected_pic_order_cnt +
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            sps->offset_for_top_to_bottom_field +
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            slice_hdr->delta_pic_order_cnt[0];
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 2:
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // See spec 8.2.1.3.
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (prev_has_memmgmnt5_)
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        prev_frame_num_offset_ = 0;
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (slice_hdr->idr_pic_flag)
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        curr_pic_->frame_num_offset = 0;
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else if (prev_frame_num_ > slice_hdr->frame_num)
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        curr_pic_->frame_num_offset = prev_frame_num_offset_ + max_frame_num_;
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        curr_pic_->frame_num_offset = prev_frame_num_offset_;
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int temp_pic_order_cnt;
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (slice_hdr->idr_pic_flag) {
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        temp_pic_order_cnt = 0;
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (!slice_hdr->nal_ref_idc) {
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        temp_pic_order_cnt =
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            2 * (curr_pic_->frame_num_offset + slice_hdr->frame_num) - 1;
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        temp_pic_order_cnt = 2 * (curr_pic_->frame_num_offset +
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            slice_hdr->frame_num);
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!slice_hdr->field_pic_flag) {
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        curr_pic_->top_field_order_cnt = temp_pic_order_cnt;
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        curr_pic_->bottom_field_order_cnt = temp_pic_order_cnt;
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (slice_hdr->bottom_field_flag) {
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        curr_pic_->bottom_field_order_cnt = temp_pic_order_cnt;
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        curr_pic_->top_field_order_cnt = temp_pic_order_cnt;
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DVLOG(1) << "Invalid pic_order_cnt_type: " << sps->pic_order_cnt_type;
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (curr_pic_->field) {
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case H264Picture::FIELD_NONE:
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      curr_pic_->pic_order_cnt = std::min(curr_pic_->top_field_order_cnt,
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          curr_pic_->bottom_field_order_cnt);
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case H264Picture::FIELD_TOP:
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      curr_pic_->pic_order_cnt = curr_pic_->top_field_order_cnt;
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case H264Picture::FIELD_BOTTOM:
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      curr_pic_->pic_order_cnt = curr_pic_->bottom_field_order_cnt;
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VaapiH264Decoder::UpdatePicNums() {
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (H264DPB::Pictures::iterator it = dpb_.begin(); it != dpb_.end(); ++it) {
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    H264Picture* pic = *it;
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(pic);
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!pic->ref)
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Below assumes non-interlaced stream.
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(pic->field, H264Picture::FIELD_NONE);
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (pic->long_term) {
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pic->long_term_pic_num = pic->long_term_frame_idx;
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (pic->frame_num > frame_num_)
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pic->frame_num_wrap = pic->frame_num - max_frame_num_;
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pic->frame_num_wrap = pic->frame_num;
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pic->pic_num = pic->frame_num_wrap;
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct PicNumDescCompare {
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool operator()(const H264Picture* a, const H264Picture* b) const {
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return a->pic_num > b->pic_num;
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct LongTermPicNumAscCompare {
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool operator()(const H264Picture* a, const H264Picture* b) const {
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return a->long_term_pic_num < b->long_term_pic_num;
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void VaapiH264Decoder::ConstructReferencePicListsP(
7565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    media::H264SliceHeader* slice_hdr) {
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // RefPicList0 (8.2.4.2.1) [[1] [2]], where:
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // [1] shortterm ref pics sorted by descending pic_num,
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // [2] longterm ref pics by ascending long_term_pic_num.
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(ref_pic_list0_.empty() && ref_pic_list1_.empty());
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // First get the short ref pics...
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dpb_.GetShortTermRefPicsAppending(ref_pic_list0_);
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t num_short_refs = ref_pic_list0_.size();
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and sort them to get [1].
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::sort(ref_pic_list0_.begin(), ref_pic_list0_.end(), PicNumDescCompare());
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now get long term pics and sort them by long_term_pic_num to get [2].
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dpb_.GetLongTermRefPicsAppending(ref_pic_list0_);
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::sort(ref_pic_list0_.begin() + num_short_refs, ref_pic_list0_.end(),
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            LongTermPicNumAscCompare());
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cut off if we have more than requested in slice header.
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ref_pic_list0_.resize(slice_hdr->num_ref_idx_l0_active_minus1 + 1);
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct POCAscCompare {
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool operator()(const H264Picture* a, const H264Picture* b) const {
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return a->pic_order_cnt < b->pic_order_cnt;
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct POCDescCompare {
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool operator()(const H264Picture* a, const H264Picture* b) const {
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return a->pic_order_cnt > b->pic_order_cnt;
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void VaapiH264Decoder::ConstructReferencePicListsB(
7905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    media::H264SliceHeader* slice_hdr) {
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // RefPicList0 (8.2.4.2.3) [[1] [2] [3]], where:
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // [1] shortterm ref pics with POC < curr_pic's POC sorted by descending POC,
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // [2] shortterm ref pics with POC > curr_pic's POC by ascending POC,
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // [3] longterm ref pics by ascending long_term_pic_num.
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(ref_pic_list0_.empty() && ref_pic_list1_.empty());
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dpb_.GetShortTermRefPicsAppending(ref_pic_list0_);
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t num_short_refs = ref_pic_list0_.size();
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // First sort ascending, this will put [1] in right place and finish [2].
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::sort(ref_pic_list0_.begin(), ref_pic_list0_.end(), POCAscCompare());
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Find first with POC > curr_pic's POC to get first element in [2]...
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  H264Picture::PtrVector::iterator iter;
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  iter = std::upper_bound(ref_pic_list0_.begin(), ref_pic_list0_.end(),
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          curr_pic_.get(), POCAscCompare());
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and sort [1] descending, thus finishing sequence [1] [2].
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::sort(ref_pic_list0_.begin(), iter, POCDescCompare());
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now add [3] and sort by ascending long_term_pic_num.
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dpb_.GetLongTermRefPicsAppending(ref_pic_list0_);
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::sort(ref_pic_list0_.begin() + num_short_refs, ref_pic_list0_.end(),
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            LongTermPicNumAscCompare());
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // RefPicList1 (8.2.4.2.4) [[1] [2] [3]], where:
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // [1] shortterm ref pics with POC > curr_pic's POC sorted by ascending POC,
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // [2] shortterm ref pics with POC < curr_pic's POC by descending POC,
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // [3] longterm ref pics by ascending long_term_pic_num.
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dpb_.GetShortTermRefPicsAppending(ref_pic_list1_);
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  num_short_refs = ref_pic_list1_.size();
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // First sort by descending POC.
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::sort(ref_pic_list1_.begin(), ref_pic_list1_.end(), POCDescCompare());
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Find first with POC < curr_pic's POC to get first element in [2]...
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  iter = std::upper_bound(ref_pic_list1_.begin(), ref_pic_list1_.end(),
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          curr_pic_.get(), POCDescCompare());
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and sort [1] ascending.
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::sort(ref_pic_list1_.begin(), iter, POCAscCompare());
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now add [3] and sort by ascending long_term_pic_num
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dpb_.GetShortTermRefPicsAppending(ref_pic_list1_);
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::sort(ref_pic_list1_.begin() + num_short_refs, ref_pic_list1_.end(),
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            LongTermPicNumAscCompare());
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If lists identical, swap first two entries in RefPicList1 (spec 8.2.4.2.3)
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ref_pic_list1_.size() > 1 &&
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::equal(ref_pic_list0_.begin(), ref_pic_list0_.end(),
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 ref_pic_list1_.begin()))
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::swap(ref_pic_list1_[0], ref_pic_list1_[1]);
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Per 8.2.4.2 it's possible for num_ref_idx_lX_active_minus1 to indicate
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // there should be more ref pics on list than we constructed.
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Those superfluous ones should be treated as non-reference.
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ref_pic_list0_.resize(slice_hdr->num_ref_idx_l0_active_minus1 + 1);
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ref_pic_list1_.resize(slice_hdr->num_ref_idx_l1_active_minus1 + 1);
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// See 8.2.4
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int VaapiH264Decoder::PicNumF(H264Picture *pic) {
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!pic)
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return -1;
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!pic->long_term)
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return pic->pic_num;
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return max_pic_num_;
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// See 8.2.4
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int VaapiH264Decoder::LongTermPicNumF(H264Picture *pic) {
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pic->ref && pic->long_term)
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return pic->long_term_pic_num;
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 2 * (max_long_term_frame_idx_ + 1);
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Shift elements on the |v| starting from |from| to |to|, inclusive,
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// one position to the right and insert pic at |from|.
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void ShiftRightAndInsert(H264Picture::PtrVector *v,
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                int from,
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                int to,
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                H264Picture* pic) {
8762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Security checks, do not disable in Debug mode.
8772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK(from <= to);
8782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK(to <= std::numeric_limits<int>::max() - 2);
8792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Additional checks. Debug mode ok.
8802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(v);
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(pic);
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK((to + 1 == static_cast<int>(v->size())) ||
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         (to + 2 == static_cast<int>(v->size())));
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  v->resize(to + 2);
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = to + 1; i > from; --i)
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*v)[i] = (*v)[i - 1];
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (*v)[from] = pic;
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool VaapiH264Decoder::ModifyReferencePicList(media::H264SliceHeader* slice_hdr,
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              int list) {
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int num_ref_idx_lX_active_minus1;
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  H264Picture::PtrVector* ref_pic_listx;
8975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  media::H264ModificationOfPicNum* list_mod;
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This can process either ref_pic_list0 or ref_pic_list1, depending on
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the list argument. Set up pointers to proper list to be processed here.
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (list == 0) {
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!slice_hdr->ref_pic_list_modification_flag_l0)
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    list_mod = slice_hdr->ref_list_l0_modifications;
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    num_ref_idx_lX_active_minus1 = ref_pic_list0_.size() - 1;
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ref_pic_listx = &ref_pic_list0_;
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!slice_hdr->ref_pic_list_modification_flag_l1)
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    list_mod = slice_hdr->ref_list_l1_modifications;
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    num_ref_idx_lX_active_minus1 = ref_pic_list1_.size() - 1;
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ref_pic_listx = &ref_pic_list1_;
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_GE(num_ref_idx_lX_active_minus1, 0);
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Spec 8.2.4.3:
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Reorder pictures on the list in a way specified in the stream.
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int pic_num_lx_pred = curr_pic_->pic_num;
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ref_idx_lx = 0;
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int pic_num_lx_no_wrap;
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int pic_num_lx;
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool done = false;
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  H264Picture* pic;
9295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (int i = 0; i < media::H264SliceHeader::kRefListModSize && !done; ++i) {
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (list_mod->modification_of_pic_nums_idc) {
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case 0:
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case 1:
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Modify short reference picture position.
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (list_mod->modification_of_pic_nums_idc == 0) {
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // Subtract given value from predicted PicNum.
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          pic_num_lx_no_wrap = pic_num_lx_pred -
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              (static_cast<int>(list_mod->abs_diff_pic_num_minus1) + 1);
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // Wrap around max_pic_num_ if it becomes < 0 as result
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // of subtraction.
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (pic_num_lx_no_wrap < 0)
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            pic_num_lx_no_wrap += max_pic_num_;
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // Add given value to predicted PicNum.
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          pic_num_lx_no_wrap = pic_num_lx_pred +
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              (static_cast<int>(list_mod->abs_diff_pic_num_minus1) + 1);
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // Wrap around max_pic_num_ if it becomes >= max_pic_num_ as result
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // of the addition.
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (pic_num_lx_no_wrap >= max_pic_num_)
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            pic_num_lx_no_wrap -= max_pic_num_;
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // For use in next iteration.
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pic_num_lx_pred = pic_num_lx_no_wrap;
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (pic_num_lx_no_wrap > curr_pic_->pic_num)
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          pic_num_lx = pic_num_lx_no_wrap - max_pic_num_;
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        else
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          pic_num_lx = pic_num_lx_no_wrap;
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK_LT(num_ref_idx_lX_active_minus1 + 1,
9615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                  media::H264SliceHeader::kRefListModSize);
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pic = dpb_.GetShortRefPicByPicNum(pic_num_lx);
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!pic) {
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          DVLOG(1) << "Malformed stream, no pic num " << pic_num_lx;
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return false;
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ShiftRightAndInsert(ref_pic_listx, ref_idx_lx,
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            num_ref_idx_lX_active_minus1, pic);
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ref_idx_lx++;
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for (int src = ref_idx_lx, dst = ref_idx_lx;
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             src <= num_ref_idx_lX_active_minus1 + 1; ++src) {
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (PicNumF((*ref_pic_listx)[src]) != pic_num_lx)
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            (*ref_pic_listx)[dst++] = (*ref_pic_listx)[src];
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case 2:
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Modify long term reference picture position.
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK_LT(num_ref_idx_lX_active_minus1 + 1,
9815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                  media::H264SliceHeader::kRefListModSize);
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pic = dpb_.GetLongRefPicByLongTermPicNum(list_mod->long_term_pic_num);
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!pic) {
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          DVLOG(1) << "Malformed stream, no pic num "
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   << list_mod->long_term_pic_num;
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return false;
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ShiftRightAndInsert(ref_pic_listx, ref_idx_lx,
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            num_ref_idx_lX_active_minus1, pic);
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ref_idx_lx++;
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for (int src = ref_idx_lx, dst = ref_idx_lx;
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             src <= num_ref_idx_lX_active_minus1 + 1; ++src) {
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (LongTermPicNumF((*ref_pic_listx)[src])
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              != static_cast<int>(list_mod->long_term_pic_num))
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            (*ref_pic_listx)[dst++] = (*ref_pic_listx)[src];
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case 3:
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // End of modification list.
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        done = true;
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // May be recoverable.
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DVLOG(1) << "Invalid modification_of_pic_nums_idc="
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << list_mod->modification_of_pic_nums_idc
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << " in position " << i;
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++list_mod;
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Per NOTE 2 in 8.2.4.3.2, the ref_pic_listx size in the above loop is
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // temporarily made one element longer than the required final list.
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Resize the list back to its required size.
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ref_pic_listx->resize(num_ref_idx_lX_active_minus1 + 1);
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VaapiH264Decoder::OutputPic(H264Picture* pic) {
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!pic->outputted);
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pic->outputted = true;
1027868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  last_output_poc_ = pic->pic_order_cnt;
1028868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1029868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DecodeSurface* dec_surface = DecodeSurfaceByPoC(pic->pic_order_cnt);
1030868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!dec_surface)
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1033868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_GE(dec_surface->input_id(), 0);
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(4) << "Posting output task for POC: " << pic->pic_order_cnt
1035868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)           << " input_id: " << dec_surface->input_id();
1036868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  output_pic_cb_.Run(dec_surface->input_id(), dec_surface->va_surface());
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1041868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void VaapiH264Decoder::ClearDPB() {
1042868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Clear DPB contents, marking the pictures as unused first.
1043868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (H264DPB::Pictures::iterator it = dpb_.begin(); it != dpb_.end(); ++it)
1044868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    UnassignSurfaceFromPoC((*it)->pic_order_cnt);
1045868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1046868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  dpb_.Clear();
1047a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  last_output_poc_ = std::numeric_limits<int>::min();
1048868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1049868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1050868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool VaapiH264Decoder::OutputAllRemainingPics() {
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Output all pictures that are waiting to be outputted.
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FinishPrevFrameIfPresent();
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  H264Picture::PtrVector to_output;
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dpb_.GetNotOutputtedPicsAppending(to_output);
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Sort them by ascending POC to output in order.
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::sort(to_output.begin(), to_output.end(), POCAscCompare());
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  H264Picture::PtrVector::iterator it;
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (it = to_output.begin(); it != to_output.end(); ++it) {
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!OutputPic(*it)) {
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DVLOG(1) << "Failed to output pic POC: " << (*it)->pic_order_cnt;
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1066868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return true;
1067868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1069868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool VaapiH264Decoder::Flush() {
10707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DVLOG(2) << "Decoder flush";
10717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1072868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!OutputAllRemainingPics())
1073868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
1074868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1075868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ClearDPB();
1076868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1077868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(decode_surfaces_in_use_.empty());
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool VaapiH264Decoder::StartNewFrame(media::H264SliceHeader* slice_hdr) {
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO posciak: add handling of max_num_ref_frames per spec.
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the new frame is an IDR, output what's left to output and clear DPB
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (slice_hdr->idr_pic_flag) {
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // (unless we are explicitly instructed not to do so).
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!slice_hdr->no_output_of_prior_pics_flag) {
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Output DPB contents.
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!Flush())
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dpb_.Clear();
1093a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    last_output_poc_ = std::numeric_limits<int>::min();
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // curr_pic_ should have either been added to DPB or discarded when finishing
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the last frame. DPB is responsible for releasing that memory once it's
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // not needed anymore.
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!curr_pic_.get());
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  curr_pic_.reset(new H264Picture);
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(curr_pic_.get());
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!InitCurrPicture(slice_hdr))
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GT(max_frame_num_, 0);
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdatePicNums();
11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Send parameter buffers before each new picture, before the first slice.
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!SendPPS())
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!SendIQMatrix())
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!QueueSlice(slice_hdr))
11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VaapiH264Decoder::HandleMemoryManagementOps() {
11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 8.2.5.4
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (unsigned int i = 0; i < arraysize(curr_pic_->ref_pic_marking); ++i) {
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Code below does not support interlaced stream (per-field pictures).
11275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    media::H264DecRefPicMarking* ref_pic_marking =
11285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        &curr_pic_->ref_pic_marking[i];
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    H264Picture* to_mark;
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int pic_num_x;
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (ref_pic_marking->memory_mgmnt_control_operation) {
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case 0:
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Normal end of operations' specification.
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case 1:
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Mark a short term reference picture as unused so it can be removed
11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // if outputted.
11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pic_num_x = curr_pic_->pic_num -
11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            (ref_pic_marking->difference_of_pic_nums_minus1 + 1);
11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        to_mark = dpb_.GetShortRefPicByPicNum(pic_num_x);
11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (to_mark) {
11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          to_mark->ref = false;
11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          DVLOG(1) << "Invalid short ref pic num to unmark";
11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return false;
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case 2:
11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Mark a long term reference picture as unused so it can be removed
11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // if outputted.
11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        to_mark = dpb_.GetLongRefPicByLongTermPicNum(
11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ref_pic_marking->long_term_pic_num);
11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (to_mark) {
11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          to_mark->ref = false;
11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          DVLOG(1) << "Invalid long term ref pic num to unmark";
11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return false;
11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case 3:
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Mark a short term reference picture as long term reference.
11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pic_num_x = curr_pic_->pic_num -
11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            (ref_pic_marking->difference_of_pic_nums_minus1 + 1);
11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        to_mark = dpb_.GetShortRefPicByPicNum(pic_num_x);
11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (to_mark) {
11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          DCHECK(to_mark->ref && !to_mark->long_term);
11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          to_mark->long_term = true;
11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          to_mark->long_term_frame_idx = ref_pic_marking->long_term_frame_idx;
11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          DVLOG(1) << "Invalid short term ref pic num to mark as long ref";
11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return false;
11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case 4: {
11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Unmark all reference pictures with long_term_frame_idx over new max.
11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        max_long_term_frame_idx_
11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            = ref_pic_marking->max_long_term_frame_idx_plus1 - 1;
11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        H264Picture::PtrVector long_terms;
11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dpb_.GetLongTermRefPicsAppending(long_terms);
11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for (size_t i = 0; i < long_terms.size(); ++i) {
11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          H264Picture* pic = long_terms[i];
11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          DCHECK(pic->ref && pic->long_term);
11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // Ok to cast, max_long_term_frame_idx is much smaller than 16bit.
11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (pic->long_term_frame_idx >
11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              static_cast<int>(max_long_term_frame_idx_))
11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            pic->ref = false;
11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case 5:
11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Unmark all reference pictures.
11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dpb_.MarkAllUnusedForRef();
11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        max_long_term_frame_idx_ = -1;
12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        curr_pic_->mem_mgmt_5 = true;
12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case 6: {
12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Replace long term reference pictures with current picture.
12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // First unmark if any existing with this long_term_frame_idx...
12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        H264Picture::PtrVector long_terms;
12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dpb_.GetLongTermRefPicsAppending(long_terms);
12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for (size_t i = 0; i < long_terms.size(); ++i) {
12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          H264Picture* pic = long_terms[i];
12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          DCHECK(pic->ref && pic->long_term);
12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // Ok to cast, long_term_frame_idx is much smaller than 16bit.
12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (pic->long_term_frame_idx ==
12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              static_cast<int>(ref_pic_marking->long_term_frame_idx))
12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            pic->ref = false;
12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // and mark the current one instead.
12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        curr_pic_->ref = true;
12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        curr_pic_->long_term = true;
12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        curr_pic_->long_term_frame_idx = ref_pic_marking->long_term_frame_idx;
12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Would indicate a bug in parser.
12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NOTREACHED();
12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This method ensures that DPB does not overflow, either by removing
12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// reference pictures as specified in the stream, or using a sliding window
12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// procedure to remove the oldest one.
12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// It also performs marking and unmarking pictures as reference.
12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// See spac 8.2.5.1.
12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VaapiH264Decoder::ReferencePictureMarking() {
12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (curr_pic_->idr) {
12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If current picture is an IDR, all reference pictures are unmarked.
12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dpb_.MarkAllUnusedForRef();
12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (curr_pic_->long_term_reference_flag) {
12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      curr_pic_->long_term = true;
12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      curr_pic_->long_term_frame_idx = 0;
12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      max_long_term_frame_idx_ = 0;
12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      curr_pic_->long_term = false;
12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      max_long_term_frame_idx_ = -1;
12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!curr_pic_->adaptive_ref_pic_marking_mode_flag) {
12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // If non-IDR, and the stream does not indicate what we should do to
12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // ensure DPB doesn't overflow, discard oldest picture.
12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // See spec 8.2.5.3.
12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (curr_pic_->field == H264Picture::FIELD_NONE) {
12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK_LE(dpb_.CountRefPics(),
12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            std::max<int>(parser_.GetSPS(curr_sps_id_)->max_num_ref_frames,
12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          1));
12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (dpb_.CountRefPics() ==
12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            std::max<int>(parser_.GetSPS(curr_sps_id_)->max_num_ref_frames,
12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          1)) {
12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // Max number of reference pics reached,
12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // need to remove one of the short term ones.
12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // Find smallest frame_num_wrap short reference picture and mark
12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // it as unused.
12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          H264Picture* to_unmark = dpb_.GetLowestFrameNumWrapShortRefPic();
12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (to_unmark == NULL) {
12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            DVLOG(1) << "Couldn't find a short ref picture to unmark";
12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return;
12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          to_unmark->ref = false;
12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Shouldn't get here.
12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DVLOG(1) << "Interlaced video not supported.";
1277868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        report_error_to_uma_cb_.Run(INTERLACED_STREAM);
12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Stream has instructions how to discard pictures from DPB and how
12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // to mark/unmark existing reference pictures. Do it.
12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Spec 8.2.5.4.
12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (curr_pic_->field == H264Picture::FIELD_NONE) {
12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        HandleMemoryManagementOps();
12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Shouldn't get here.
12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DVLOG(1) << "Interlaced video not supported.";
1288868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        report_error_to_uma_cb_.Run(INTERLACED_STREAM);
12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VaapiH264Decoder::FinishPicture() {
12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(curr_pic_.get());
12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Finish processing previous picture.
12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start by storing previous reference picture data for later use,
12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // if picture being finished is a reference picture.
13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (curr_pic_->ref) {
13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReferencePictureMarking();
13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    prev_ref_has_memmgmnt5_ = curr_pic_->mem_mgmt_5;
13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    prev_ref_top_field_order_cnt_ = curr_pic_->top_field_order_cnt;
13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    prev_ref_pic_order_cnt_msb_ = curr_pic_->pic_order_cnt_msb;
13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    prev_ref_pic_order_cnt_lsb_ = curr_pic_->pic_order_cnt_lsb;
13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    prev_ref_field_ = curr_pic_->field;
13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  prev_has_memmgmnt5_ = curr_pic_->mem_mgmt_5;
13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  prev_frame_num_offset_ = curr_pic_->frame_num_offset;
13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Remove unused (for reference or later output) pictures from DPB, marking
13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // them as such.
13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (H264DPB::Pictures::iterator it = dpb_.begin(); it != dpb_.end(); ++it) {
13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((*it)->outputted && !(*it)->ref)
13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UnassignSurfaceFromPoC((*it)->pic_order_cnt);
13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1317868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  dpb_.DeleteUnused();
13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1319868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DVLOG(4) << "Finishing picture, entries in DPB: " << dpb_.size();
13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Whatever happens below, curr_pic_ will stop managing the pointer to the
13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // picture after this function returns. The ownership will either be
13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // transferred to DPB, if the image is still needed (for output and/or
13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // reference), or the memory will be released if we manage to output it here
13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // without having to store it for future reference.
13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<H264Picture> pic(curr_pic_.release());
13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get all pictures that haven't been outputted yet.
13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  H264Picture::PtrVector not_outputted;
13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(posciak): pass as pointer, not reference (violates coding style).
13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dpb_.GetNotOutputtedPicsAppending(not_outputted);
13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Include the one we've just decoded.
13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  not_outputted.push_back(pic.get());
1334a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Sort in output order.
13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::sort(not_outputted.begin(), not_outputted.end(), POCAscCompare());
13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1338a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Try to output as many pictures as we can. A picture can be output,
1339a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // if the number of decoded and not yet outputted pictures that would remain
1340a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // in DPB afterwards would at least be equal to max_num_reorder_frames.
13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the outputted picture is not a reference picture, it doesn't have
13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to remain in the DPB and can be removed.
13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  H264Picture::PtrVector::iterator output_candidate = not_outputted.begin();
1344a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  size_t num_remaining = not_outputted.size();
1345a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  while (num_remaining > max_num_reorder_frames_) {
13468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    int poc = (*output_candidate)->pic_order_cnt;
13478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    DCHECK_GE(poc, last_output_poc_);
13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!OutputPic(*output_candidate))
13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!(*output_candidate)->ref) {
13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Current picture hasn't been inserted into DPB yet, so don't remove it
13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // if we managed to output it immediately.
1354c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (*output_candidate != pic)
13558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        dpb_.DeleteByPOC(poc);
13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Mark as unused.
13578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      UnassignSurfaceFromPoC(poc);
13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1359a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1360a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    ++output_candidate;
1361a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    --num_remaining;
13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we haven't managed to output the picture that we just decoded, or if
13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // it's a reference picture, we have to store it in DPB.
13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!pic->outputted || pic->ref) {
13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dpb_.IsFull()) {
13685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // If we haven't managed to output anything to free up space in DPB
13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // to store this picture, it's an error in the stream.
13705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DVLOG(1) << "Could not free up space in DPB!";
13715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
13725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
13735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dpb_.StorePic(pic.release());
13755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
13785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static int LevelToMaxDpbMbs(int level) {
13812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // See table A-1 in spec.
13822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (level) {
13832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case 10: return 396;
13842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case 11: return 900;
13852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case 12: //  fallthrough
13862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case 13: //  fallthrough
13872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case 20: return 2376;
13882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case 21: return 4752;
13892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case 22: //  fallthrough
13902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case 30: return 8100;
13912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case 31: return 18000;
13922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case 32: return 20480;
13932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case 40: //  fallthrough
13942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case 41: return 32768;
13952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case 42: return 34816;
13962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case 50: return 110400;
13972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case 51: //  fallthrough
13982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case 52: return 184320;
13992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    default:
14002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DVLOG(1) << "Invalid codec level (" << level << ")";
14012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return 0;
14022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
14032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
14042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1405a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool VaapiH264Decoder::UpdateMaxNumReorderFrames(const media::H264SPS* sps) {
1406a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (sps->vui_parameters_present_flag && sps->bitstream_restriction_flag) {
1407a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    max_num_reorder_frames_ =
1408a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        base::checked_cast<size_t>(sps->max_num_reorder_frames);
1409a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (max_num_reorder_frames_ > dpb_.max_num_pics()) {
1410a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      DVLOG(1)
1411a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          << "max_num_reorder_frames present, but larger than MaxDpbFrames ("
1412a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          << max_num_reorder_frames_ << " > " << dpb_.max_num_pics() << ")";
1413a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      max_num_reorder_frames_ = 0;
1414a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return false;
1415a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
1416a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return true;
1417a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
1418a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1419a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // max_num_reorder_frames not present, infer from profile/constraints
1420a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // (see VUI semantics in spec).
1421a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (sps->constraint_set3_flag) {
1422a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    switch (sps->profile_idc) {
1423a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      case 44:
1424a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      case 86:
1425a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      case 100:
1426a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      case 110:
1427a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      case 122:
1428a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      case 244:
1429a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        max_num_reorder_frames_ = 0;
1430a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        break;
1431a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      default:
1432a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        max_num_reorder_frames_ = dpb_.max_num_pics();
1433a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        break;
1434a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
1435a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  } else {
1436a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    max_num_reorder_frames_ = dpb_.max_num_pics();
1437a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
1438a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1439a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return true;
1440a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
1441a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1442868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool VaapiH264Decoder::ProcessSPS(int sps_id, bool* need_new_buffers) {
14435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const media::H264SPS* sps = parser_.GetSPS(sps_id);
14445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(sps);
14457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DVLOG(4) << "Processing SPS";
14465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1447868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  *need_new_buffers = false;
1448868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1449c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (sps->frame_mbs_only_flag == 0) {
1450c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DVLOG(1) << "frame_mbs_only_flag != 1 not supported";
1451868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    report_error_to_uma_cb_.Run(FRAME_MBS_ONLY_FLAG_NOT_ONE);
1452c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
1453c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1454c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
14555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (sps->gaps_in_frame_num_value_allowed_flag) {
14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "Gaps in frame numbers not supported";
1457868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    report_error_to_uma_cb_.Run(GAPS_IN_FRAME_NUM);
14585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
14595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  curr_sps_id_ = sps->seq_parameter_set_id;
14625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Calculate picture height/width in macroblocks and pixels
14642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // (spec 7.4.2.1.1, 7.4.3).
14652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int width_mb = sps->pic_width_in_mbs_minus1 + 1;
14662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int height_mb = (2 - sps->frame_mbs_only_flag) *
14675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (sps->pic_height_in_map_units_minus1 + 1);
14685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  gfx::Size new_pic_size(16 * width_mb, 16 * height_mb);
14707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (new_pic_size.IsEmpty()) {
14717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    DVLOG(1) << "Invalid picture size: " << new_pic_size.ToString();
14722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
14732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
14742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
14757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!pic_size_.IsEmpty() && new_pic_size == pic_size_) {
14767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // Already have surfaces and this SPS keeps the same resolution,
14777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // no need to request a new set.
14787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return true;
14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  pic_size_ = new_pic_size;
14827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DVLOG(1) << "New picture size: " << pic_size_.ToString();
14835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  max_pic_order_cnt_lsb_ = 1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4);
14855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  max_frame_num_ = 1 << (sps->log2_max_frame_num_minus4 + 4);
14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int level = sps->level_idc;
14882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int max_dpb_mbs = LevelToMaxDpbMbs(level);
14892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (max_dpb_mbs == 0)
14902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
14912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
14922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  size_t max_dpb_size = std::min(max_dpb_mbs / (width_mb * height_mb),
14932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 static_cast<int>(H264DPB::kDPBMaxSize));
14942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DVLOG(1) << "Codec level: " << level << ", DPB size: " << max_dpb_size;
14953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (max_dpb_size == 0) {
14963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    DVLOG(1) << "Invalid DPB Size";
14973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return false;
14983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
14992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
15002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dpb_.set_max_num_pics(max_dpb_size);
15012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1502a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!UpdateMaxNumReorderFrames(sps))
1503a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return false;
1504a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DVLOG(1) << "max_num_reorder_frames: " << max_num_reorder_frames_;
1505a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1506868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  *need_new_buffers = true;
15075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
15085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VaapiH264Decoder::ProcessPPS(int pps_id) {
15115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const media::H264PPS* pps = parser_.GetPPS(pps_id);
15125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(pps);
15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  curr_pps_id_ = pps->pic_parameter_set_id;
15155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
15175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VaapiH264Decoder::FinishPrevFrameIfPresent() {
15205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we already have a frame waiting to be decoded, decode it and finish.
15215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (curr_pic_ != NULL) {
15225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!DecodePicture())
15235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
15245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return FinishPicture();
15255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool VaapiH264Decoder::ProcessSlice(media::H264SliceHeader* slice_hdr) {
15315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  prev_frame_num_ = frame_num_;
15325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  frame_num_ = slice_hdr->frame_num;
15335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (prev_frame_num_ > 0 && prev_frame_num_ < frame_num_ - 1) {
15355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "Gap in frame_num!";
1536868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    report_error_to_uma_cb_.Run(GAPS_IN_FRAME_NUM);
15375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
15385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (slice_hdr->field_pic_flag == 0)
15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    max_pic_num_ = max_frame_num_;
15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
15435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    max_pic_num_ = 2 * max_frame_num_;
15445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO posciak: switch to new picture detection per 7.4.1.2.4.
15465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (curr_pic_ != NULL && slice_hdr->first_mb_in_slice != 0) {
15475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This is just some more slice data of the current picture, so
15485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // just queue it and return.
15495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    QueueSlice(slice_hdr);
15505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
15515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
15525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // A new frame, so first finish the previous one before processing it...
15535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!FinishPrevFrameIfPresent())
15545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
15555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // and then start a new one.
15575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return StartNewFrame(slice_hdr);
15585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SET_ERROR_AND_RETURN()             \
15625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {                                     \
15635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "Error during decode";     \
15645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    state_ = kError;                       \
15655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return VaapiH264Decoder::kDecodeError; \
15665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (0)
15675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void VaapiH264Decoder::SetStream(const uint8* ptr,
15695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 size_t size,
15705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 int32 input_id) {
15715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(ptr);
15725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(size);
15735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Got new input stream data from the client.
1575868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DVLOG(4) << "New input stream id: " << input_id << " at: " << (void*) ptr
15765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           << " size:  " << size;
15775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parser_.SetStream(ptr, size);
1578868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  curr_input_id_ = input_id;
15795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1581868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)VaapiH264Decoder::DecResult VaapiH264Decoder::Decode() {
15825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  media::H264Parser::Result par_res;
15835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  media::H264NALU nalu;
1584868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_NE(state_, kError);
15855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (1) {
1587868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // If we've already decoded some of the stream (after reset, i.e. we are
1588868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // not in kNeedStreamMetadata state), we may be able to go back into
1589868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // decoding state not only starting at/resuming from an SPS, but also from
1590868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // other resume points, such as IDRs. In the latter case we need an output
1591868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // surface, because we will end up decoding that IDR in the process.
1592868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Otherwise we just look for an SPS and don't produce any output frames.
1593868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (state_ != kNeedStreamMetadata && available_va_surfaces_.empty()) {
15945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DVLOG(4) << "No output surfaces available";
1595868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return kRanOutOfSurfaces;
15965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1597868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
15985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    par_res = parser_.AdvanceToNextNALU(&nalu);
15995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (par_res == media::H264Parser::kEOStream)
1600868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return kRanOutOfStreamData;
16015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    else if (par_res != media::H264Parser::kOk)
16025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SET_ERROR_AND_RETURN();
16035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(4) << "NALU found: " << static_cast<int>(nalu.nal_unit_type);
16055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (nalu.nal_unit_type) {
16075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      case media::H264NALU::kNonIDRSlice:
1608868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        // We can't resume from a non-IDR slice.
1609868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        if (state_ != kDecoding)
1610868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          break;
1611868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        // else fallthrough
16125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      case media::H264NALU::kIDRSlice: {
1613868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        // TODO(posciak): the IDR may require an SPS that we don't have
1614868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        // available. For now we'd fail if that happens, but ideally we'd like
1615868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        // to keep going until the next SPS in the stream.
1616868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        if (state_ == kNeedStreamMetadata) {
1617868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          // We need an SPS, skip this IDR and keep looking.
1618868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          break;
1619868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        }
1620868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1621868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        // If after reset, we should be able to recover from an IDR.
16225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        media::H264SliceHeader slice_hdr;
16235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        par_res = parser_.ParseSliceHeader(nalu, &slice_hdr);
16255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (par_res != media::H264Parser::kOk)
16265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          SET_ERROR_AND_RETURN();
16275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!ProcessSlice(&slice_hdr))
16295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          SET_ERROR_AND_RETURN();
1630868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1631868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        state_ = kDecoding;
16325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
16335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
16345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      case media::H264NALU::kSPS: {
16365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int sps_id;
16375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!FinishPrevFrameIfPresent())
16395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          SET_ERROR_AND_RETURN();
16405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        par_res = parser_.ParseSPS(&sps_id);
16425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (par_res != media::H264Parser::kOk)
16435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          SET_ERROR_AND_RETURN();
16445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        bool need_new_buffers = false;
1646868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        if (!ProcessSPS(sps_id, &need_new_buffers))
16475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          SET_ERROR_AND_RETURN();
1648868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1649868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        state_ = kDecoding;
1650868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
16517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        if (need_new_buffers) {
16527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          if (!Flush())
16537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            return kDecodeError;
1654868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
16557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          available_va_surfaces_.clear();
16567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          return kAllocateNewSurfaces;
16577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        }
16585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1659868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      }
1660868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
16615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      case media::H264NALU::kPPS: {
1662868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        if (state_ != kDecoding)
1663868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          break;
16645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int pps_id;
16665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!FinishPrevFrameIfPresent())
16685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          SET_ERROR_AND_RETURN();
16695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        par_res = parser_.ParsePPS(&pps_id);
16715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (par_res != media::H264Parser::kOk)
16725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          SET_ERROR_AND_RETURN();
16735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!ProcessPPS(pps_id))
16755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          SET_ERROR_AND_RETURN();
16765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1677868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      }
16785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
1680a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        DVLOG(4) << "Skipping NALU type: " << nalu.nal_unit_type;
16815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
16825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
16835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t VaapiH264Decoder::GetRequiredNumOfPictures() {
16872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return dpb_.max_num_pics() + kPicsInPipeline;
16885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace content
1691