5#include <QtCore/qcoreapplication.h>
10#include <QtCore/qdebug.h>
13#if defined(QT_PLATFORM_UIKIT)
14#import <QuartzCore/CADisplayLink.h>
15#import <Foundation/NSRunLoop.h>
20#if defined(QT_PLATFORM_UIKIT)
22@implementation DisplayLinkObserver
24 AVFDisplayLink *m_avfDisplayLink;
25 CADisplayLink *m_displayLink;
28- (id)initWithAVFDisplayLink:(AVFDisplayLink *)link
33 m_avfDisplayLink = link;
34 m_displayLink = [[CADisplayLink displayLinkWithTarget:self selector:@selector(displayLinkNotification:)] retain];
43 [m_displayLink release];
44 m_displayLink =
nullptr;
52 [m_displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
57 [m_displayLink removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
60- (
void)displayLinkNotification:(CADisplayLink *)sender
63 m_avfDisplayLink->displayLinkEvent(
nullptr);
68static CVReturn CVDisplayLinkCallback([[maybe_unused]] CVDisplayLinkRef displayLink,
69 [[maybe_unused]]
const CVTimeStamp *inNow,
70 const CVTimeStamp *inOutputTime,
71 [[maybe_unused]] CVOptionFlags flagsIn,
72 [[maybe_unused]] CVOptionFlags *flagsOut,
73 void *displayLinkContext)
75 AVFDisplayLink *link = (AVFDisplayLink *)displayLinkContext;
77 link->displayLinkEvent(inOutputTime);
78 return kCVReturnSuccess;
82AVFDisplayLink::AVFDisplayLink(QObject *parent)
85#if defined(QT_PLATFORM_UIKIT)
86 m_displayLink = [[DisplayLinkObserver alloc] initWithAVFDisplayLink:
this];
89 CVDisplayLinkCreateWithCGDisplay(kCGDirectMainDisplay, &m_displayLink);
92 CVDisplayLinkSetCurrentCGDisplay(m_displayLink, kCGDirectMainDisplay);
95 CVDisplayLinkSetOutputCallback(m_displayLink, &CVDisplayLinkCallback,
this);
100AVFDisplayLink::~AVFDisplayLink()
103 qDebug() << Q_FUNC_INFO;
108#if defined(QT_PLATFORM_UIKIT)
109 [m_displayLink release];
111 CVDisplayLinkRelease(m_displayLink);
113 m_displayLink =
nullptr;
117bool AVFDisplayLink::isValid()
const
119 return m_displayLink !=
nullptr;
122bool AVFDisplayLink::isActive()
const
127void AVFDisplayLink::start()
129 if (m_displayLink && !m_isActive) {
130#if defined(QT_PLATFORM_UIKIT)
131 [m_displayLink start];
133 CVDisplayLinkStart(m_displayLink);
139void AVFDisplayLink::stop()
141 if (m_displayLink && m_isActive) {
142#if defined(QT_PLATFORM_UIKIT)
143 [m_displayLink stop];
145 CVDisplayLinkStop(m_displayLink);
150 std::lock_guard guard{ m_displayLinkMutex };
151 m_frameTimeStamp = std::nullopt;
155void AVFDisplayLink::displayLinkEvent(
const CVTimeStamp *ts)
161 std::unique_lock guard{ m_displayLinkMutex };
163 bool pending = m_frameTimeStamp.has_value();
164#if defined(QT_PLATFORM_UIKIT)
166 m_frameTimeStamp = CVTimeStamp{};
168 m_frameTimeStamp = *ts;
173 qApp->postEvent(
this,
new QEvent(QEvent::User), Qt::HighEventPriority);
176bool AVFDisplayLink::event(QEvent *event)
178 switch (event->type()){
180 std::unique_lock guard{ m_displayLinkMutex };
181 if (!m_frameTimeStamp)
184 CVTimeStamp ts = *m_frameTimeStamp;
185 m_frameTimeStamp = std::nullopt;
195 return QObject::event(event);
198#include "moc_avfdisplaylink_p.cpp"