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