diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/imports/multimedia/multimedia.pro | 2 | ||||
-rw-r--r-- | src/imports/multimedia/qdeclarativevideooutput_render.cpp | 9 | ||||
-rw-r--r-- | src/imports/multimedia/qdeclarativevideooutput_render_p.h | 5 | ||||
-rw-r--r-- | src/imports/multimedia/qsgvideonode_texture.cpp | 262 | ||||
-rw-r--r-- | src/imports/multimedia/qsgvideonode_texture.h | 74 | ||||
-rw-r--r-- | src/plugins/qt7/mediaplayer/qt7playerservice.mm | 6 | ||||
-rw-r--r-- | src/plugins/qt7/qt7movieviewrenderer.h | 9 | ||||
-rw-r--r-- | src/plugins/qt7/qt7movieviewrenderer.mm | 138 |
8 files changed, 493 insertions, 12 deletions
diff --git a/src/imports/multimedia/multimedia.pro b/src/imports/multimedia/multimedia.pro index c60416e57..45a0f7b6d 100644 --- a/src/imports/multimedia/multimedia.pro +++ b/src/imports/multimedia/multimedia.pro @@ -19,6 +19,7 @@ HEADERS += \ qdeclarativevideooutput_window_p.h \ qsgvideonode_i420.h \ qsgvideonode_rgb.h \ + qsgvideonode_texture.h \ qdeclarativeradio_p.h \ qdeclarativeradiodata_p.h \ qdeclarativecamera_p.h \ @@ -39,6 +40,7 @@ SOURCES += \ qdeclarativevideooutput_window.cpp \ qsgvideonode_i420.cpp \ qsgvideonode_rgb.cpp \ + qsgvideonode_texture.cpp \ qdeclarativeradio.cpp \ qdeclarativeradiodata.cpp \ qdeclarativecamera.cpp \ diff --git a/src/imports/multimedia/qdeclarativevideooutput_render.cpp b/src/imports/multimedia/qdeclarativevideooutput_render.cpp index 1f8bd993a..f59d20aa6 100644 --- a/src/imports/multimedia/qdeclarativevideooutput_render.cpp +++ b/src/imports/multimedia/qdeclarativevideooutput_render.cpp @@ -47,6 +47,8 @@ #include <private/qmediapluginloader_p.h> #include <private/qsgvideonode_p.h> +#include <QtGui/QOpenGLContext> + QT_BEGIN_NAMESPACE Q_GLOBAL_STATIC_WITH_ARGS(QMediaPluginLoader, videoNodeFactoryLoader, @@ -54,6 +56,7 @@ Q_GLOBAL_STATIC_WITH_ARGS(QMediaPluginLoader, videoNodeFactoryLoader, QDeclarativeVideoRendererBackend::QDeclarativeVideoRendererBackend(QDeclarativeVideoOutput *parent) : QDeclarativeVideoBackend(parent), + m_glContext(0), m_frameChanged(false) { m_surface = new QSGVideoItemSurface(this); @@ -69,6 +72,7 @@ QDeclarativeVideoRendererBackend::QDeclarativeVideoRendererBackend(QDeclarativeV // Append existing node factories as fallback if we have no plugins m_videoNodeFactories.append(&m_i420Factory); m_videoNodeFactories.append(&m_rgbFactory); + m_videoNodeFactories.append(&m_textureFactory); } QDeclarativeVideoRendererBackend::~QDeclarativeVideoRendererBackend() @@ -165,6 +169,11 @@ QSGNode *QDeclarativeVideoRendererBackend::updatePaintNode(QSGNode *oldNode, QMutexLocker lock(&m_frameMutex); + if (!m_glContext) { + m_glContext = QOpenGLContext::currentContext(); + m_surface->setProperty("GLContext", QVariant::fromValue<QObject*>(m_glContext)); + } + if (m_frameChanged) { if (videoNode && videoNode->pixelFormat() != m_frame.pixelFormat()) { #ifdef DEBUG_VIDEOITEM diff --git a/src/imports/multimedia/qdeclarativevideooutput_render_p.h b/src/imports/multimedia/qdeclarativevideooutput_render_p.h index e734215ea..b5421bf37 100644 --- a/src/imports/multimedia/qdeclarativevideooutput_render_p.h +++ b/src/imports/multimedia/qdeclarativevideooutput_render_p.h @@ -46,6 +46,8 @@ #include "qdeclarativevideooutput_backend_p.h" #include "qsgvideonode_i420.h" #include "qsgvideonode_rgb.h" +#include "qsgvideonode_texture.h" + #include <QtCore/qmutex.h> #include <QtMultimedia/qabstractvideosurface.h> @@ -53,6 +55,7 @@ QT_BEGIN_NAMESPACE class QSGVideoItemSurface; class QVideoRendererControl; +class QOpenGLContext; class QDeclarativeVideoRendererBackend : public QDeclarativeVideoBackend { @@ -77,10 +80,12 @@ private: QPointer<QVideoRendererControl> m_rendererControl; QList<QSGVideoNodeFactoryInterface*> m_videoNodeFactories; QSGVideoItemSurface *m_surface; + QOpenGLContext *m_glContext; QVideoFrame m_frame; bool m_frameChanged; QSGVideoNodeFactory_I420 m_i420Factory; QSGVideoNodeFactory_RGB m_rgbFactory; + QSGVideoNodeFactory_Texture m_textureFactory; QMutex m_frameMutex; QRectF m_renderedRect; // Destination pixel coordinates, clipped QRectF m_sourceTextureRect; // Source texture coordinates diff --git a/src/imports/multimedia/qsgvideonode_texture.cpp b/src/imports/multimedia/qsgvideonode_texture.cpp new file mode 100644 index 000000000..657e49200 --- /dev/null +++ b/src/imports/multimedia/qsgvideonode_texture.cpp @@ -0,0 +1,262 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "qsgvideonode_texture.h" +#include <QtQuick/qsgtexturematerial.h> +#include <QtQuick/qsgmaterial.h> +#include <QtCore/qmutex.h> +#include <QtGui/QOpenGLContext> +#include <QtGui/QOpenGLFunctions> +#include <QtGui/QOpenGLShaderProgram> + +QList<QVideoFrame::PixelFormat> QSGVideoNodeFactory_Texture::supportedPixelFormats( + QAbstractVideoBuffer::HandleType handleType) const +{ + QList<QVideoFrame::PixelFormat> pixelFormats; + + if (handleType == QAbstractVideoBuffer::GLTextureHandle) { + pixelFormats.append(QVideoFrame::Format_RGB565); + pixelFormats.append(QVideoFrame::Format_RGB32); + pixelFormats.append(QVideoFrame::Format_ARGB32); + pixelFormats.append(QVideoFrame::Format_BGR32); + pixelFormats.append(QVideoFrame::Format_BGRA32); + } + + return pixelFormats; +} + +QSGVideoNode *QSGVideoNodeFactory_Texture::createNode(const QVideoSurfaceFormat &format) +{ + if (supportedPixelFormats(format.handleType()).contains(format.pixelFormat())) + return new QSGVideoNode_Texture(format); + + return 0; +} + + +class QSGVideoMaterialShader_Texture : public QSGMaterialShader +{ +public: + QSGVideoMaterialShader_Texture(QVideoFrame::PixelFormat pixelFormat) + : QSGMaterialShader(), + m_pixelFormat(pixelFormat) + { + } + + void updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial); + + virtual char const *const *attributeNames() const { + static const char *names[] = { + "qt_VertexPosition", + "qt_VertexTexCoord", + 0 + }; + return names; + } + +protected: + + virtual const char *vertexShader() const { + const char *shader = + "uniform highp mat4 qt_Matrix; \n" + "attribute highp vec4 qt_VertexPosition; \n" + "attribute highp vec2 qt_VertexTexCoord; \n" + "varying highp vec2 qt_TexCoord; \n" + "void main() { \n" + " qt_TexCoord = qt_VertexTexCoord; \n" + " gl_Position = qt_Matrix * qt_VertexPosition; \n" + "}"; + return shader; + } + + virtual const char *fragmentShader() const { + static const char *shader = + "uniform sampler2D rgbTexture;" + "uniform lowp float opacity;" + "" + "varying highp vec2 qt_TexCoord;" + "" + "void main()" + "{" + " gl_FragColor = texture2D(rgbTexture, qt_TexCoord) * opacity;" + "}"; + + static const char *colorsSwapShader = + "uniform sampler2D rgbTexture;" + "uniform lowp float opacity;" + "" + "varying highp vec2 qt_TexCoord;" + "" + "void main()" + "{" + " gl_FragColor = vec4(texture2D(rgbTexture, qt_TexCoord).bgr, 1.0) * opacity;" + "}"; + + + switch (m_pixelFormat) { + case QVideoFrame::Format_RGB32: + case QVideoFrame::Format_ARGB32: + return colorsSwapShader; + default: + return shader; + } + } + + virtual void initialize() { + m_id_matrix = program()->uniformLocation("qt_Matrix"); + m_id_Texture = program()->uniformLocation("rgbTexture"); + m_id_opacity = program()->uniformLocation("opacity"); + } + + int m_id_matrix; + int m_id_Texture; + int m_id_opacity; + QVideoFrame::PixelFormat m_pixelFormat; +}; + + +class QSGVideoMaterial_Texture : public QSGMaterial +{ +public: + QSGVideoMaterial_Texture(const QVideoSurfaceFormat &format) : + m_format(format), + m_textureId(0), + m_opacity(1.0) + { + setFlag(Blending, false); + } + + ~QSGVideoMaterial_Texture() + { + m_frame = QVideoFrame(); + } + + virtual QSGMaterialType *type() const { + static QSGMaterialType theType; + return &theType; + } + + virtual QSGMaterialShader *createShader() const { + return new QSGVideoMaterialShader_Texture(m_format.pixelFormat()); + } + + virtual int compare(const QSGMaterial *other) const { + const QSGVideoMaterial_Texture *m = static_cast<const QSGVideoMaterial_Texture *>(other); + int diff = m_textureId - m->m_textureId; + if (diff) + return diff; + + diff = m_format.pixelFormat() - m->m_format.pixelFormat(); + if (diff) + return diff; + + return (m_opacity > m->m_opacity) ? 1 : -1; + } + + void updateBlending() { + setFlag(Blending, qFuzzyCompare(m_opacity, qreal(1.0)) ? false : true); + } + + void setVideoFrame(const QVideoFrame &frame) { + QMutexLocker lock(&m_frameMutex); + m_frame = frame; + } + + void bind() + { + QMutexLocker lock(&m_frameMutex); + if (m_frame.isValid()) { + m_textureId = m_frame.handle().toUInt(); + glBindTexture(GL_TEXTURE_2D, m_textureId); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + } else { + m_textureId = 0; + } + } + + QVideoFrame m_frame; + QMutex m_frameMutex; + QSize m_textureSize; + QVideoSurfaceFormat m_format; + GLuint m_textureId; + qreal m_opacity; +}; + + +QSGVideoNode_Texture::QSGVideoNode_Texture(const QVideoSurfaceFormat &format) : + m_format(format) +{ + m_material = new QSGVideoMaterial_Texture(format); + setMaterial(m_material); +} + +QSGVideoNode_Texture::~QSGVideoNode_Texture() +{ +} + +void QSGVideoNode_Texture::setCurrentFrame(const QVideoFrame &frame) +{ + m_material->setVideoFrame(frame); + markDirty(DirtyMaterial); +} + +void QSGVideoMaterialShader_Texture::updateState(const RenderState &state, + QSGMaterial *newMaterial, + QSGMaterial *oldMaterial) +{ + Q_UNUSED(oldMaterial); + QSGVideoMaterial_Texture *mat = static_cast<QSGVideoMaterial_Texture *>(newMaterial); + program()->setUniformValue(m_id_Texture, 0); + + mat->bind(); + + if (state.isOpacityDirty()) { + mat->m_opacity = state.opacity(); + mat->updateBlending(); + program()->setUniformValue(m_id_opacity, GLfloat(mat->m_opacity)); + } + + if (state.isMatrixDirty()) + program()->setUniformValue(m_id_matrix, state.combinedMatrix()); +} diff --git a/src/imports/multimedia/qsgvideonode_texture.h b/src/imports/multimedia/qsgvideonode_texture.h new file mode 100644 index 000000000..b2a1fc76a --- /dev/null +++ b/src/imports/multimedia/qsgvideonode_texture.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSGVIDEONODE_TEXTURE_H +#define QSGVIDEONODE_TEXTURE_H + +#include <private/qsgvideonode_p.h> +#include <QtMultimedia/qvideosurfaceformat.h> + +class QSGVideoMaterial_Texture; + +class QSGVideoNode_Texture : public QSGVideoNode +{ +public: + QSGVideoNode_Texture(const QVideoSurfaceFormat &format); + ~QSGVideoNode_Texture(); + + virtual QVideoFrame::PixelFormat pixelFormat() const { + return m_format.pixelFormat(); + } + void setCurrentFrame(const QVideoFrame &frame); + +private: + QVideoSurfaceFormat m_format; + QSGVideoMaterial_Texture *m_material; + QVideoFrame m_frame; +}; + +class QSGVideoNodeFactory_Texture : public QSGVideoNodeFactoryInterface { +public: + QList<QVideoFrame::PixelFormat> supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType) const; + QSGVideoNode *createNode(const QVideoSurfaceFormat &format); +}; + + +#endif diff --git a/src/plugins/qt7/mediaplayer/qt7playerservice.mm b/src/plugins/qt7/mediaplayer/qt7playerservice.mm index cf2a3ebec..67a7a8140 100644 --- a/src/plugins/qt7/mediaplayer/qt7playerservice.mm +++ b/src/plugins/qt7/mediaplayer/qt7playerservice.mm @@ -92,12 +92,8 @@ QMediaControl *QT7PlayerService::requestControl(const char *name) } if (qstrcmp(name, QVideoRendererControl_iid) == 0) { -#ifdef QUICKTIME_C_API_AVAILABLE - m_videoOutput = new QT7MovieRenderer(this); -#elif !defined(QT_NO_WIDGETS) +#ifndef QT_NO_WIDGETS m_videoOutput = new QT7MovieViewRenderer(this); -#else - return 0; #endif } diff --git a/src/plugins/qt7/qt7movieviewrenderer.h b/src/plugins/qt7/qt7movieviewrenderer.h index 786adb4de..8c8329664 100644 --- a/src/plugins/qt7/qt7movieviewrenderer.h +++ b/src/plugins/qt7/qt7movieviewrenderer.h @@ -51,12 +51,16 @@ #include "qt7videooutput.h" #include <qvideoframe.h> +#include <QuartzCore/CIContext.h> + QT_BEGIN_NAMESPACE class QVideoFrame; class QT7PlayerSession; class QT7PlayerService; +class QGLWidget; +class QGLFramebufferObject; class QT7MovieViewRenderer : public QT7VideoRendererControl { @@ -77,12 +81,17 @@ protected: private: void setupVideoOutput(); + QVideoFrame convertCIImageToGLTexture(const QVideoFrame &frame); void *m_movie; void *m_movieView; QSize m_nativeSize; QAbstractVideoSurface *m_surface; QVideoFrame m_currentFrame; + QGLWidget *m_glWidget; + QGLFramebufferObject *m_fbo; + CIContext *m_ciContext; + bool m_pendingRenderEvent; QMutex m_mutex; }; diff --git a/src/plugins/qt7/qt7movieviewrenderer.mm b/src/plugins/qt7/qt7movieviewrenderer.mm index 0f4bf27d1..3a6ff8a92 100644 --- a/src/plugins/qt7/qt7movieviewrenderer.mm +++ b/src/plugins/qt7/qt7movieviewrenderer.mm @@ -50,6 +50,10 @@ #include <QtCore/qdebug.h> #include <QtCore/qcoreevent.h> #include <QtCore/qcoreapplication.h> +#include <QtGui/qwindow.h> +#include <QtGui/qopenglcontext.h> +#include <QtOpenGL/qgl.h> +#include <QtOpenGL/qglframebufferobject.h> #include <QtCore/qreadwritelock.h> @@ -104,6 +108,29 @@ private: MapMode m_mode; }; +class TextureVideoBuffer : public QAbstractVideoBuffer +{ +public: + TextureVideoBuffer(GLuint textureId) + : QAbstractVideoBuffer(GLTextureHandle) + , m_textureId(textureId) + {} + + virtual ~TextureVideoBuffer() {} + + MapMode mapMode() const { return NotMapped; } + uchar *map(MapMode, int*, int*) { return 0; } + void unmap() {} + + QVariant handle() const + { + return QVariant::fromValue<unsigned int>(m_textureId); + } + +private: + GLuint m_textureId; +}; + #define VIDEO_TRANSPARENT(m) -(void)m:(NSEvent *)e{[[self superview] m:e];} @@ -146,6 +173,7 @@ private: - (void) dealloc { + delete self->m_window; [super dealloc]; } @@ -171,6 +199,7 @@ private: // before the image will be drawn. Q_UNUSED(view); QReadLocker lock(&m_rendererLock); + AutoReleasePool pool; if (m_renderer) { CGRect bounds = [img extent]; @@ -183,7 +212,8 @@ private: if (!surface || !surface->isActive()) return img; - if (surface->surfaceFormat().handleType() == QAbstractVideoBuffer::CoreImageHandle) { + if (surface->surfaceFormat().handleType() == QAbstractVideoBuffer::CoreImageHandle || + surface->surfaceFormat().handleType() == QAbstractVideoBuffer::GLTextureHandle) { //surface supports rendering of opengl based CIImage frame = QVideoFrame(new QT7CIImageVideoBuffer(img), QSize(w,h), QVideoFrame::Format_RGB32 ); } else { @@ -243,6 +273,9 @@ QT7MovieViewRenderer::QT7MovieViewRenderer(QObject *parent) m_movie(0), m_movieView(0), m_surface(0), + m_glWidget(0), + m_fbo(0), + m_ciContext(0), m_pendingRenderEvent(false) { } @@ -254,6 +287,9 @@ QT7MovieViewRenderer::~QT7MovieViewRenderer() QMutexLocker locker(&m_mutex); m_currentFrame = QVideoFrame(); [(HiddenQTMovieView*)m_movieView release]; + [m_ciContext release]; + delete m_fbo; + delete m_glWidget; } void QT7MovieViewRenderer::setupVideoOutput() @@ -288,11 +324,20 @@ void QT7MovieViewRenderer::setupVideoOutput() } if (m_surface && !m_nativeSize.isEmpty()) { - bool coreImageFrameSupported = !m_surface->supportedPixelFormats(QAbstractVideoBuffer::CoreImageHandle).isEmpty() && - !m_surface->supportedPixelFormats(QAbstractVideoBuffer::GLTextureHandle).isEmpty(); + bool coreImageFrameSupported = !m_surface->supportedPixelFormats(QAbstractVideoBuffer::CoreImageHandle).isEmpty(); + bool glTextureSupported = !m_surface->supportedPixelFormats(QAbstractVideoBuffer::GLTextureHandle).isEmpty(); + + QAbstractVideoBuffer::HandleType handleType = QAbstractVideoBuffer::NoHandle; + QVideoFrame::PixelFormat pixelFormat = QVideoFrame::Format_RGB32; - QVideoSurfaceFormat format(m_nativeSize, QVideoFrame::Format_RGB32, - coreImageFrameSupported ? QAbstractVideoBuffer::CoreImageHandle : QAbstractVideoBuffer::NoHandle); + if (glTextureSupported) { + handleType = QAbstractVideoBuffer::GLTextureHandle; + pixelFormat = QVideoFrame::Format_BGR32; + } else if (coreImageFrameSupported) { + handleType = QAbstractVideoBuffer::CoreImageHandle; + } + + QVideoSurfaceFormat format(m_nativeSize, pixelFormat, handleType); if (m_surface->isActive() && m_surface->surfaceFormat() != format) { #ifdef QT_DEBUG_QT7 @@ -311,6 +356,73 @@ void QT7MovieViewRenderer::setupVideoOutput() } } +/*! + Render the CIImage based video frame to FBO and return the video frame with resulting texture +*/ +QVideoFrame QT7MovieViewRenderer::convertCIImageToGLTexture(const QVideoFrame &frame) +{ + if (frame.handleType() != QAbstractVideoBuffer::CoreImageHandle) + return QVideoFrame(); + + if (!m_glWidget) { + QOpenGLContext *qGlContext = 0; + + if (m_surface) + qGlContext = qobject_cast<QOpenGLContext*>(m_surface->property("GLContext").value<QObject*>()); + + if (qGlContext) { + QGLContext *surfaceContext = QGLContext::fromOpenGLContext(qGlContext); + m_glWidget = new QGLWidget(); + + QGLContext *context = new QGLContext(surfaceContext->format()); + m_glWidget->setContext(context, surfaceContext); + } else { + return QVideoFrame(); + } + } + + m_glWidget->makeCurrent(); + + if (!m_fbo || m_fbo->size() != frame.size()) { + delete m_fbo; + m_fbo = new QGLFramebufferObject(frame.size()); + } + + CIImage *ciImg = (CIImage*)(frame.handle().value<void*>()); + if (ciImg) { + AutoReleasePool pool; + + QPainter p(m_fbo); + p.beginNativePainting(); + CGLContextObj cglContext = CGLGetCurrentContext(); + if (cglContext) { + if (!m_ciContext) { + NSOpenGLPixelFormat *nsglPixelFormat = [NSOpenGLView defaultPixelFormat]; + CGLPixelFormatObj cglPixelFormat = static_cast<CGLPixelFormatObj>([nsglPixelFormat CGLPixelFormatObj]); + + m_ciContext = [CIContext contextWithCGLContext:cglContext + pixelFormat:cglPixelFormat + colorSpace:nil + options:nil]; + + [m_ciContext retain]; + } + + QRect viewport = QRect(0, 0, frame.width(), frame.height()); + CGRect sRect = CGRectMake(viewport.x(), viewport.y(), viewport.width(), viewport.height()); + CGRect dRect = CGRectMake(viewport.x(), viewport.y(), viewport.width(), viewport.height()); + + [m_ciContext drawImage:ciImg inRect:dRect fromRect:sRect]; + } + p.endNativePainting(); + + QAbstractVideoBuffer *buffer = new TextureVideoBuffer(m_fbo->texture()); + return QVideoFrame(buffer, frame.size(), QVideoFrame::Format_BGR32); + } + + return QVideoFrame(); +} + void QT7MovieViewRenderer::setMovie(void *movie) { if (movie == m_movie) @@ -365,8 +477,20 @@ bool QT7MovieViewRenderer::event(QEvent *event) if (event->type() == QEvent::User) { QMutexLocker locker(&m_mutex); m_pendingRenderEvent = false; - if (m_surface->isActive()) - m_surface->present(m_currentFrame); + + if (m_surface->isActive()) { + //For GL texture frames, render in the main thread CIImage based buffers + //to FBO shared with video surface shared context + if (m_surface->surfaceFormat().handleType() == QAbstractVideoBuffer::GLTextureHandle) { + m_currentFrame = convertCIImageToGLTexture(m_currentFrame); + if (m_currentFrame.isValid()) + m_surface->present(m_currentFrame); + } else { + m_surface->present(m_currentFrame); + } + } + + m_currentFrame = QVideoFrame(); } return QT7VideoRendererControl::event(event); |