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#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
26
27AVFVideoSink::~AVFVideoSink()
28{
29}
30
31void AVFVideoSink::setRhi(QRhi *rhi)
32{
33 if (m_rhi == rhi)
34 return;
35 m_rhi = rhi;
36 if (m_interface)
37 m_interface->setRhi(rhi);
38}
39
40void AVFVideoSink::setNativeSize(QSize size)
41{
42 if (size == nativeSize())
43 return;
44 QPlatformVideoSink::setNativeSize(size);
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)
59 [m_layer release];
60 if (m_outputSettings)
61 [m_outputSettings release];
62 freeTextureCaches();
63}
64
65void AVFVideoSinkInterface::freeTextureCaches()
66{
67 if (cvMetalTextureCache)
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 if (m_sink)
88
89 m_sink = sink;
90
91 if (m_sink) {
94 }
95}
96
97void AVFVideoSinkInterface::setRhi(QRhi *rhi)
98{
99 if (m_rhi == rhi)
100 return;
101 freeTextureCaches();
102 m_rhi = rhi;
103
104 if (!rhi)
105 return;
106 if (rhi->backend() == QRhi::Metal) {
107 const auto *metal = static_cast<const QRhiMetalNativeHandles *>(rhi->nativeHandles());
108
109 // Create a Metal Core Video texture cache from the pixel buffer.
110 Q_ASSERT(!cvMetalTextureCache);
111 if (CVMetalTextureCacheCreate(
112 kCFAllocatorDefault,
113 nil,
114 (id<MTLDevice>)metal->dev,
115 nil,
116 &cvMetalTextureCache) != kCVReturnSuccess) {
117 qWarning() << "Metal texture cache creation failed";
118 m_rhi = nullptr;
119 }
120 } else if (rhi->backend() == QRhi::OpenGLES2) {
121#if QT_CONFIG(opengl)
122#ifdef Q_OS_MACOS
123 const auto *gl = static_cast<const QRhiGles2NativeHandles *>(rhi->nativeHandles());
124
125 auto nsGLContext = gl->context->nativeInterface<QNativeInterface::QCocoaGLContext>()->nativeContext();
126 auto nsGLPixelFormat = nsGLContext.pixelFormat.CGLPixelFormatObj;
127
128 // Create an OpenGL CoreVideo texture cache from the pixel buffer.
129 if (CVOpenGLTextureCacheCreate(
130 kCFAllocatorDefault,
131 nullptr,
132 reinterpret_cast<CGLContextObj>(nsGLContext.CGLContextObj),
133 nsGLPixelFormat,
134 nil,
135 &cvOpenGLTextureCache)) {
136 qWarning() << "OpenGL texture cache creation failed";
137 m_rhi = nullptr;
138 }
139#endif
140#ifdef Q_OS_IOS
141 // Create an OpenGL CoreVideo texture cache from the pixel buffer.
142 if (CVOpenGLESTextureCacheCreate(
143 kCFAllocatorDefault,
144 nullptr,
145 [EAGLContext currentContext],
146 nullptr,
147 &cvOpenGLESTextureCache)) {
148 qWarning() << "OpenGL texture cache creation failed";
149 m_rhi = nullptr;
150 }
151#endif
152#else
153 m_rhi = nullptr;
154#endif // QT_CONFIG(opengl)
155 }
157}
158
159void AVFVideoSinkInterface::setLayer(CALayer *layer)
160{
161 if (layer == m_layer)
162 return;
163
164 if (m_layer)
165 [m_layer release];
166
167 m_layer = layer;
168 if (m_layer)
169 [m_layer retain];
170
171 reconfigure();
172}
173
175{
176 if (m_outputSettings)
177 [m_outputSettings release];
178 m_outputSettings = nil;
179
180 // Set pixel format
181 NSDictionary *dictionary = nil;
182 if (m_rhi && m_rhi->backend() == QRhi::OpenGLES2) {
183#if QT_CONFIG(opengl)
184 dictionary = @{(NSString *)kCVPixelBufferPixelFormatTypeKey:
185 @(kCVPixelFormatType_32BGRA)
186#ifndef Q_OS_IOS // On iOS this key generates a warning about unsupported key.
187 , (NSString *)kCVPixelBufferOpenGLCompatibilityKey: @true
188#endif // Q_OS_IOS
189 };
190#endif
191 } else {
192 dictionary = @{(NSString *)kCVPixelBufferPixelFormatTypeKey:
193 @[
194 @(kCVPixelFormatType_32BGRA),
195 @(kCVPixelFormatType_32RGBA),
196 @(kCVPixelFormatType_422YpCbCr8),
197 @(kCVPixelFormatType_422YpCbCr8_yuvs),
198 @(kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange),
199 @(kCVPixelFormatType_420YpCbCr8BiPlanarFullRange),
200 @(kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange),
201 @(kCVPixelFormatType_420YpCbCr10BiPlanarFullRange),
202 @(kCVPixelFormatType_OneComponent8),
203 @(kCVPixelFormatType_OneComponent16),
204 @(kCVPixelFormatType_420YpCbCr8Planar),
205 @(kCVPixelFormatType_420YpCbCr8PlanarFullRange)
206 ]
207#ifndef Q_OS_IOS // This key is not supported and generates a warning.
208 , (NSString *)kCVPixelBufferMetalCompatibilityKey: @true
209#endif // Q_OS_IOS
210 };
211 }
212
213 m_outputSettings = [[NSDictionary alloc] initWithDictionary:dictionary];
214}
215
217{
218 if (!m_layer)
219 return;
220 [CATransaction begin];
221 [CATransaction setDisableActions: YES]; // disable animation/flicks
222 m_layer.frame = QRectF(0, 0, nativeSize().width(), nativeSize().height()).toCGRect();
223 m_layer.bounds = m_layer.frame;
224 [CATransaction commit];
225}
226
227#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
#define __has_include(x)