iOS video frame render implementation.
Uses CVTextureCache, iOS only for now, OS-X code could be ported but will need further work to support TEXTURE_RECTANGLE in the QVideoNode classes. When we can’t share a context, falls back to an offscreen window, FBO rendering and grabbing a QImage. Change-Id: I23b831fdcc63aeb1b67b7741d8d56779470240d3 Reviewed-by: Yoann Lopes <yoann.lopes@theqtcompany.com>
This commit is contained in:
committed by
Yoann Lopes
parent
3e94b7ce2d
commit
9444c8ec61
@@ -46,8 +46,70 @@
|
||||
#include <QtCore/qdebug.h>
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_IOS)
|
||||
#import <QuartzCore/CADisplayLink.h>
|
||||
#import <Foundation/NSRunLoop.h>
|
||||
#define _m_displayLink static_cast<DisplayLinkObserver*>(m_displayLink)
|
||||
#else
|
||||
#endif
|
||||
|
||||
QT_USE_NAMESPACE
|
||||
|
||||
#if defined(Q_OS_IOS)
|
||||
@interface DisplayLinkObserver : NSObject
|
||||
{
|
||||
AVFDisplayLink *m_avfDisplayLink;
|
||||
CADisplayLink *m_displayLink;
|
||||
}
|
||||
|
||||
- (void)start;
|
||||
- (void)stop;
|
||||
- (void)displayLinkNotification:(CADisplayLink *)sender;
|
||||
|
||||
@end
|
||||
|
||||
@implementation DisplayLinkObserver
|
||||
|
||||
- (id)initWithAVFDisplayLink:(AVFDisplayLink *)link
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
if (self) {
|
||||
m_avfDisplayLink = link;
|
||||
m_displayLink = [[CADisplayLink displayLinkWithTarget:self selector:@selector(displayLinkNotification:)] retain];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
if (m_displayLink) {
|
||||
[m_displayLink release];
|
||||
m_displayLink = NULL;
|
||||
}
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void)start
|
||||
{
|
||||
[m_displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
|
||||
}
|
||||
|
||||
- (void)stop
|
||||
{
|
||||
[m_displayLink removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
|
||||
}
|
||||
|
||||
- (void)displayLinkNotification:(CADisplayLink *)sender
|
||||
{
|
||||
Q_UNUSED(sender);
|
||||
m_avfDisplayLink->displayLinkEvent(nullptr);
|
||||
}
|
||||
|
||||
@end
|
||||
#else
|
||||
static CVReturn CVDisplayLinkCallback(CVDisplayLinkRef displayLink,
|
||||
const CVTimeStamp *inNow,
|
||||
const CVTimeStamp *inOutputTime,
|
||||
@@ -65,12 +127,17 @@ static CVReturn CVDisplayLinkCallback(CVDisplayLinkRef displayLink,
|
||||
link->displayLinkEvent(inOutputTime);
|
||||
return kCVReturnSuccess;
|
||||
}
|
||||
#endif
|
||||
|
||||
AVFDisplayLink::AVFDisplayLink(QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_displayLink(0)
|
||||
, m_pendingDisplayLinkEvent(false)
|
||||
, m_isActive(false)
|
||||
{
|
||||
#if defined(Q_OS_IOS)
|
||||
m_displayLink = [[DisplayLinkObserver alloc] initWithAVFDisplayLink:this];
|
||||
#else
|
||||
// create display link for the main display
|
||||
CVDisplayLinkCreateWithCGDisplay(kCGDirectMainDisplay, &m_displayLink);
|
||||
if (m_displayLink) {
|
||||
@@ -80,6 +147,7 @@ AVFDisplayLink::AVFDisplayLink(QObject *parent)
|
||||
// set the renderer output callback function
|
||||
CVDisplayLinkSetOutputCallback(m_displayLink, &CVDisplayLinkCallback, this);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
AVFDisplayLink::~AVFDisplayLink()
|
||||
@@ -89,8 +157,12 @@ AVFDisplayLink::~AVFDisplayLink()
|
||||
#endif
|
||||
|
||||
if (m_displayLink) {
|
||||
CVDisplayLinkStop(m_displayLink);
|
||||
stop();
|
||||
#if defined(Q_OS_IOS)
|
||||
[_m_displayLink release];
|
||||
#else
|
||||
CVDisplayLinkRelease(m_displayLink);
|
||||
#endif
|
||||
m_displayLink = NULL;
|
||||
}
|
||||
}
|
||||
@@ -108,20 +180,27 @@ bool AVFDisplayLink::isActive() const
|
||||
void AVFDisplayLink::start()
|
||||
{
|
||||
if (m_displayLink && !m_isActive) {
|
||||
CVDisplayLinkStart(m_displayLink);
|
||||
m_isActive = true;
|
||||
#if defined(Q_OS_IOS)
|
||||
[_m_displayLink start];
|
||||
#else
|
||||
CVDisplayLinkStart(m_displayLink);
|
||||
#endif
|
||||
m_isActive = true;
|
||||
}
|
||||
}
|
||||
|
||||
void AVFDisplayLink::stop()
|
||||
{
|
||||
if (m_displayLink && m_isActive) {
|
||||
#if defined(Q_OS_IOS)
|
||||
[_m_displayLink stop];
|
||||
#else
|
||||
CVDisplayLinkStop(m_displayLink);
|
||||
#endif
|
||||
m_isActive = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void AVFDisplayLink::displayLinkEvent(const CVTimeStamp *ts)
|
||||
{
|
||||
// This function is called from a
|
||||
@@ -131,7 +210,12 @@ void AVFDisplayLink::displayLinkEvent(const CVTimeStamp *ts)
|
||||
m_displayLinkMutex.lock();
|
||||
bool pending = m_pendingDisplayLinkEvent;
|
||||
m_pendingDisplayLinkEvent = true;
|
||||
#if defined(Q_OS_IOS)
|
||||
Q_UNUSED(ts);
|
||||
memset(&m_frameTimeStamp, 0, sizeof(CVTimeStamp));
|
||||
#else
|
||||
m_frameTimeStamp = *ts;
|
||||
#endif
|
||||
m_displayLinkMutex.unlock();
|
||||
|
||||
if (!pending)
|
||||
|
||||
Reference in New Issue
Block a user