Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
avfvideosink.mm
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd and/or its subsidiary(-ies).
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 "avfvideosink_p.h"
5
6#include <rhi/qrhi.h>
7#include <QtGui/qopenglcontext.h>
8
9#include <AVFoundation/AVFoundation.h>
10#import <QuartzCore/CATransaction.h>
11
12#if __has_include(<AppKit/AppKit.h>)
13#include <AppKit/AppKit.h>
14#endif
15
16#if __has_include(<UIKit/UIKit.h>)
17#include <UIKit/UIKit.h>
18#endif
19
21
24{
25}
26
28{
29}
30
32{
33 if (m_rhi == rhi)
34 return;
35 m_rhi = rhi;
36 if (m_interface)
37 m_interface->setRhi(rhi);
38}
39
41{
42 if (size == nativeSize())
43 return;
45 if (m_interface)
46 m_interface->nativeSizeChanged();
47}
48
50{
51 m_interface = interface;
52 if (m_interface)
53 m_interface->setRhi(m_rhi);
54}
55
57{
58 if (m_layer)
62 freeTextureCaches();
63}
64
65void AVFVideoSinkInterface::freeTextureCaches()
66{
68 CFRelease(cvMetalTextureCache);
69 cvMetalTextureCache = nullptr;
70#if defined(Q_OS_MACOS)
71 if (cvOpenGLTextureCache)
72 CFRelease(cvOpenGLTextureCache);
73 cvOpenGLTextureCache = nullptr;
74#elif defined(Q_OS_IOS)
75 if (cvOpenGLESTextureCache)
76 CFRelease(cvOpenGLESTextureCache);
77 cvOpenGLESTextureCache = nullptr;
78#endif
79}
80
82{
83 if (sink == m_sink)
84 return;
85
86 m_sink = sink;
87 if (m_sink) {
90 }
91}
92
94{
96 if (m_rhi == rhi)
97 return;
98 freeTextureCaches();
99 m_rhi = rhi;
100
101 if (!rhi)
102 return;
103 if (rhi->backend() == QRhi::Metal) {
104 const auto *metal = static_cast<const QRhiMetalNativeHandles *>(rhi->nativeHandles());
105
106 // Create a Metal Core Video texture cache from the pixel buffer.
108 if (CVMetalTextureCacheCreate(
109 kCFAllocatorDefault,
110 nil,
111 (id<MTLDevice>)metal->dev,
112 nil,
113 &cvMetalTextureCache) != kCVReturnSuccess) {
114 qWarning() << "Metal texture cache creation failed";
115 m_rhi = nullptr;
116 }
117 } else if (rhi->backend() == QRhi::OpenGLES2) {
118#if QT_CONFIG(opengl)
119#ifdef Q_OS_MACOS
120 const auto *gl = static_cast<const QRhiGles2NativeHandles *>(rhi->nativeHandles());
121
122 auto nsGLContext = gl->context->nativeInterface<QNativeInterface::QCocoaGLContext>()->nativeContext();
123 auto nsGLPixelFormat = nsGLContext.pixelFormat.CGLPixelFormatObj;
124
125 // Create an OpenGL CoreVideo texture cache from the pixel buffer.
126 if (CVOpenGLTextureCacheCreate(
127 kCFAllocatorDefault,
128 nullptr,
129 reinterpret_cast<CGLContextObj>(nsGLContext.CGLContextObj),
130 nsGLPixelFormat,
131 nil,
132 &cvOpenGLTextureCache)) {
133 qWarning() << "OpenGL texture cache creation failed";
134 m_rhi = nullptr;
135 }
136#endif
137#ifdef Q_OS_IOS
138 // Create an OpenGL CoreVideo texture cache from the pixel buffer.
139 if (CVOpenGLESTextureCacheCreate(
140 kCFAllocatorDefault,
141 nullptr,
142 [EAGLContext currentContext],
143 nullptr,
144 &cvOpenGLESTextureCache)) {
145 qWarning() << "OpenGL texture cache creation failed";
146 m_rhi = nullptr;
147 }
148#endif
149#else
150 m_rhi = nullptr;
151#endif // QT_CONFIG(opengl)
152 }
154}
155
157{
158 if (layer == m_layer)
159 return;
160
161 if (m_layer)
163
164 m_layer = layer;
165 if (m_layer)
166 [m_layer retain];
167
168 reconfigure();
169}
170
172{
175 m_outputSettings = nil;
176
177 // Set pixel format
178 NSDictionary *dictionary = nil;
179 if (m_rhi && m_rhi->backend() == QRhi::OpenGLES2) {
180#if QT_CONFIG(opengl)
181 dictionary = @{(NSString *)kCVPixelBufferPixelFormatTypeKey:
182 @(kCVPixelFormatType_32BGRA)
183#ifndef Q_OS_IOS // On iOS this key generates a warning about unsupported key.
184 , (NSString *)kCVPixelBufferOpenGLCompatibilityKey: @true
185#endif // Q_OS_IOS
186 };
187#endif
188 } else {
189 dictionary = @{(NSString *)kCVPixelBufferPixelFormatTypeKey:
190 @[
191 @(kCVPixelFormatType_32BGRA),
192 @(kCVPixelFormatType_32RGBA),
193 @(kCVPixelFormatType_422YpCbCr8),
194 @(kCVPixelFormatType_422YpCbCr8_yuvs),
195 @(kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange),
196 @(kCVPixelFormatType_420YpCbCr8BiPlanarFullRange),
197 @(kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange),
198 @(kCVPixelFormatType_420YpCbCr10BiPlanarFullRange),
199 @(kCVPixelFormatType_OneComponent8),
200 @(kCVPixelFormatType_OneComponent16),
201 @(kCVPixelFormatType_420YpCbCr8Planar),
202 @(kCVPixelFormatType_420YpCbCr8PlanarFullRange)
203 ]
204#ifndef Q_OS_IOS // This key is not supported and generates a warning.
205 , (NSString *)kCVPixelBufferMetalCompatibilityKey: @true
206#endif // Q_OS_IOS
207 };
208 }
209
210 m_outputSettings = [[NSDictionary alloc] initWithDictionary:dictionary];
211}
212
214{
215 if (!m_layer)
216 return;
217 [CATransaction begin];
218 [CATransaction setDisableActions: YES]; // disable animation/flicks
219 m_layer.frame = QRectF(0, 0, nativeSize().width(), nativeSize().height()).toCGRect();
220 m_layer.bounds = m_layer.frame;
221 [CATransaction commit];
222}
223
224#include "moc_avfvideosink_p.cpp"
virtual void setLayer(CALayer *layer)
NSDictionary * m_outputSettings
virtual void setOutputSettings()
virtual void setRhi(QRhi *)
virtual void reconfigure()=0
AVFVideoSink * m_sink
void setVideoSink(AVFVideoSink *sink)
QSize nativeSize() const
CVMetalTextureCacheRef cvMetalTextureCache
AVFVideoSink(QVideoSink *parent=nullptr)
virtual ~AVFVideoSink()
void setRhi(QRhi *rhi) override
void setVideoSinkInterface(AVFVideoSinkInterface *interface)
void setNativeSize(QSize size)
\inmodule QtCore
Definition qmutex.h:317
Native interface to an NSOpenGLContext on \macos.
\inmodule QtCore\reentrant
Definition qrect.h:483
\variable QRhiGles2InitParams::format
\inmodule QtRhi
\inmodule QtGui
Definition qrhi.h:1767
Implementation backend() const
Definition qrhi.cpp:8289
@ Metal
Definition qrhi.h:1774
@ OpenGLES2
Definition qrhi.h:1772
const QRhiNativeHandles * nativeHandles()
Definition qrhi.cpp:9708
\inmodule QtCore
Definition qsize.h:25
The QVideoSink class represents a generic sink for video data.
Definition qvideosink.h:22
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char * interface
EGLOutputLayerEXT layer
#define qWarning
Definition qlogging.h:162
GLint GLsizei GLsizei height
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum GLuint id
[7]
GLint GLint GLint GLint GLsizei GLsizei GLsizei GLboolean commit
GLint GLsizei width
GLsizei GLenum GLboolean sink
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIterator begin(const QRegularExpressionMatchIterator &iterator)
QFuture< QSet< QString > > dictionary
sem release()
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent