chromium/media/gpu/windows/d3d12_helpers.h

// Copyright 2024 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_D3D12_HELPERS_H_
#define MEDIA_GPU_WINDOWS_D3D12_HELPERS_H_

#include <wrl.h>

#include <array>
#include <memory>

#include "media/base/limits.h"
#include "media/base/video_codecs.h"
#include "media/base/video_types.h"
#include "media/gpu/h264_dpb.h"
#include "media/gpu/media_gpu_export.h"
#include "media/gpu/windows/d3d_com_defs.h"
#include "media/parsers/h265_parser.h"
#include "media/parsers/vp9_parser.h"
#include "third_party/abseil-cpp/absl/container/inlined_vector.h"
#include "third_party/libgav1/src/src/utils/constants.h"

namespace media {

// Manages reference frame buffers, for reference frame descriptors to index on.
class MEDIA_GPU_EXPORT D3D12ReferenceFrameList {
 public:
  explicit D3D12ReferenceFrameList(ComD3D12VideoDecoderHeap heap);
  ~D3D12ReferenceFrameList();

  void WriteTo(D3D12_VIDEO_DECODE_REFERENCE_FRAMES* dest);

  void emplace(size_t index, ID3D12Resource* resource, UINT subresource);

 private:
  // Max size of picture_buffers_ that D3D11VideoDecoder may create.
  static constexpr size_t kMaxSize =
      std::max({static_cast<size_t>(H264DPB::kDPBMaxSize),
                static_cast<size_t>(/*H265*/ kMaxDpbSize),
                static_cast<size_t>(kVp9NumRefFrames),
                static_cast<size_t>(libgav1::kNumReferenceFrameTypes)}) +
      limits::kMaxVideoFrames + 2;

  ComD3D12VideoDecoderHeap heap_;
  size_t size_ = 0;
  // D3D12_VIDEO_DECODE_REFERENCE_FRAMES has ID3D12Resource** ppTexture2Ds, so
  // we have to store raw pointer array here. The pointers are only passed to
  // D3D12 API and we never dereference it in Chromium.
  // The lifetime of these |resources_| is managed by |D3D11VideoDecoder|'s
  // |picture_buffers_|. When picture buffers are invalidated, the
  // D3D12VideoDecoderWrapper and its ID3D12VideoDecoder instance will be
  // destroyed ensuring these values are no longer referenced.
  std::array<ID3D12Resource*, kMaxSize> resources_;
  std::array<UINT, kMaxSize> subresources_;
  // D3D12_VIDEO_DECODE_REFERENCE_FRAMES also has ID3D12VideoDecoderHeap**
  // ppHeaps. The items in |heaps_| are always |heap_.Get()|.
  std::array<ID3D12VideoDecoderHeap*, kMaxSize> heaps_;
};

MEDIA_GPU_EXPORT ComD3D12Device CreateD3D12Device(IDXGIAdapter* adapter);

// In D3D12 resource barriers, subresource id is not only being composed of mip
// level id and array index id, but also plane id. This method is to create an
// vector of transition barriers for all planes if there is more than one (like
// Y plane and UV plane for NV12).
MEDIA_GPU_EXPORT absl::InlinedVector<D3D12_RESOURCE_BARRIER, 2>
CreateD3D12TransitionBarriersForAllPlanes(ID3D12Resource* resource,
                                          UINT subresource,
                                          D3D12_RESOURCE_STATES state_before,
                                          D3D12_RESOURCE_STATES state_after);

// Get the profile GUID for creating ID3D12VideoDecoder. The |bitdepth| and
// |chroma_sampling| will only be checked when the |profile| is
// HEVCPROFILE_REXT.
MEDIA_GPU_EXPORT GUID
GetD3D12VideoDecodeGUID(VideoCodecProfile profile,
                        uint8_t bitdepth,
                        VideoChromaSampling chroma_sampling);

}  // namespace media

#endif  // MEDIA_GPU_WINDOWS_D3D12_HELPERS_H_