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
  169
  170
  171
  172
  173
  174
  175
  176
  177
  178
  179
  180
  181
  182
  183
  184
  185
  186
  187
  188
  189

media / gpu / windows / d3d11_h265_accelerator.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_WINDOWS_D3D11_H265_ACCELERATOR_H_
#define MEDIA_GPU_WINDOWS_D3D11_H265_ACCELERATOR_H_

#include <d3d11_1.h>
#include <d3d9.h>
#include <dxva.h>

#include "base/memory/raw_ptr.h"
#include "gpu/command_buffer/service/texture_manager.h"
#include "media/base/video_frame.h"
#include "media/base/win/mf_helpers.h"
#include "media/gpu/h265_decoder.h"
#include "media/gpu/h265_dpb.h"
#include "media/gpu/windows/d3d11_video_decoder_client.h"
#include "third_party/angle/include/EGL/egl.h"
#include "third_party/angle/include/EGL/eglext.h"

namespace media {

// Maximum of valid DXVA_PicEntry_HEVC entries in RefPicList
constexpr unsigned kMaxRefPicListSize = 15;

class MediaLog;

// Picture Parameters DXVA buffer struct for Rext/Scc is not specified in DXVA
// spec. The below structures come from Intel platform DDI definition, so they
// are currently Intel specific.
// For NVidia and AMD platforms supporting HEVC Rext & Scc, it is expected
// the picture param information included in below structures is sufficient
// for underlying drivers supporting range extension/Scc.
#pragma pack(push, 1)
typedef struct {
  DXVA_PicParams_HEVC main;

  // HEVC Range Extension. Fields are named the same as in HEVC spec.
  union {
    struct {
      UINT32 transform_skip_rotation_enabled_flag : 1;
      UINT32 transform_skip_context_enabled_flag : 1;
      UINT32 implicit_rdpcm_enabled_flag : 1;
      UINT32 explicit_rdpcm_enabled_flag : 1;
      UINT32 extended_precision_processing_flag : 1;
      UINT32 intra_smoothing_disabled_flag : 1;
      UINT32 high_precision_offsets_enabled_flag : 1;
      UINT32 persistent_rice_adaptation_enabled_flag : 1;
      UINT32 cabac_bypass_alignment_enabled_flag : 1;
      UINT32 cross_component_prediction_enabled_flag : 1;
      UINT32 chroma_qp_offset_list_enabled_flag : 1;
      // Indicates if luma bit depth equals to 16. If its value is 1, the
      // corresponding bit_depth_luma_minus8 must be set to 0.
      UINT32 BitDepthLuma16 : 1;
      // Indicates if chroma bit depth equals to 16. If its value is 1, the
      // corresponding bit_depth_chroma_minus8 must be set to 0.
      UINT32 BitDepthChroma16 : 1;
      UINT32 ReservedBits8 : 19;
    };
    UINT32 dwRangeExtensionFlags;
  };

  UCHAR diff_cu_chroma_qp_offset_depth;    // [0..3]
  UCHAR chroma_qp_offset_list_len_minus1;  // [0..5]
  UCHAR log2_sao_offset_scale_luma;        // [0..6]
  UCHAR log2_sao_offset_scale_chroma;      // [0..6]
  UCHAR log2_max_transform_skip_block_size_minus2;
  CHAR cb_qp_offset_list[6];  // [-12..12]
  CHAR cr_qp_offset_list[6];  // [-12..12]
} DXVA_PicParams_HEVC_Rext;

typedef struct {
  DXVA_PicParams_HEVC_Rext main_rext;

  // HEVC Screen Content Coding. Fields are named the same as in HEVC spec.
  union {
    struct {
      UINT32 pps_curr_pic_ref_enabled_flag : 1;
      UINT32 palette_mode_enabled_flag : 1;
      UINT32 motion_vector_resolution_control_idc : 2;
      UINT32 intra_boundary_filtering_disabled_flag : 1;
      UINT32 residual_adaptive_coloour_transform_enabled_flag : 1;
      UINT32 pps_slice_act_qp_offsets_present_flag : 1;
      UINT32 ReservedBits9 : 25;
    };
    UINT dwSccExtensionFlags;
  };

  UCHAR palette_max_size;                  // [0..64]
  UCHAR delta_palette_max_predictor_size;  // [0..128]
  UCHAR PredictorPaletteSize;              // [0..127]
  USHORT PredictorPaletteEntries[3][128];
  CHAR pps_act_y_qp_offset_plus5;   // [-7..17]
  CHAR pps_act_cb_qp_offset_plus5;  // [-7..17]
  CHAR pps_act_cr_qp_offset_plus3;  // [-9..15]
} DXVA_PicParams_HEVC_SCC;
#pragma pack(pop)

class D3D11H265Accelerator : public H265Decoder::H265Accelerator {
 public:
  D3D11H265Accelerator(D3D11VideoDecoderClient* client, MediaLog* media_log);

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

