kodi
DXVA.h
1 /*
2  * Copyright (C) 2005-2018 Team Kodi
3  * This file is part of Kodi - https://kodi.tv
4  *
5  * SPDX-License-Identifier: GPL-2.0-or-later
6  * See LICENSES/README.md for more information.
7  */
8 
9 #pragma once
10 
11 #include "cores/VideoPlayer/Buffers/VideoBuffer.h"
12 #include "cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodec.h"
13 #include "guilib/D3DResource.h"
14 #include "threads/Event.h"
15 
16 #include <mutex>
17 #include <vector>
18 
19 #include <d3d11_4.h>
20 #include <wrl/client.h>
21 extern "C"
22 {
23 #include <libavcodec/avcodec.h>
24 #include <libavcodec/d3d11va.h>
25 }
26 
27 namespace DXVA
28 {
29 class CDecoder;
30 
32 {
33  template<typename TBuffer>
34  friend class CVideoBufferPoolTyped;
35 
36 public:
37  virtual ~CVideoBuffer();
38 
39  void SetRef(AVFrame* frame);
40  void Unref();
41 
42  virtual void Initialize(CDecoder* decoder);
43  virtual HRESULT GetResource(ID3D11Resource** ppResource);
44  virtual unsigned GetIdx();
45 
46  ID3D11View* view = nullptr;
47  DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN;
48  unsigned width = 0;
49  unsigned height = 0;
50 
51 protected:
52  explicit CVideoBuffer(int id);
53 
54 private:
55  AVFrame* m_pFrame{nullptr};
56 };
57 
59 {
60  template<typename TBuffer>
61  friend class CVideoBufferPoolTyped;
62 
63 public:
64  HRESULT GetResource(ID3D11Resource** ppResource) override;
65  void Initialize(CDecoder* decoder) override;
66  virtual ~CVideoBufferShared();
67 
68 protected:
69  explicit CVideoBufferShared(int id)
70  : CVideoBuffer(id) {}
71  void InitializeFence(CDecoder* decoder);
72  void SetFence();
73 
74  HANDLE handle = INVALID_HANDLE_VALUE;
75  Microsoft::WRL::ComPtr<ID3D11Resource> m_sharedRes;
76 
78  Microsoft::WRL::ComPtr<ID3D11Fence> m_fence;
80  Microsoft::WRL::ComPtr<ID3D11DeviceContext4> m_deviceContext4;
82  HANDLE m_handleFence{INVALID_HANDLE_VALUE};
83  UINT64 m_fenceValue{0};
85  Microsoft::WRL::ComPtr<ID3D11Fence> m_appFence;
87  Microsoft::WRL::ComPtr<ID3D11DeviceContext4> m_appContext4;
88 };
89 
91 {
92  template<typename TBuffer>
93  friend class CVideoBufferPoolTyped;
94 
95 public:
96  void Initialize(CDecoder* decoder) override;
97  unsigned GetIdx() override { return 0; }
98 
99 protected:
100  explicit CVideoBufferCopy(int id)
101  : CVideoBufferShared(id) {}
102 
103  Microsoft::WRL::ComPtr<ID3D11Resource> m_copyRes;
104  Microsoft::WRL::ComPtr<ID3D11Resource> m_pResource;
105  Microsoft::WRL::ComPtr<ID3D11DeviceContext> m_pDeviceContext;
106 };
107 
108 class CContext
109 {
110 public:
111  typedef std::shared_ptr<CContext> shared_ptr;
112  typedef std::weak_ptr<CContext> weak_ptr;
113 
114  ~CContext();
115 
116  static shared_ptr EnsureContext(CDecoder* decoder);
117  bool GetFormatAndConfig(AVCodecContext* avctx, D3D11_VIDEO_DECODER_DESC& format, D3D11_VIDEO_DECODER_CONFIG& config) const;
118  bool CreateSurfaces(const D3D11_VIDEO_DECODER_DESC& format, uint32_t count, uint32_t alignment,
119  ID3D11VideoDecoderOutputView** surfaces, HANDLE* pHandle, bool trueShared) const;
120  bool CreateDecoder(const D3D11_VIDEO_DECODER_DESC& format, const D3D11_VIDEO_DECODER_CONFIG& config,
121  ID3D11VideoDecoder** decoder, ID3D11VideoContext** context);
122  void Release(CDecoder* decoder);
123 
124  bool Check() const;
125  bool Reset();
126  bool IsContextShared() const
127  {
128  return m_sharingAllowed;
129  }
130  bool HasAMDWorkaround() const
131  {
132  return m_atiWorkaround;
133  }
134 
135 private:
136  explicit CContext() = default;
137 
138  void Close();
139  bool CreateContext();
140  void DestroyContext();
141  void QueryCaps();
142  bool IsValidDecoder(CDecoder* decoder);
143  bool GetConfig(const D3D11_VIDEO_DECODER_DESC& format, D3D11_VIDEO_DECODER_CONFIG& config) const;
144 
145  static weak_ptr m_context;
146  static CCriticalSection m_section;
147 
148  UINT m_input_count = 0;
149  GUID* m_input_list = nullptr;
150  bool m_atiWorkaround = false;
151  bool m_sharingAllowed = false;
152  Microsoft::WRL::ComPtr<ID3D11VideoContext> m_pD3D11Context;
153  Microsoft::WRL::ComPtr<ID3D11VideoDevice> m_pD3D11Device;
154 #ifdef _DEBUG
155  Microsoft::WRL::ComPtr<ID3D11Debug> m_d3d11Debug;
156 #endif
157 
158  std::vector<CDecoder*> m_decoders;
159 };
160 
162 {
163 public:
164  typedef std::shared_ptr<CVideoBufferPool> shared_ptr;
165 
167  virtual ~CVideoBufferPool();
168 
169  // IVideoBufferPool overrides
170  ::CVideoBuffer* Get() override;
171  void Return(int id) override;
172 
173  // views pool
174  void AddView(ID3D11View* view);
175  bool ReturnView(ID3D11View* view);
176  ID3D11View* GetView();
177  bool IsValid(ID3D11View* view);
178  size_t Size();
179  bool HasFree();
180 
181 protected:
182  void Reset();
183  virtual CVideoBuffer* CreateBuffer(int idx) = 0;
184 
185  CCriticalSection m_section;
186 
187  std::vector<ID3D11View*> m_views;
188  std::deque<size_t> m_freeViews;
189  std::vector<CVideoBuffer*> m_out;
190  std::deque<size_t> m_freeOut;
191 };
192 
193 template<typename TBuffer>
195 {
196 protected:
197  CVideoBuffer* CreateBuffer(int idx) override
198  {
199  return new TBuffer(idx);
200  }
201 };
202 
203 class CDecoder : public IHardwareDecoder, public ID3DResource
204 {
205 public:
206  ~CDecoder() override;
207 
208  static IHardwareDecoder* Create(CDVDStreamInfo& hint, CProcessInfo& processInfo, AVPixelFormat fmt);
209  static bool Register();
210 
211  // IHardwareDecoder overrides
212  bool Open(AVCodecContext* avctx, AVCodecContext* mainctx, const enum AVPixelFormat) override;
213  CDVDVideoCodec::VCReturn Decode(AVCodecContext* avctx, AVFrame* frame) override;
214  bool GetPicture(AVCodecContext* avctx, VideoPicture* picture) override;
215  CDVDVideoCodec::VCReturn Check(AVCodecContext* avctx) override;
216  const std::string Name() override { return "d3d11va"; }
217  unsigned GetAllowedReferences() override;
218  void Reset() override;
219 
220  bool OpenDecoder();
221  int GetBuffer(AVCodecContext* avctx, AVFrame* pic);
222  void ReleaseBuffer(uint8_t* data);
223  void Close();
224  void CloseDXVADecoder();
225 
226  //static members
227  static bool Supports(enum AVPixelFormat fmt);
228  static int FFGetBuffer(AVCodecContext* avctx, AVFrame* pic, int flags);
229  static void FFReleaseBuffer(void* opaque, uint8_t* data);
230 
231 protected:
232  friend CVideoBuffer;
233  friend CVideoBufferShared;
234  friend CVideoBufferCopy;
235 
236  explicit CDecoder(CProcessInfo& processInfo);
237 
238  enum EDeviceState
239  {
240  DXVA_OPEN,
241  DXVA_RESET,
242  DXVA_LOST
243  } m_state = DXVA_OPEN;
244 
245 
246  // ID3DResource overrides
247  void OnCreateDevice() override
248  {
249  std::unique_lock<CCriticalSection> lock(m_section);
250  m_state = DXVA_RESET;
251  m_event.Set();
252  }
253  void OnDestroyDevice(bool fatal) override
254  {
255  std::unique_lock<CCriticalSection> lock(m_section);
256  m_state = DXVA_LOST;
257  m_event.Reset();
258  }
259 
260  CEvent m_event;
261  CCriticalSection m_section;
262  CProcessInfo& m_processInfo;
263  Microsoft::WRL::ComPtr<ID3D11VideoDecoder> m_pD3D11Decoder;
264  Microsoft::WRL::ComPtr<ID3D11VideoContext> m_pD3D11Context;
265  CVideoBufferPool::shared_ptr m_bufferPool;
266  CContext::shared_ptr m_dxvaContext;
267  CVideoBuffer* m_videoBuffer = nullptr;
268  struct AVD3D11VAContext* m_avD3D11Context = nullptr;
269  int m_refs = 0;
270  unsigned int m_shared = 0;
271  unsigned int m_surface_alignment = 0;
272  HANDLE m_sharedHandle = INVALID_HANDLE_VALUE;
273  D3D11_VIDEO_DECODER_DESC m_format = {};
274  bool m_DVDWorkaround = false;
275 };
276 
277 } // namespace DXVA
This is an Event class built from a ConditionVariable.
Definition: Event.h:35
Definition: XHandle.h:21
Definition: DXVA.h:31
Definition: DVDStreamInfo.h:25
Definition: deflate.c:123
Microsoft::WRL::ComPtr< ID3D11Fence > m_appFence
app-side fence object
Definition: DXVA.h:85
Definition: DXVA.h:161
Definition: DXVA.h:58
Definition: DVDVideoCodec.h:248
Definition: DXVA.h:194
Definition: VideoBuffer.h:51
Microsoft::WRL::ComPtr< ID3D11DeviceContext4 > m_deviceContext4
decoder-side context
Definition: DXVA.h:80
Microsoft::WRL::ComPtr< ID3D11DeviceContext4 > m_appContext4
app-side context
Definition: DXVA.h:87
Definition: DXVA.h:27
Definition: DXVA.h:108
Definition: DXVA.h:90
Definition: ProcessInfo.h:26
Definition: DXVA.h:203
Definition: D3DResource.h:36
Microsoft::WRL::ComPtr< ID3D11Fence > m_fence
decoder-side fence object
Definition: DXVA.h:78
Definition: DVDVideoCodec.h:36