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
29
30using namespace QFFmpeg;
31
32namespace {
33
34template <typename Converter>
35using ConverterTypeIdentity = q20::type_identity<Converter>;
36
37template <typename ConverterTypeHandler>
38void applyConverterTypeByPixelFormat(AVFrame &hwFrame, QRhi &rhi, ConverterTypeHandler &&handler)
39{
40 if (!TextureConverter::hwTextureConversionEnabled())
41 return;
42
43 switch (AVPixelFormat(hwFrame.format)) {
44#if QT_CONFIG(vaapi)
45 case AV_PIX_FMT_VAAPI:
46 handler(ConverterTypeIdentity<VAAPITextureConverter>{});
47 break;
48#endif
49#ifdef Q_OS_DARWIN
50 case AV_PIX_FMT_VIDEOTOOLBOX:
51 handler(ConverterTypeIdentity<VideoToolBoxTextureConverter>{});
52 break;
53#endif
54#ifdef Q_OS_WINDOWS
55 case AV_PIX_FMT_D3D11:
56 if (D3D11TextureConverter::isSupported(hwFrame, rhi))
57 handler(ConverterTypeIdentity<D3D11TextureConverter>{});
58 break;
59#endif
60#ifdef Q_OS_ANDROID
61 case AV_PIX_FMT_MEDIACODEC:
62 handler(ConverterTypeIdentity<MediaCodecTextureConverter>{});
63 break;
64#endif
65 default:
66 Q_UNUSED(handler)
67 Q_UNUSED(rhi)
68 break;
69 }
70}
71
72} // namespace
73
74TextureConverterBackend::~TextureConverterBackend() = default;
75
76TextureConverter::TextureConverter(QRhi &rhi) : m_rhi(rhi) { }
77
78bool TextureConverter::init(AVFrame &hwFrame)
79{
80 Q_ASSERT(hwFrame.hw_frames_ctx);
81 if (AVPixelFormat(hwFrame.format) != m_format)
82 updateBackend(hwFrame);
83 return !isNull();
84}
85
86QVideoFrameTexturesUPtr TextureConverter::createTextures(AVFrame &hwFrame,
87 QVideoFrameTexturesUPtr &oldTextures)
88{
89 if (isNull())
90 return nullptr;
91
92 Q_ASSERT(hwFrame.format == m_format);
93 return m_backend->createTextures(&hwFrame, oldTextures);
94}
95
96QVideoFrameTexturesHandlesUPtr
97TextureConverter::createTextureHandles(AVFrame &hwFrame, QVideoFrameTexturesHandlesUPtr oldHandles)
98{
99 if (isNull())
100 return nullptr;
101
102 Q_ASSERT(hwFrame.format == m_format);
103 return m_backend->createTextureHandles(&hwFrame, std::move(oldHandles));
104}
105
106void TextureConverter::updateBackend(AVFrame &hwFrame)
107{
108 m_backend = nullptr;
109 m_format = AVPixelFormat(hwFrame.format); // should be saved even if m_backend is not created
110
111 applyConverterTypeByPixelFormat(hwFrame, m_rhi, [this](auto converterTypeIdentity) {
112 using ConverterType = typename decltype(converterTypeIdentity)::type;
113 m_backend = ConverterType::create(&m_rhi);
114 });
115}
116
117bool TextureConverter::hwTextureConversionEnabled()
118{
119 // HW texture conversions are not stable in specific cases, dependent on the hardware and OS.
120 // We need the env var for testing with no texture conversion on the user's side.
121 static const int disableHwConversion =
122 qEnvironmentVariableIntValue("QT_DISABLE_HW_TEXTURES_CONVERSION");
123
124 return !disableHwConversion;
125}
126
127void TextureConverter::applyDecoderPreset(const AVPixelFormat format, AVCodecContext &codecContext)
128{
129 if (!hwTextureConversionEnabled())
130 return;
131
132 Q_ASSERT(codecContext.codec && Codec(codecContext.codec).isDecoder());
133
134#ifdef Q_OS_WINDOWS
135 if (format == AV_PIX_FMT_D3D11)
136 D3D11TextureConverter::SetupDecoderTextures(&codecContext);
137#elif defined Q_OS_ANDROID
138 if (format == AV_PIX_FMT_MEDIACODEC)
139 MediaCodecTextureConverter::setupDecoderSurface(&codecContext);
140#else
141 Q_UNUSED(codecContext);
142 Q_UNUSED(format);
143#endif
144}
145
146bool TextureConverter::isBackendAvailable(AVFrame &hwFrame, QRhi &rhi)
147{
148 bool result = false;
149 applyConverterTypeByPixelFormat(hwFrame, rhi, [&result](auto) {
150 result = true;
151 });
152 return result;
153}
154
155QT_END_NAMESPACE
Combined button and popup list for selecting options.