  ~D3D11H265Accelerator() override;

  // H265Decoder::H265Accelerator implementation.
  scoped_refptr<H265Picture> CreateH265Picture() override;
  Status SubmitFrameMetadata(
      const H265SPS* sps,
      const H265PPS* pps,
      const H265SliceHeader* slice_hdr,
      const H265Picture::Vector& ref_pic_list,
      const H265Picture::Vector& ref_pic_set_lt_curr,
      const H265Picture::Vector& ref_pic_set_st_curr_after,
      const H265Picture::Vector& ref_pic_set_st_curr_before,
      scoped_refptr<H265Picture> pic) override;
  Status SubmitSlice(const H265SPS* sps,
                     const H265PPS* pps,
                     const H265SliceHeader* slice_hdr,
                     const H265Picture::Vector& ref_pic_list0,
                     const H265Picture::Vector& ref_pic_list1,
                     const H265Picture::Vector& ref_pic_set_lt_curr,
                     const H265Picture::Vector& ref_pic_set_st_curr_after,
                     const H265Picture::Vector& ref_pic_set_st_curr_before,
                     scoped_refptr<H265Picture> pic,
                     const uint8_t* data,
                     size_t size,
                     const std::vector<SubsampleEntry>& subsamples) override;
  Status SubmitDecode(scoped_refptr<H265Picture> pic) override;
  void Reset() override;
  bool OutputPicture(scoped_refptr<H265Picture> pic) override;
  Status SetStream(base::span<const uint8_t> stream,
                   const DecryptConfig* decrypt_config) override;
  bool IsChromaSamplingSupported(VideoChromaSampling chroma_sampling) override;

 private:
  // Gets a pic params struct with the constant fields set.
  void FillPicParamsWithConstants(DXVA_PicParams_HEVC_Rext* pic_param);

  // Populate the pic params with fields from the SPS structure.
  void PicParamsFromSPS(DXVA_PicParams_HEVC_Rext* pic_param,
                        const H265SPS* sps);

  // Populate the pic params with fields from the PPS structure.
  void PicParamsFromPPS(DXVA_PicParams_HEVC_Rext* pic_param,
                        const H265PPS* pps);

  // Populate the pic params with fields from the slice header structure.
  void PicParamsFromSliceHeader(DXVA_PicParams_HEVC_Rext* pic_param,
                                const H265SPS* sps,
                                const H265SliceHeader* slice_hdr);

  // Populate the pic params with fields from the picture passed in.
  void PicParamsFromPic(DXVA_PicParams_HEVC_Rext* pic_param,
                        D3D11H265Picture* pic);

  // Populate the pic params with fields from ref_pic_set_lt_curr,
  // ref_pic_set_st_curr_after and ref_pic_set_st_curr_before
  bool PicParamsFromRefLists(
      DXVA_PicParams_HEVC_Rext* pic_param,
      const H265Picture::Vector& ref_pic_set_lt_curr,
      const H265Picture::Vector& ref_pic_set_st_curr_after,
      const H265Picture::Vector& ref_pic_set_st_curr_before);

  std::unique_ptr<MediaLog> media_log_;
  raw_ptr<D3D11VideoDecoderClient> client_;

  // This information set at the beginning of a frame and saved for processing
  // all the slices.
  DXVA_PicEntry_HEVC ref_frame_list_[kMaxRefPicListSize];
  int ref_frame_pocs_[kMaxRefPicListSize];
  base::flat_map<int, int> poc_index_into_ref_pic_list_;
  bool use_scaling_lists_ = false;
  // If current stream is encoded with range extension profile.
  bool is_rext_ = false;

  // For HEVC this number needs to be larger than 1 and different
  // in each call to Execute().
  int current_status_report_feedback_num_ = 1;

  uint32_t current_frame_size_ = 0;
};

}  // namespace media

#endif  // MEDIA_GPU_WINDOWS_D3D11_H265_ACCELERATOR_H_