diff options
author | Fabian Bumberger <fbumberger@rim.com> | 2014-03-21 16:02:48 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2014-04-01 15:01:41 +0200 |
commit | 36649887e8ba8841b45522a772cf83b5c5130fca (patch) | |
tree | 123a5a79b8dcb765bfa8dd5dcca59c693ec8fea0 /src/plugins/qnx/mediaplayer | |
parent | d2b54b360ec0cedf2dfd64c72cc8f476fb93bc7c (diff) |
QNX: Remove most of the CPU overhead for video rendering
This patch uses the GL_OES_EGL_image extension to create a OpenGL Texture handle
for a libscreen pixmap. If the extension is not available it uses the "old"
technique as fallback where the image data is copied into a QImage.
This reduces the CPU load by more than 70% and allows HD videos to be played jitter-free.
Task-number: QTBUG-37752
Change-Id: I4cad22c39390e4cf9eb5be5f0bfe446544a11b9e
Reviewed-by: Bernd Weimer <bweimer@blackberry.com>
Reviewed-by: Sean Harmer <sean.harmer@kdab.com>
Diffstat (limited to 'src/plugins/qnx/mediaplayer')
-rw-r--r-- | src/plugins/qnx/mediaplayer/mmrendererplayervideorenderercontrol.cpp | 81 | ||||
-rw-r--r-- | src/plugins/qnx/mediaplayer/mmrendererplayervideorenderercontrol.h | 4 |
2 files changed, 79 insertions, 6 deletions
diff --git a/src/plugins/qnx/mediaplayer/mmrendererplayervideorenderercontrol.cpp b/src/plugins/qnx/mediaplayer/mmrendererplayervideorenderercontrol.cpp index 0abdfec49..b9fe95026 100644 --- a/src/plugins/qnx/mediaplayer/mmrendererplayervideorenderercontrol.cpp +++ b/src/plugins/qnx/mediaplayer/mmrendererplayervideorenderercontrol.cpp @@ -46,6 +46,7 @@ #include <QCoreApplication> #include <QDebug> #include <QVideoSurfaceFormat> +#include <QOpenGLContext> #include <mm/renderer.h> @@ -59,7 +60,7 @@ MmRendererPlayerVideoRendererControl::MmRendererPlayerVideoRendererControl(QObje , m_context(0) , m_videoId(-1) { - connect(m_windowGrabber, SIGNAL(frameGrabbed(QImage)), SLOT(frameGrabbed(QImage))); + connect(m_windowGrabber, SIGNAL(frameGrabbed(QImage, int)), SLOT(frameGrabbed(QImage, int))); } MmRendererPlayerVideoRendererControl::~MmRendererPlayerVideoRendererControl() @@ -75,6 +76,10 @@ QAbstractVideoSurface *MmRendererPlayerVideoRendererControl::surface() const void MmRendererPlayerVideoRendererControl::setSurface(QAbstractVideoSurface *surface) { m_surface = QPointer<QAbstractVideoSurface>(surface); + if (QOpenGLContext::currentContext()) + m_windowGrabber->checkForEglImageExtension(); + else + m_surface->setProperty("_q_GLThreadCallback", QVariant::fromValue<QObject*>(this)); } void MmRendererPlayerVideoRendererControl::attachDisplay(mmr_context_t *context) @@ -139,20 +144,86 @@ void MmRendererPlayerVideoRendererControl::resume() m_windowGrabber->resume(); } -void MmRendererPlayerVideoRendererControl::frameGrabbed(const QImage &frame) +class BBTextureBuffer : public QAbstractVideoBuffer +{ +public: + BBTextureBuffer(int handle) : + QAbstractVideoBuffer(QAbstractVideoBuffer::GLTextureHandle) + { + m_handle = handle; + } + MapMode mapMode() const { + return QAbstractVideoBuffer::ReadWrite; + } + void unmap() { + + } + uchar *map(MapMode mode, int * numBytes, int * bytesPerLine) { + Q_UNUSED(mode); + Q_UNUSED(numBytes); + Q_UNUSED(bytesPerLine); + return 0; + } + QVariant handle() const { + return m_handle; + } +private: + int m_handle; +}; + +void MmRendererPlayerVideoRendererControl::frameGrabbed(const QImage &frame, int handle) { if (m_surface) { if (!m_surface->isActive()) { - m_surface->start(QVideoSurfaceFormat(frame.size(), QVideoFrame::Format_ARGB32)); + if (m_windowGrabber->eglImageSupported()) { + if (QOpenGLContext::currentContext()) + m_windowGrabber->createEglImages(); + else + m_surface->setProperty("_q_GLThreadCallback", QVariant::fromValue<QObject*>(this)); + + m_surface->start(QVideoSurfaceFormat(frame.size(), QVideoFrame::Format_BGR32, + QAbstractVideoBuffer::GLTextureHandle)); + } else { + m_surface->start(QVideoSurfaceFormat(frame.size(), QVideoFrame::Format_ARGB32)); + } } else { if (m_surface->surfaceFormat().frameSize() != frame.size()) { + QAbstractVideoBuffer::HandleType type = m_surface->surfaceFormat().handleType(); m_surface->stop(); - m_surface->start(QVideoSurfaceFormat(frame.size(), QVideoFrame::Format_ARGB32)); + if (type != QAbstractVideoBuffer::NoHandle) { + m_surface->setProperty("_q_GLThreadCallback", QVariant::fromValue<QObject*>(this)); + m_surface->start(QVideoSurfaceFormat(frame.size(), QVideoFrame::Format_BGR32, + QAbstractVideoBuffer::GLTextureHandle)); + } else { + m_surface->start(QVideoSurfaceFormat(frame.size(), QVideoFrame::Format_ARGB32)); + } } } - m_surface->present(frame.copy()); + // Depending on the support of EGL images on the current platform we either pass a texture + // handle or a copy of the image data + if (m_surface->surfaceFormat().handleType() != QAbstractVideoBuffer::NoHandle) { + if (m_windowGrabber->eglImagesInitialized() && + m_surface->property("_q_GLThreadCallback") != 0) + m_surface->setProperty("_q_GLThreadCallback", 0); + + + BBTextureBuffer *textBuffer = new BBTextureBuffer(handle); + QVideoFrame actualFrame(textBuffer, frame.size(), QVideoFrame::Format_BGR32); + m_surface->present(actualFrame); + } else { + m_surface->present(frame.copy()); + } } } +void MmRendererPlayerVideoRendererControl::customEvent(QEvent *e) +{ + // This is running in the render thread (OpenGL enabled) + if (e->type() == QEvent::User) + m_windowGrabber->checkForEglImageExtension(); + else if (e->type() == QEvent::User + 1) + m_windowGrabber->createEglImages(); +} + QT_END_NAMESPACE diff --git a/src/plugins/qnx/mediaplayer/mmrendererplayervideorenderercontrol.h b/src/plugins/qnx/mediaplayer/mmrendererplayervideorenderercontrol.h index 4e271ad5d..5624b464e 100644 --- a/src/plugins/qnx/mediaplayer/mmrendererplayervideorenderercontrol.h +++ b/src/plugins/qnx/mediaplayer/mmrendererplayervideorenderercontrol.h @@ -67,8 +67,10 @@ public: void pause(); void resume(); + void customEvent(QEvent *) Q_DECL_OVERRIDE; + private Q_SLOTS: - void frameGrabbed(const QImage &frame); + void frameGrabbed(const QImage &frame, int); private: QPointer<QAbstractVideoSurface> m_surface; |