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

Provided by KDAB

Privacy Policy
Start learning QML with our Intro Training
Find out more

source code of qtmultimedia/src/plugins/multimedia/ffmpeg/qffmpegtextureconverter.cpp