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
64{
65 if (!rhi)
66 return;
67
68 if (rhi->backend() == QRhi::Metal) {
69 const auto *metal = static_cast<const QRhiMetalNativeHandles *>(rhi->nativeHandles());
70
71 // Create a Metal Core Video texture cache from the pixel buffer.
76 nil,
78 nil,
81 qWarning() << "Metal texture cache creation failed";
82 rhi = nullptr;
83 }
84
87
88 } else if (rhi->backend() == QRhi::OpenGLES2) {
89#if QT_CONFIG(opengl)
90#ifdef Q_OS_MACOS
91 const auto *gl = static_cast<const QRhiGles2NativeHandles *>(rhi->nativeHandles());
92
93 // Create an OpenGL CoreVideo texture cache from the pixel buffer.
100 nullptr,
101 reinterpret_cast<CGLContextObj>(nsGLContext.CGLContextObj),
103 nil,
105 if (cvReturn != kCVReturnSuccess) {
106 qWarning() << "OpenGL texture cache creation failed";
107 rhi = nullptr;
108 }
109
112
113#endif
114#ifdef Q_OS_IOS
115 // Create an OpenGL CoreVideo texture cache from the pixel buffer.
119 nullptr,
121 nullptr,
123 if (cvReturn != kCVReturnSuccess) {
124 qWarning() << "OpenGLES texture cache creation failed";
125 rhi = nullptr;
126 }
127
130
131#endif
132#else
133 rhi = nullptr;
134#endif // QT_CONFIG(opengl)
135 }
136}
137
139{
141}
142
144{
145 m_cvMetalTextureCache = nullptr;
146#if defined(Q_OS_MACOS)
147 m_cvOpenGLTextureCache = nullptr;
148#elif defined(Q_OS_IOS)
149 m_cvOpenGLESTextureCache = nullptr;
150#endif
151}
152
154{
155 switch (f) {
156 default:
157 case QRhiTexture::UnknownFormat:
158 return MTLPixelFormatInvalid;
159 case QRhiTexture::RGBA8:
160 return MTLPixelFormatRGBA8Unorm;
161 case QRhiTexture::BGRA8:
162 return MTLPixelFormatBGRA8Unorm;
163 case QRhiTexture::R8:
164 case QRhiTexture::RED_OR_ALPHA8:
165 return MTLPixelFormatR8Unorm;
166 case QRhiTexture::RG8:
167 return MTLPixelFormatRG8Unorm;
168 case QRhiTexture::R16:
169 return MTLPixelFormatR16Unorm;
170 case QRhiTexture::RG16:
171 return MTLPixelFormatRG16Unorm;
172
173 case QRhiTexture::RGBA16F:
174 return MTLPixelFormatRGBA16Float;
175 case QRhiTexture::RGBA32F:
176 return MTLPixelFormatRGBA32Float;
177 case QRhiTexture::R16F:
178 return MTLPixelFormatR16Float;
179 case QRhiTexture::R32F:
180 return MTLPixelFormatR32Float;
181 }
182}
183
186 QVideoFrameTexturesHandlesUPtr /*oldHandles*/)
187{
188 if (!rhi)
189 return nullptr;
190
191 bool needsConversion = false;
193 if (needsConversion) {
194 // qDebug() << "XXXXXXXXXXXX pixel format needs conversion" << pixelFormat << HWAccel::format(frame);
195 return nullptr;
196 }
197
198 auto cvPixelBufferRef = reinterpret_cast<CVPixelBufferRef>(frame->data[3]);
200
207
210 // qDebug() << "XXXXX createTextureHandles" << pixelFormat << bufferPlanes << buffer;
211
212 if (rhi->backend() == QRhi::Metal) {
213 // First check that all planes have pixel-formats that we can handle,
214 // before we create any Metal textures.
215 for (int plane = 0; plane < bufferPlanes; ++plane) {
219 return nullptr;
220 }
221
222 for (int plane = 0; plane < bufferPlanes; ++plane) {
227
228 // Tested to be valid in prior loop.
231
232 // Create a CoreVideo pixel buffer backed Metal texture image from the texture cache.
238 nil,
240 width, height,
241 plane,
243 if (ret != kCVReturnSuccess) {
244 qWarning() << "texture creation failed" << ret;
245 return nullptr;
246 }
247
250
251 }
252 } else if (rhi->backend() == QRhi::OpenGLES2) {
253#if QT_CONFIG(opengl)
254#ifdef Q_OS_MACOS
257 // Create a CVPixelBuffer-backed OpenGL texture image from the texture cache.
262 nil,
264 if (cvret != kCVReturnSuccess) {
265 qCWarning(qLcVideotoolbox) << "OpenGL texture creation failed" << cvret;
266 return nullptr;
267 }
268
272
273#endif
274#ifdef Q_OS_IOS
277 // Create a CVPixelBuffer-backed OpenGL texture image from the texture cache.
282 nil,
284 GL_RGBA,
287 GL_RGBA,
289 0,
291 if (cvret != kCVReturnSuccess) {
292 qCWarning(qLcVideotoolbox) << "OpenGL ES texture creation failed" << cvret;
293 return nullptr;
294 }
295
298
299#endif
300#endif
301 }
302
303 return textureHandles;
304}
305
306VideoToolBoxTextureHandles::~VideoToolBoxTextureHandles()
307{
308}
309
310quint64 VideoToolBoxTextureHandles::textureHandle(QRhi &, int plane)
311{
312 if (rhi->backend() == QRhi::Metal)
313 return m_cvMetalTexture[plane] ? qint64(CVMetalTextureGetTexture(m_cvMetalTexture[plane])) : 0;
314#if QT_CONFIG(opengl)
315 Q_ASSERT(plane == 0);
316#ifdef Q_OS_MACOS
317 return CVOpenGLTextureGetName(m_cvOpenGLTexture);
318#endif
319#ifdef Q_OS_IOS
320 return CVOpenGLESTextureGetName(m_cvOpenGLESTexture);
321#endif
322#endif
323}
324
325}
326
327QT_END_NAMESPACE
static MTLPixelFormat rhiTextureFormatToMetalFormat(QRhiTexture::Format f)
std::conditional_t< QT_FFMPEG_AVIO_WRITE_CONST, const uint8_t *, uint8_t * > AvioWriteBufferType
QT_BEGIN_NAMESPACE Q_STATIC_LOGGING_CATEGORY(lcSynthesizedIterableAccess, "qt.iterable.synthesized", QtWarningMsg)