Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qffmpegtextureconverter.cpp
Go to the documentation of this file.
1// Copyright (C) 2024 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include <QtFFmpegMediaPluginImpl/private/qffmpegtextureconverter_p.h>
5
6#include <QtFFmpegMediaPluginImpl/private/qffmpeghwaccel_p.h>
7
8#include <rhi/qrhi.h>
9
10#include <q20type_traits.h>
11
12#if QT_CONFIG(vaapi)
13# include <QtFFmpegMediaPluginImpl/private/qffmpeghwaccel_vaapi_p.h>
14#endif
15
16#ifdef Q_OS_DARWIN
17# include <QtFFmpegMediaPluginImpl/private/qffmpeghwaccel_videotoolbox_p.h>
18#endif
19
20#ifdef Q_OS_WINDOWS
21# include <QtFFmpegMediaPluginImpl/private/qffmpeghwaccel_d3d11_p.h>
22#endif
23
24#ifdef Q_OS_ANDROID
25# include <QtFFmpegMediaPluginImpl/private/qffmpeghwaccel_mediacodec_p.h>
26#endif
27
28#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
29# include <QtFFmpegMediaPluginImpl/private/qffmpeghwaccel_cuda_p.h>
30#endif
31
33
34using namespace QFFmpeg;
35
36namespace {
37
38template <typename Converter>
39using ConverterTypeIdentity = q20::type_identity<Converter>;
40
41template <typename ConverterTypeHandler>
42void applyConverterTypeByPixelFormat(AVFrame &hwFrame, QRhi &rhi, ConverterTypeHandler &&handler)
43{
44 if (!TextureConverter::hwTextureConversionEnabled())
45 return;
46
47 switch (AVPixelFormat(hwFrame.format)) {
48#if QT_CONFIG(vaapi)
49 case AV_PIX_FMT_VAAPI:
50 handler(ConverterTypeIdentity<VAAPITextureConverter>{});
51 break;
52#endif
53#ifdef Q_OS_DARWIN
54 case AV_PIX_FMT_VIDEOTOOLBOX:
55 handler(ConverterTypeIdentity<VideoToolBoxTextureConverter>{});
56 break;
57#endif
58#ifdef Q_OS_WINDOWS
59 case AV_PIX_FMT_D3D11:
60 if (D3D11TextureConverter::isSupported(hwFrame, rhi))
61 handler(ConverterTypeIdentity<D3D11TextureConverter>{});
62 break;
63#endif
64#ifdef Q_OS_ANDROID
65 case AV_PIX_FMT_MEDIACODEC:
66 handler(ConverterTypeIdentity<MediaCodecTextureConverter>{});
67 break;
68#endif
69#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
70 case AV_PIX_FMT_CUDA:
71 handler(ConverterTypeIdentity<CUDATextureConverterFactory>{});
72 break;
73#endif
74 default:
75 Q_UNUSED(handler)
76 Q_UNUSED(rhi)
77 break;
78 }
79}
80
81} // namespace
82
83TextureConverterBackend::~TextureConverterBackend() = default;
84
85TextureConverter::TextureConverter(QRhi &rhi) : m_rhi(rhi) { }
86
87bool TextureConverter::init(AVFrame &hwFrame)
88{
89 Q_ASSERT(hwFrame.hw_frames_ctx);
90 if (AVPixelFormat(hwFrame.format) != m_format)
91 updateBackend(hwFrame);
92 return !isNull();
93}
94
95QVideoFrameTexturesUPtr TextureConverter::createTextures(AVFrame &hwFrame,
96 QVideoFrameTexturesUPtr &oldTextures)
97{
98 if (isNull())
99 return nullptr;
100
101 Q_ASSERT(hwFrame.format == m_format);
102 return m_backend->createTextures(&hwFrame, oldTextures);
103}
104
105QVideoFrameTexturesHandlesUPtr
106TextureConverter::createTextureHandles(AVFrame &hwFrame, QVideoFrameTexturesHandlesUPtr oldHandles)
107{
108 if (isNull())
109 return nullptr;
110
111 Q_ASSERT(hwFrame.format == m_format);
112 return m_backend->createTextureHandles(&hwFrame, std::move(oldHandles));
113}
114
115void TextureConverter::updateBackend(AVFrame &hwFrame)
116{
117 m_backend = nullptr;
118 m_format = AVPixelFormat(hwFrame.format); // should be saved even if m_backend is not created
119
120 applyConverterTypeByPixelFormat(hwFrame, m_rhi, [this](auto converterTypeIdentity) {
121 using ConverterType = typename decltype(converterTypeIdentity)::type;
122 m_backend = ConverterType::create(&m_rhi);
123 });
124}
125
126bool TextureConverter::hwTextureConversionEnabled()
127{
128 // HW texture conversions are not stable in specific cases, dependent on the hardware and OS.
129 // We need the env var for testing with no texture conversion on the user's side.
130 static const int disableHwConversion =
131 qEnvironmentVariableIntValue("QT_DISABLE_HW_TEXTURES_CONVERSION");
132
133 return !disableHwConversion;
134}
135
136void TextureConverter::applyDecoderPreset(const AVPixelFormat format, AVCodecContext &codecContext)
137{
138 if (!hwTextureConversionEnabled())
139 return;
140
141 Q_ASSERT(codecContext.codec && Codec(codecContext.codec).isDecoder());
142
143#ifdef Q_OS_WINDOWS
144 if (format == AV_PIX_FMT_D3D11)
145 D3D11TextureConverter::SetupDecoderTextures(&codecContext);
146#elif defined Q_OS_ANDROID
147 if (format == AV_PIX_FMT_MEDIACODEC)
148 MediaCodecTextureConverter::setupDecoderSurface(&codecContext);
149#else
150 Q_UNUSED(codecContext);
151 Q_UNUSED(format);
152#endif
153}
154
155bool TextureConverter::isBackendAvailable(AVFrame &hwFrame, QRhi &rhi)
156{
157 bool result = false;
158 applyConverterTypeByPixelFormat(hwFrame, rhi, [&result](auto) {
159 result = true;
160 });
161 return result;
162}
163
164QT_END_NAMESPACE
Combined button and popup list for selecting options.