summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/imports/multimedia/multimedia.pro2
-rw-r--r--src/imports/multimedia/qdeclarativevideooutput_render.cpp9
-rw-r--r--src/imports/multimedia/qdeclarativevideooutput_render_p.h5
-rw-r--r--src/imports/multimedia/qsgvideonode_texture.cpp262
-rw-r--r--src/imports/multimedia/qsgvideonode_texture.h74
-rw-r--r--src/plugins/qt7/mediaplayer/qt7playerservice.mm6
-rw-r--r--src/plugins/qt7/qt7movieviewrenderer.h9
-rw-r--r--src/plugins/qt7/qt7movieviewrenderer.mm138
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);