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
avfdisplaylink.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 <QtCore/qcoreapplication.h>
7
8#ifdef QT_DEBUG_AVF
9#include <QtCore/qdebug.h>
10#endif
11
12
13
14#import <Foundation/NSRunLoop.h>
15#if !defined(QT_PLATFORM_UIKIT)
16#import <AppKit/NSScreen.h>
17#endif
18
19QT_USE_NAMESPACE
20
21@interface QT_MANGLE_NAMESPACE (DisplayLinkObserver) : NSObject
22{
23 AVFDisplayLink *_Nonnull m_avfDisplayLink;
24 CADisplayLink *m_displayLink;
25}
26- (id)initWithAVFDisplayLink:(AVFDisplayLink *_Nonnull)link;
27- (void)setDisplayLink:(CADisplayLink *)displayLink;
28- (void)start;
29- (void)stop;
30- (void)displayLinkNotification:(CADisplayLink *)sender;
31@end
32
33@implementation QT_MANGLE_NAMESPACE (DisplayLinkObserver)
34
35- (id)initWithAVFDisplayLink:(AVFDisplayLink *_Nonnull)link
36{
37 self = [super init];
38 if (self)
39 m_avfDisplayLink = link;
40 return self;
41}
42
43- (void)dealloc
44{
45 [self setDisplayLink:nullptr];
46 [super dealloc];
47}
48
49- (void)setDisplayLink:(CADisplayLink *)displayLink
50{
51 if (m_displayLink == displayLink)
52 return;
53 if (m_displayLink) {
54 [m_displayLink invalidate];
55 [m_displayLink release];
56 }
57 if (displayLink)
58 m_displayLink = [displayLink retain];
59}
60
61- (void)start
62{
63 [m_displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
64}
65
66- (void)stop
67{
68 [m_displayLink removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
69}
70
71- (void)displayLinkNotification:(CADisplayLink *)sender
72{
73 Q_UNUSED(sender);
74 m_avfDisplayLink->displayLinkEvent();
75}
76
77@end
78
79#ifdef QT_NAMESPACE
80using DisplayLinkObserver = QT_MANGLE_NAMESPACE(DisplayLinkObserver);
81#endif
82
83AVFDisplayLink::AVFDisplayLink(QObject *parent)
84 : QObject(parent)
85{
86#if defined(QT_PLATFORM_UIKIT)
87 m_observer = [[DisplayLinkObserver alloc] initWithAVFDisplayLink:this];
88 CADisplayLink *dl = [CADisplayLink displayLinkWithTarget:m_observer
89 selector:@selector(displayLinkNotification:)];
90 [m_observer setDisplayLink:dl];
91#else
92 if (@available(macOS 15.0, *)) {
93 m_observer = [[DisplayLinkObserver alloc] initWithAVFDisplayLink:this];
94 CADisplayLink *_Nonnull dl =
95 [NSScreen.mainScreen displayLinkWithTarget:m_observer
96 selector:@selector(displayLinkNotification:)];
97 [m_observer setDisplayLink:dl];
98 return;
99 }
100 if (!m_observer) {
101 QT_WARNING_PUSH
102 QT_WARNING_DISABLE_DEPRECATED
103 CVDisplayLinkCreateWithCGDisplay(kCGDirectMainDisplay, &m_cvDisplayLink);
104 if (m_cvDisplayLink) {
105 CVDisplayLinkSetCurrentCGDisplay(m_cvDisplayLink, kCGDirectMainDisplay);
106 CVDisplayLinkSetOutputCallback(m_cvDisplayLink,
107 [](CVDisplayLinkRef, const CVTimeStamp *,
108 const CVTimeStamp *, CVOptionFlags, CVOptionFlags *,
109 void *displayLinkContext) -> CVReturn {
110 static_cast<AVFDisplayLink *>(displayLinkContext)->displayLinkEvent();
111 return kCVReturnSuccess;
112 },
113 this);
114 }
115 QT_WARNING_POP
116 }
117#endif
118}
119
120AVFDisplayLink::~AVFDisplayLink()
121{
122#ifdef QT_DEBUG_AVF
123 qDebug() << Q_FUNC_INFO;
124#endif
125
126 stop();
127
128 if (m_observer) {
129 [m_observer release];
130 m_observer = nil;
131 }
132
133#if !defined(QT_PLATFORM_UIKIT)
134 if (m_cvDisplayLink) {
135 QT_WARNING_PUSH
136 QT_WARNING_DISABLE_DEPRECATED
137 CVDisplayLinkRelease(m_cvDisplayLink);
138 QT_WARNING_POP
139 m_cvDisplayLink = nullptr;
140 }
141#endif
142}
143
144bool AVFDisplayLink::isValid() const
145{
146#if !defined(QT_PLATFORM_UIKIT)
147 return m_observer || m_cvDisplayLink != nullptr;
148#else
149 return m_observer;
150#endif
151}
152
153bool AVFDisplayLink::isActive() const
154{
155 return m_isActive;
156}
157
158void AVFDisplayLink::start()
159{
160 if (!m_isActive) {
161 if (m_observer)
162 [m_observer start];
163#if !defined(QT_PLATFORM_UIKIT)
164 else if (m_cvDisplayLink) {
165 QT_WARNING_PUSH
166 QT_WARNING_DISABLE_DEPRECATED
167 CVDisplayLinkStart(m_cvDisplayLink);
168 QT_WARNING_POP
169 }
170#endif
171 m_isActive = true;
172 }
173}
174
175void AVFDisplayLink::stop()
176{
177 if (m_isActive) {
178 if (m_observer)
179 [m_observer stop];
180#if !defined(QT_PLATFORM_UIKIT)
181 else if (m_cvDisplayLink) {
182 QT_WARNING_PUSH
183 QT_WARNING_DISABLE_DEPRECATED
184 CVDisplayLinkStop(m_cvDisplayLink);
185 QT_WARNING_POP
186 }
187#endif
188 m_framePending = false;
189 m_isActive = false;
190 }
191}
192
193void AVFDisplayLink::displayLinkEvent()
194{
195 if (!m_framePending.exchange(true))
196 qApp->postEvent(this, new QEvent(QEvent::User), Qt::HighEventPriority);
197}
198
199bool AVFDisplayLink::event(QEvent *event)
200{
201 switch (event->type()){
202 case QEvent::User: {
203 if (!m_framePending.exchange(false))
204 return false;
205
206 Q_EMIT tick();
207
208 return false;
209 }
210 default:
211 break;
212 }
213 return QObject::event(event);
214}
215
216#include "moc_avfdisplaylink_p.cpp"