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
|
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFFMPEGHWACCEL_D3D11_P_H
#define QFFMPEGHWACCEL_D3D11_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include "qffmpeghwaccel_p.h"
#include <private/quniquehandle_p.h>
#include <private/qcomptr_p.h>
#include <qt_windows.h>
#include <d3d11.h>
#include <d3d11_1.h>
#if QT_CONFIG(wmf)
QT_BEGIN_NAMESPACE
class QRhi;
namespace QFFmpeg {
struct SharedTextureHandleTraits
{
using Type = HANDLE;
static Type invalidValue() { return nullptr; }
static bool close(Type handle) { return CloseHandle(handle) != 0; }
};
using SharedTextureHandle = QUniqueHandle<SharedTextureHandleTraits>;
/*! \internal Utility class for synchronized transfer of a texture between two D3D devices
*
* This class is used to copy a texture from one device to another device. This
* is implemented using a shared texture, along with keyed mutexes to synchronize
* access to the texture.
*
* This is needed because we need to copy data from FFmpeg to RHI. FFmpeg and RHI
* uses different D3D devices.
*/
class TextureBridge final
{
public:
/** Copy a texture slice at position 'index' belonging to device 'dev'
* into a shared texture, limiting the texture size to the frame size */
bool copyToSharedTex(ID3D11Device *dev, ID3D11DeviceContext *ctx,
const ComPtr<ID3D11Texture2D> &tex, UINT index, const QSize &frameSize);
/** Obtain a copy of the texture on a second device 'dev' */
ComPtr<ID3D11Texture2D> copyFromSharedTex(const ComPtr<ID3D11Device1> &dev,
const ComPtr<ID3D11DeviceContext> &ctx);
private:
bool ensureDestTex(const ComPtr<ID3D11Device1> &dev);
bool ensureSrcTex(ID3D11Device *dev, const ComPtr<ID3D11Texture2D> &tex, const QSize &frameSize);
bool isSrcInitialized(const ID3D11Device *dev, const ComPtr<ID3D11Texture2D> &tex, const QSize &frameSize) const;
bool recreateSrc(ID3D11Device *dev, const ComPtr<ID3D11Texture2D> &tex, const QSize &frameSize);
SharedTextureHandle m_sharedHandle{};
const UINT m_srcKey = 0;
ComPtr<ID3D11Texture2D> m_srcTex;
ComPtr<IDXGIKeyedMutex> m_srcMutex;
const UINT m_destKey = 1;
ComPtr<ID3D11Device1> m_destDevice;
ComPtr<ID3D11Texture2D> m_destTex;
ComPtr<IDXGIKeyedMutex> m_destMutex;
ComPtr<ID3D11Texture2D> m_outputTex;
};
class D3D11TextureConverter : public TextureConverterBackend
{
public:
D3D11TextureConverter(QRhi *rhi);
TextureSet *getTextures(AVFrame *frame) override;
static void SetupDecoderTextures(AVCodecContext *s);
private:
ComPtr<ID3D11Device1> m_rhiDevice;
ComPtr<ID3D11DeviceContext> m_rhiCtx;
TextureBridge m_bridge;
};
} // namespace QFFmpeg
QT_END_NAMESPACE
#endif
#endif
|