1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156
  157
  158
  159
  160
  161
  162
  163
  164
  165
  166
  167
  168

media / gpu / vaapi / test / h265_dpb.h [blame]

// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef MEDIA_GPU_VAAPI_TEST_H265_DPB_H_
#define MEDIA_GPU_VAAPI_TEST_H265_DPB_H_

#include <vector>

#include "base/memory/ref_counted.h"
#include "media/gpu/vaapi/test/shared_va_surface.h"
#include "media/parsers/h265_parser.h"
#include "ui/gfx/geometry/rect.h"

namespace media::vaapi_test {

#define LOG_PIC_INFO(func, pic, fetch_policy)                                \
  do {                                                                       \
    VLOG(3) << func << "," << pic->pic_order_cnt_val_ << ","                 \
            << pic->nal_unit_type_ << ","                                    \
            << pic->surface->GetMD5Sum(fetch_policy) << ","                  \
            << pic->pic_output_flag_ << ","                                  \
            << pic->no_output_of_prior_pics_flag_ << "," << pic->outputted_; \
  } while (0)

// A picture (a frame or a field) in the H.265 spec sense.
// See spec at http://www.itu.int/rec/T-REC-H.265
class H265Picture : public base::RefCountedThreadSafe<H265Picture> {
 public:
  using Vector = std::vector<scoped_refptr<H265Picture>>;

  explicit H265Picture(scoped_refptr<SharedVASurface> target_surface);

  H265Picture(const H265Picture&) = delete;
  H265Picture& operator=(const H265Picture&) = delete;

  enum ReferenceType {
    kUnused = 0,
    kShortTermCurrBefore = 1,
    kShortTermCurrAfter = 2,
    kShortTermFoll = 3,
    kLongTermCurr = 4,
    kLongTermFoll = 5,
  };

  static std::string GetReferenceName(ReferenceType ref) {
    if (ref == kUnused)
      return "Unused";
    else if (ref == kLongTermCurr || ref == kLongTermFoll)
      return "LongTerm";
    else
      return "ShortTerm";
  }

  bool IsLongTermRef() const {
    return ref_ == kLongTermCurr || ref_ == kLongTermFoll;
  }
  bool IsShortTermRef() const {
    return ref_ == kShortTermCurrBefore || ref_ == kShortTermCurrAfter ||
           ref_ == kShortTermFoll;
  }
  bool IsUnused() const { return ref_ == kUnused; }

  const gfx::Rect visible_rect() const { return visible_rect_; }
  void set_visible_rect(const gfx::Rect& rect) { visible_rect_ = rect; }

  // Values calculated per H.265 specification or taken from slice header.
  // See spec for more details on each (some names have been converted from
  // CamelCase in spec to Chromium-style names).
  int nal_unit_type_;
  bool no_rasl_output_flag_{false};
  bool no_output_of_prior_pics_flag_{false};
  bool pic_output_flag_{false};
  bool valid_for_prev_tid0_pic_{false};
  int slice_pic_order_cnt_lsb_{0};
  int pic_order_cnt_msb_{0};
  int pic_order_cnt_val_{0};

  // Our own state variables.
  bool irap_pic_;
  bool first_picture_;
  bool processed_{false};

  ReferenceType ref_{kUnused};

  bool outputted_{false};

  scoped_refptr<SharedVASurface> surface;

 protected:
  friend class base::RefCountedThreadSafe<H265Picture>;
  virtual ~H265Picture();

 private:
  gfx::Rect visible_rect_;
};

// DPB - Decoded Picture Buffer.
// Stores decoded pictures that will be used for future display and/or
// reference.
class H265DPB {
 public:
  H265DPB();

  H265DPB(const H265DPB&) = delete;
  H265DPB& operator=(const H265DPB&) = delete;

  ~H265DPB();

  void set_max_num_pics(size_t max_num_pics);
  size_t max_num_pics() const { return max_num_pics_; }

  // Removes all entries from the DPB.
  void Clear();

  // Stores |pic| in the DPB. If |used_for_long_term| is true it'll be marked as
  // used for long term reference, otherwise it'll be marked as used for short
  // term reference.
  void StorePicture(scoped_refptr<H265Picture> pic,
                    H265Picture::ReferenceType ref);

  // Mark all pictures in DPB as unused for reference.
  void MarkAllUnusedForReference();

  // Removes all pictures from the DPB that do not have |pic_output_flag_| set
  // and are marked Unused for reference.
  void DeleteUnused();

  // Returns the number of pictures in the DPB that are marked for reference.
  int GetReferencePicCount();

  // Returns a picture in the DPB which has a POC equal to |poc| and marks it
  // with |ref| reference type. If not found, returns nullptr.
  scoped_refptr<H265Picture> GetPicByPocAndMark(int poc,
                                                H265Picture::ReferenceType ref);

  // Returns a picture in the DPB which has a POC bitmasked by |mask| which
  // equals |poc| and marks it with |ref| reference type. If not found, returns
  // nullptr. If |mask| is zero, then no bitmasking is done.
  scoped_refptr<H265Picture>
  GetPicByPocMaskedAndMark(int poc, int mask, H265Picture::ReferenceType ref);

  // Appends to |out| all of the pictures in the DPB that are flagged for output
  // but have not be outputted yet.
  void AppendPendingOutputPics(H265Picture::Vector* out);

  // Appends to |out| all of the pictures in the DPB that are not marked as
  // unused for reference.
  void AppendReferencePics(H265Picture::Vector* out);

  size_t size() const { return pics_.size(); }
  bool IsFull() const { return pics_.size() >= max_num_pics_; }

  // Sets the fetch_policy, which allow the dpb to get the MD5
  // value of the picture.
  void SetFetchPolicy(SharedVASurface::FetchPolicy fetch_policy) {
    fetch_policy_ = fetch_policy;
  }

 private:
  H265Picture::Vector pics_;
  size_t max_num_pics_{0};
  SharedVASurface::FetchPolicy fetch_policy_;
};

}  // namespace media::vaapi_test

#endif  // MEDIA_GPU_VAAPI_TEST_H265_DPB_H_