Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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
4#include "avfdisplaylink_p.h"
5#include <QtCore/qcoreapplication.h>
6
7#ifdef QT_DEBUG_AVF
8#include <QtCore/qdebug.h>
9#endif
10
11#if defined(Q_OS_IOS) || defined(Q_OS_TVOS)
12#import <QuartzCore/CADisplayLink.h>
13#import <Foundation/NSRunLoop.h>
14#define _m_displayLink static_cast<DisplayLinkObserver*>(m_displayLink)
15#else
16#endif
17
19
20#if defined(Q_OS_IOS) || defined(Q_OS_TVOS)
21@interface DisplayLinkObserver : NSObject
22
23- (void)start;
24- (void)stop;
25- (void)displayLinkNotification:(CADisplayLink *)sender;
26
27@end
28
29@implementation DisplayLinkObserver
30{
31 AVFDisplayLink *m_avfDisplayLink;
32 CADisplayLink *m_displayLink;
33}
34
35- (id)initWithAVFDisplayLink:(AVFDisplayLink *)link
36{
37 self = [super init];
38
39 if (self) {
40 m_avfDisplayLink = link;
41 m_displayLink = [[CADisplayLink displayLinkWithTarget:self selector:@selector(displayLinkNotification:)] retain];
42 }
43
44 return self;
45}
46
47- (void) dealloc
48{
49 if (m_displayLink) {
50 [m_displayLink release];
51 m_displayLink = nullptr;
52 }
53
54 [super dealloc];
55}
56
57- (void)start
58{
59 [m_displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
60}
61
62- (void)stop
63{
64 [m_displayLink removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
65}
66
67- (void)displayLinkNotification:(CADisplayLink *)sender
68{
69 Q_UNUSED(sender);
70 m_avfDisplayLink->displayLinkEvent(nullptr);
71}
72
73@end
74#else
75static CVReturn CVDisplayLinkCallback(CVDisplayLinkRef displayLink,
76 const CVTimeStamp *inNow,
77 const CVTimeStamp *inOutputTime,
78 CVOptionFlags flagsIn,
79 CVOptionFlags *flagsOut,
80 void *displayLinkContext)
81{
82 Q_UNUSED(displayLink);
83 Q_UNUSED(inNow);
84 Q_UNUSED(flagsIn);
85 Q_UNUSED(flagsOut);
86
87 AVFDisplayLink *link = (AVFDisplayLink *)displayLinkContext;
88
89 link->displayLinkEvent(inOutputTime);
90 return kCVReturnSuccess;
91}
92#endif
93
95 : QObject(parent)
96 , m_displayLink(nullptr)
97 , m_pendingDisplayLinkEvent(false)
98 , m_isActive(false)
99{
100#if defined(Q_OS_IOS) || defined(Q_OS_TVOS)
101 m_displayLink = [[DisplayLinkObserver alloc] initWithAVFDisplayLink:this];
102#else
103 // create display link for the main display
104 CVDisplayLinkCreateWithCGDisplay(kCGDirectMainDisplay, &m_displayLink);
105 if (m_displayLink) {
106 // set the current display of a display link.
107 CVDisplayLinkSetCurrentCGDisplay(m_displayLink, kCGDirectMainDisplay);
108
109 // set the renderer output callback function
110 CVDisplayLinkSetOutputCallback(m_displayLink, &CVDisplayLinkCallback, this);
111 }
112#endif
113}
114
116{
117#ifdef QT_DEBUG_AVF
118 qDebug() << Q_FUNC_INFO;
119#endif
120
121 if (m_displayLink) {
122 stop();
123#if defined(Q_OS_IOS) || defined(Q_OS_TVOS)
124 [_m_displayLink release];
125#else
126 CVDisplayLinkRelease(m_displayLink);
127#endif
128 m_displayLink = nullptr;
129 }
130}
131
133{
134 return m_displayLink != nullptr;
135}
136
138{
139 return m_isActive;
140}
141
143{
144 if (m_displayLink && !m_isActive) {
145#if defined(Q_OS_IOS) || defined(Q_OS_TVOS)
146 [_m_displayLink start];
147#else
148 CVDisplayLinkStart(m_displayLink);
149#endif
150 m_isActive = true;
151 }
152}
153
155{
156 if (m_displayLink && m_isActive) {
157#if defined(Q_OS_IOS) || defined(Q_OS_TVOS)
158 [_m_displayLink stop];
159#else
160 CVDisplayLinkStop(m_displayLink);
161#endif
162 m_isActive = false;
163 }
164}
165
166void AVFDisplayLink::displayLinkEvent(const CVTimeStamp *ts)
167{
168 // This function is called from a
169 // thread != gui thread. So we post the event.
170 // But we need to make sure that we don't post faster
171 // than the event loop can eat:
172 m_displayLinkMutex.lock();
173 bool pending = m_pendingDisplayLinkEvent;
174 m_pendingDisplayLinkEvent = true;
175#if defined(Q_OS_IOS) || defined(Q_OS_TVOS)
176 Q_UNUSED(ts);
177 memset(&m_frameTimeStamp, 0, sizeof(CVTimeStamp));
178#else
179 m_frameTimeStamp = *ts;
180#endif
181 m_displayLinkMutex.unlock();
182
183 if (!pending)
184 qApp->postEvent(this, new QEvent(QEvent::User), Qt::HighEventPriority);
185}
186
188{
189 switch (event->type()){
190 case QEvent::User: {
191 m_displayLinkMutex.lock();
192 m_pendingDisplayLinkEvent = false;
193 CVTimeStamp ts = m_frameTimeStamp;
194 m_displayLinkMutex.unlock();
195
196 Q_EMIT tick(ts);
197
198 return false;
199 }
200 break;
201 default:
202 break;
203 }
204 return QObject::event(event);
205}
206
207#include "moc_avfdisplaylink_p.cpp"
\inmodule QtCore
Definition qcoreevent.h:45
void unlock() noexcept
Unlocks the mutex.
Definition qmutex.h:289
void lock() noexcept
Locks the mutex.
Definition qmutex.h:286
\inmodule QtCore
Definition qobject.h:103
virtual bool event(QEvent *event)
This virtual function receives events to an object and should return true if the event e was recogniz...
Definition qobject.cpp:1389
@ HighEventPriority
QString self
Definition language.cpp:58
#define Q_FUNC_INFO
#define qApp
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 const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
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 const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage return DBusPendingCall * pending
#define qDebug
[1]
Definition qlogging.h:164
GLenum GLuint id
[7]
GLuint start
struct _cl_event * event
#define Q_EMIT
#define Q_UNUSED(x)
QObject::connect nullptr