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
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
5
6#include <QtGui/qopenglcontext.h>
7#include <QtGui/rhi/qrhi.h>
8
9#include <CoreVideo/CVBase.h>
10#include <CoreVideo/CVImageBuffer.h>
11#include <CoreVideo/CVPixelBuffer.h>
12
13#import <AVFoundation/AVFoundation.h>
14#import <QuartzCore/CATransaction.h>
15
16#include <Foundation/Foundation.h>
17
18#ifdef Q_OS_MACOS
19#import <AppKit/AppKit.h>
20#endif
21
22QT_USE_NAMESPACE
23
25{
26 connect(this, &QRhiVideoSink::rhiChanged, this, [this](QRhi *rhi) {
27 if (m_interface)
28 m_interface->setRhi(rhi);
29 });
30}
31
32AVFVideoSink::~AVFVideoSink() = default;
33
34void AVFVideoSink::setNativeSize(QSize size)
35{
36 if (size == nativeSize())
37 return;
38 QPlatformVideoSink::setNativeSize(size);
39 if (m_interface)
40 m_interface->nativeSizeChanged();
41}
42
44{
45 m_interface = interface;
46 if (m_interface) {
47 withRhi([&](QRhi *rhi) {
48 m_interface->setRhi(rhi);
49 });
50 }
51}
52
54{
55 if (m_layer)
56 [m_layer release];
57 if (m_outputSettings)
58 [m_outputSettings release];
59 freeTextureCaches();
60}
61
62void AVFVideoSinkInterface::freeTextureCaches()
63{
64 cvMetalTextureCache = {};
65#if defined(Q_OS_MACOS)
66 cvOpenGLTextureCache = {};
67#elif defined(Q_OS_IOS)
68 cvOpenGLESTextureCache = {};
69#endif
70}
71
73{
74 if (sink == m_sink)
75 return;
76
77 if (m_sink)
79
80 m_sink = sink;
81
82 if (m_sink) {
85 }
86}
87
89{
90 if (m_rhi == rhi)
91 return;
92 freeTextureCaches();
93 m_rhi = rhi;
94
95 if (!rhi)
96 return;
97 if (rhi->backend() == QRhi::Metal) {
98 const auto *metal = static_cast<const QRhiMetalNativeHandles *>(rhi->nativeHandles());
99
100 // Create a Metal Core Video texture cache from the pixel buffer.
101 Q_ASSERT(!cvMetalTextureCache);
102 if (CVMetalTextureCacheCreate(
103 kCFAllocatorDefault,
104 nil,
105 (id<MTLDevice>)metal->dev,
106 nil,
107 &cvMetalTextureCache) != kCVReturnSuccess) {
108 qWarning() << "Metal texture cache creation failed";
109 m_rhi = nullptr;
110 }
111 } else if (rhi->backend() == QRhi::OpenGLES2) {
112#if QT_CONFIG(opengl)
113#ifdef Q_OS_MACOS
114 const auto *gl = static_cast<const QRhiGles2NativeHandles *>(rhi->nativeHandles());
115
116 auto nsGLContext = gl->context->nativeInterface<QNativeInterface::QCocoaGLContext>()->nativeContext();
117 auto nsGLPixelFormat = nsGLContext.pixelFormat.CGLPixelFormatObj;
118
119 // Create an OpenGL CoreVideo texture cache from the pixel buffer.
120 if (CVOpenGLTextureCacheCreate(
121 kCFAllocatorDefault,
122 nullptr,
123 reinterpret_cast<CGLContextObj>(nsGLContext.CGLContextObj),
124 nsGLPixelFormat,
125 nil,
126 &cvOpenGLTextureCache)) {
127 qWarning() << "OpenGL texture cache creation failed";
128 m_rhi = nullptr;
129 }
130#endif
131#ifdef Q_OS_IOS
132 // Create an OpenGL CoreVideo texture cache from the pixel buffer.
133 if (CVOpenGLESTextureCacheCreate(
134 kCFAllocatorDefault,
135 nullptr,
136 [EAGLContext currentContext],
137 nullptr,
138 &cvOpenGLESTextureCache)) {
139 qWarning() << "OpenGL texture cache creation failed";
140 m_rhi = nullptr;
141 }
142#endif
143#else
144 m_rhi = nullptr;
145#endif // QT_CONFIG(opengl)
146 }
148}
149
150void AVFVideoSinkInterface::setLayer(CALayer *layer)
151{
152 if (layer == m_layer)
153 return;
154
155 if (m_layer)
156 [m_layer release];
157
158 m_layer = layer;
159 if (m_layer)
160 [m_layer retain];
161
163}
164
166{
167 if (m_outputSettings)
168 [m_outputSettings release];
169 m_outputSettings = nil;
170
171 // Set pixel format
172 NSDictionary *dictionary = nil;
173 if (m_rhi && m_rhi->backend() == QRhi::OpenGLES2) {
174#if QT_CONFIG(opengl)
175 dictionary = @{(NSString *)kCVPixelBufferPixelFormatTypeKey:
176 @(kCVPixelFormatType_32BGRA)
177#ifndef Q_OS_IOS // On iOS this key generates a warning about unsupported key.
178 , (NSString *)kCVPixelBufferOpenGLCompatibilityKey: @true
179#endif // Q_OS_IOS
180 };
181#endif
182 } else {
183 dictionary = @{(NSString *)kCVPixelBufferPixelFormatTypeKey:
184 @[
185 @(kCVPixelFormatType_32BGRA),
186 @(kCVPixelFormatType_32RGBA),
187 @(kCVPixelFormatType_422YpCbCr8),
188 @(kCVPixelFormatType_422YpCbCr8_yuvs),
189 @(kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange),
190 @(kCVPixelFormatType_420YpCbCr8BiPlanarFullRange),
191 @(kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange),
192 @(kCVPixelFormatType_420YpCbCr10BiPlanarFullRange),
193 @(kCVPixelFormatType_OneComponent8),
194 @(kCVPixelFormatType_OneComponent16),
195 @(kCVPixelFormatType_420YpCbCr8Planar),
196 @(kCVPixelFormatType_420YpCbCr8PlanarFullRange)
197 ]
198#ifndef Q_OS_IOS // This key is not supported and generates a warning.
199 , (NSString *)kCVPixelBufferMetalCompatibilityKey: @true
200#endif // Q_OS_IOS
201 };
202 }
203
204 m_outputSettings = [[NSDictionary alloc] initWithDictionary:dictionary];
205}
206
208{
209 if (!m_layer)
210 return;
211 [CATransaction begin];
212 [CATransaction setDisableActions: YES]; // disable animation/flicks
213 m_layer.frame = QRectF(0, 0, nativeSize().width(), nativeSize().height()).toCGRect();
214 m_layer.bounds = m_layer.frame;
215 [CATransaction commit];
216}
217
218#include "moc_avfvideosink_p.cpp"
virtual void setLayer(CALayer *layer)
virtual void setOutputSettings()
virtual void setRhi(QRhi *)
virtual void reconfigure()=0
AVFVideoSink * m_sink
void setVideoSink(AVFVideoSink *sink)
void setVideoSinkInterface(AVFVideoSinkInterface *interface)
void setNativeSize(QSize size)
QObject * parent
Definition qobject.h:74
The QVideoSink class represents a generic sink for video data.
Definition qvideosink.h:22