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
qffmpeghwaccel_videotoolbox.mm
Go to the documentation of this file.
1// Copyright (C) 2021 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/qffmpeghwaccel_videotoolbox_p.h>
5
6#if !defined(Q_OS_DARWIN)
7#error "Configuration error"
8#endif
9
10#include <QtCore/qloggingcategory.h>
11
12#include <QtFFmpegMediaPluginImpl/private/qffmpegvideobuffer_p.h>
13
14#include <QtGui/qopenglcontext.h>
15#include <QtGui/rhi/qrhi.h>
16
17#include <QtMultimedia/private/qavfhelpers_p.h>
18#include <QtMultimedia/private/qvideotexturehelper_p.h>
19#include <QtMultimedia/qvideoframeformat.h>
20
21#include <CoreVideo/CVMetalTexture.h>
22#include <CoreVideo/CVMetalTextureCache.h>
23
24#ifdef Q_OS_MACOS
25#import <AppKit/AppKit.h>
26#endif
27#ifdef Q_OS_IOS
28#import <OpenGLES/EAGL.h>
29#endif
30#import <Metal/Metal.h>
31
33
34Q_STATIC_LOGGING_CATEGORY(qLcVideotoolbox, "qt.multimedia.ffmpeg.videotoolbox");
35
36namespace QFFmpeg
37{
38
39namespace {
40
41class VideoToolBoxTextureHandles : public QVideoFrameTexturesHandles
42{
43public:
44 ~VideoToolBoxTextureHandles();
45 quint64 textureHandle(QRhi &, int plane) override;
46
47 TextureConverterBackendPtr parentConverterBackend; // ensures the backend is deleted after the texture
48
49 QRhi *rhi = nullptr;
50 QCFType<CVMetalTextureRef> m_cvMetalTexture[3] = {};
51
52#if defined(Q_OS_MACOS)
53 QCFType<CVOpenGLTextureRef> m_cvOpenGLTexture;
54#elif defined(Q_OS_IOS)
55 QCFType<CVOpenGLESTextureRef> m_cvOpenGLESTexture;
56#endif
57
58 QAVFHelpers::QSharedCVPixelBuffer m_buffer;
59};
60}
61
63{
65}
66
69{
70 if (!rhi)
71 return;
72
73 if (rhi->backend() == QRhi::Metal) {
74 const auto *metal = static_cast<const QRhiMetalNativeHandles *>(rhi->nativeHandles());
75
76 // Create a Metal Core Video texture cache from the pixel buffer.
81 nil,
83 nil,
86 qCWarning(qLcVideotoolbox) << "Metal texture cache creation failed";
87 rhi = nullptr;
88 }
89
92
93 } else if (rhi->backend() == QRhi::OpenGLES2) {
94#if QT_CONFIG(opengl)
95#ifdef Q_OS_MACOS
96 const auto *gl = static_cast<const QRhiGles2NativeHandles *>(rhi->nativeHandles());
97
98 // Create an OpenGL CoreVideo texture cache from the pixel buffer.
105 nullptr,
106 reinterpret_cast<CGLContextObj>(nsGLContext.CGLContextObj),
108 nil,
110 if (cvReturn != kCVReturnSuccess) {
111 qCWarning(qLcVideotoolbox) << "OpenGL texture cache creation failed";
112 rhi = nullptr;
113 }
114
117
118#endif
119#ifdef Q_OS_IOS
120 // Create an OpenGL CoreVideo texture cache from the pixel buffer.
124 nullptr,
126 nullptr,
128 if (cvReturn != kCVReturnSuccess) {
129 qCWarning(qLcVideotoolbox) << "OpenGLES texture cache creation failed";
130 rhi = nullptr;
131 }
132
135
136#endif
137#else
138 rhi = nullptr;
139#endif // QT_CONFIG(opengl)
140 }
141}
142
144{
146}
147
149{
150 m_cvMetalTextureCache = nullptr;
151#if defined(Q_OS_MACOS)
152 m_cvOpenGLTextureCache = nullptr;
153#elif defined(Q_OS_IOS)
154 m_cvOpenGLESTextureCache = nullptr;
155#endif
156}
157
159{
160 switch (f) {
161 default:
162 case QRhiTexture::UnknownFormat:
163 return MTLPixelFormatInvalid;
164 case QRhiTexture::RGBA8:
165 return MTLPixelFormatRGBA8Unorm;
166 case QRhiTexture::BGRA8:
167 return MTLPixelFormatBGRA8Unorm;
168 case QRhiTexture::R8:
169 case QRhiTexture::RED_OR_ALPHA8:
170 return MTLPixelFormatR8Unorm;
171 case QRhiTexture::RG8:
172 return MTLPixelFormatRG8Unorm;
173 case QRhiTexture::R16:
174 return MTLPixelFormatR16Unorm;
175 case QRhiTexture::RG16:
176 return MTLPixelFormatRG16Unorm;
177
178 case QRhiTexture::RGBA16F:
179 return MTLPixelFormatRGBA16Float;
180 case QRhiTexture::RGBA32F:
181 return MTLPixelFormatRGBA32Float;
182 case QRhiTexture::R16F:
183 return MTLPixelFormatR16Float;
184 case QRhiTexture::R32F:
185 return MTLPixelFormatR32Float;
186 }
187}
188
191 QVideoFrameTexturesHandlesUPtr /*oldHandles*/)
192{
193 if (!rhi)
194 return nullptr;
195
196 bool needsConversion = false;
198 if (needsConversion) {
199 return nullptr;
200 }
201
202 auto cvPixelBufferRef = reinterpret_cast<CVPixelBufferRef>(frame->data[3]);
204
211
214
215 if (rhi->backend() == QRhi::Metal) {
216 // First check that all planes have pixel-formats that we can handle,
217 // before we create any Metal textures.
218 for (int plane = 0; plane < bufferPlanes; ++plane) {
222 return nullptr;
223 }
224
225 for (int plane = 0; plane < bufferPlanes; ++plane) {
230
231 // Tested to be valid in prior loop.
234
235 // Create a CoreVideo pixel buffer backed Metal texture image from the texture cache.
241 nil,
243 width, height,
244 plane,
246 if (ret != kCVReturnSuccess) {
247 qCWarning(qLcVideotoolbox) << "Metal texture creation failed" << ret;
248 return nullptr;
249 }
250
253
254 }
255 } else if (rhi->backend() == QRhi::OpenGLES2) {
256#if QT_CONFIG(opengl)
257#ifdef Q_OS_MACOS
260 // Create a CVPixelBuffer-backed OpenGL texture image from the texture cache.
265 nil,
267 if (cvret != kCVReturnSuccess) {
268 qCWarning(qLcVideotoolbox) << "OpenGL texture creation failed" << cvret;
269 return nullptr;
270 }
271
275
276#endif
277#ifdef Q_OS_IOS
280 // Create a CVPixelBuffer-backed OpenGL texture image from the texture cache.
285 nil,
287 GL_RGBA,
290 GL_RGBA,
292 0,
294 if (cvret != kCVReturnSuccess) {
295 qCWarning(qLcVideotoolbox) << "OpenGL ES texture creation failed" << cvret;
296 return nullptr;
297 }
298
301
302#endif
303#endif
304 }
305
306 return textureHandles;
307}
308
309VideoToolBoxTextureHandles::~VideoToolBoxTextureHandles()
310{
311}
312
313quint64 VideoToolBoxTextureHandles::textureHandle(QRhi &, int plane)
314{
315 if (rhi->backend() == QRhi::Metal)
316 return m_cvMetalTexture[plane] ? qint64(CVMetalTextureGetTexture(m_cvMetalTexture[plane])) : 0;
317#if QT_CONFIG(opengl)
318 Q_ASSERT(plane == 0);
319#ifdef Q_OS_MACOS
320 return CVOpenGLTextureGetName(m_cvOpenGLTexture);
321#endif
322#ifdef Q_OS_IOS
323 return CVOpenGLESTextureGetName(m_cvOpenGLESTexture);
324#endif
325#endif
326 return 0;
327}
328
329}
330
331QT_END_NAMESPACE
static MTLPixelFormat rhiTextureFormatToMetalFormat(QRhiTexture::Format f)
QT_BEGIN_NAMESPACE Q_STATIC_LOGGING_CATEGORY(lcSynthesizedIterableAccess, "qt.iterable.synthesized", QtWarningMsg)