summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDan Cape <dcape@qnx.com>2016-04-22 14:40:23 -0400
committerYoann Lopes <yoann.lopes@qt.io>2016-04-27 10:58:11 +0000
commitc1cfbd98d2c03a2aff305c4fc190424906d7f465 (patch)
tree56528f42875ef1d93881657ef3711119c5e4989e /src
parent80deebcee3e9b14046a042cf6a66467ff078d57b (diff)
QNX: Avoid reading frames faster than they're rendered
The previous code would capture frames with a 60Hz timer into two pixmaps alternating pixmaps with each successive frame. Rendering was somewhat disconnected from this, if rendering was unable to occur at 60fps, multiple frames might be copied for each frame rendered. This meant that it might try copying a video frame into a pixmap that was currently being used by the GPU with bad effects. The primary effect being severe flicker on i.mx6 targets. The change is to ensure that we don't read the window data until we're just about to make use of it. This means we don't ever get ahead of ourselves and read the video window once for every frame rendered. The code has been significantly refactored. There is now a class that manages the pixmaps and egl images. This is created on demand and the images are created and destroyed when sizes change. Since this all now occurs in the proper thread, much of the nonsense of setting _q_GLThreadCallback to arrange a call from the render thread is avoided. Remove BlackBerry ifdefs that are no longer used. Change-Id: I4bf5efa4c39c8170e3f55499c167ee10e521e100 Reviewed-by: James McDonnell <jmcdonnell@qnx.com> Reviewed-by: Rafael Roquetto <rafael.roquetto@kdab.com>
Diffstat (limited to 'src')
-rw-r--r--src/plugins/qnx/common/windowgrabber.cpp362
-rw-r--r--src/plugins/qnx/common/windowgrabber.h61
-rw-r--r--src/plugins/qnx/mediaplayer/mmrendererplayervideorenderercontrol.cpp53
-rw-r--r--src/plugins/qnx/mediaplayer/mmrendererplayervideorenderercontrol.h2
-rw-r--r--src/qtmultimediaquicktools/qdeclarativevideooutput_render.cpp10
5 files changed, 241 insertions, 247 deletions
diff --git a/src/plugins/qnx/common/windowgrabber.cpp b/src/plugins/qnx/common/windowgrabber.cpp
index 39d87c781..3fd99c319 100644
--- a/src/plugins/qnx/common/windowgrabber.cpp
+++ b/src/plugins/qnx/common/windowgrabber.cpp
@@ -37,47 +37,50 @@
#include <QDebug>
#include <QGuiApplication>
#include <QImage>
+#include <QThread>
#include <qpa/qplatformnativeinterface.h>
#include <QOpenGLContext>
#include <QOpenGLFunctions>
-#ifdef Q_OS_BLACKBERRY
-#include <bps/event.h>
-#include <bps/screen.h>
-#endif
#include <errno.h>
QT_BEGIN_NAMESPACE
+static PFNEGLCREATEIMAGEKHRPROC s_eglCreateImageKHR;
+static PFNEGLDESTROYIMAGEKHRPROC s_eglDestroyImageKHR;
+
WindowGrabber::WindowGrabber(QObject *parent)
: QObject(parent),
- m_screenBufferWidth(-1),
- m_screenBufferHeight(-1),
+ m_screenContext(0),
m_active(false),
- m_screenContextInitialized(false),
- m_screenPixmapBuffersInitialized(false),
m_currentFrame(0),
m_eglImageSupported(false),
- m_eglImagesInitialized(false),
m_eglImageCheck(false)
{
// grab the window frame with 60 frames per second
m_timer.setInterval(1000/60);
- connect(&m_timer, SIGNAL(timeout()), SLOT(grab()));
+ connect(&m_timer, SIGNAL(timeout()), SLOT(triggerUpdate()));
QCoreApplication::eventDispatcher()->installNativeEventFilter(this);
+
+ for ( int i = 0; i < 2; ++i )
+ m_images[i] = 0;
+
+ // Use of EGL images can be disabled by setting QQNX_MM_DISABLE_EGLIMAGE_SUPPORT to something
+ // non-zero. This is probably useful only to test that this path still works since it results
+ // in a high CPU load.
+ if (!s_eglCreateImageKHR && qgetenv("QQNX_MM_DISABLE_EGLIMAGE_SUPPORT").toInt() == 0) {
+ s_eglCreateImageKHR = reinterpret_cast<PFNEGLCREATEIMAGEKHRPROC>(eglGetProcAddress("eglCreateImageKHR"));
+ s_eglDestroyImageKHR = reinterpret_cast<PFNEGLDESTROYIMAGEKHRPROC>(eglGetProcAddress("eglDestroyImageKHR"));
+ }
}
WindowGrabber::~WindowGrabber()
{
QCoreApplication::eventDispatcher()->removeNativeEventFilter(this);
- if (eglImagesInitialized()) {
- glDeleteTextures(2, imgTextures);
- eglDestroyImageKHR(eglGetDisplay(EGL_DEFAULT_DISPLAY), img[0]);
- eglDestroyImageKHR(eglGetDisplay(EGL_DEFAULT_DISPLAY), img[1]);
- }
+ cleanup();
}
void WindowGrabber::setFrameRate(int frameRate)
@@ -85,36 +88,6 @@ void WindowGrabber::setFrameRate(int frameRate)
m_timer.setInterval(1000/frameRate);
}
-void WindowGrabber::createEglImages()
-{
- // Do nothing if either egl images are not supported, the screen context is not valid
- // or the images are already created
- if (!eglImageSupported() || !m_screenContextInitialized || eglImagesInitialized())
- return;
-
- glGenTextures(2, imgTextures);
- glBindTexture(GL_TEXTURE_2D, imgTextures[0]);
- img[0] = eglCreateImageKHR(eglGetDisplay(EGL_DEFAULT_DISPLAY), EGL_NO_CONTEXT,
- EGL_NATIVE_PIXMAP_KHR,
- m_screenPixmaps[0],
- 0);
- glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, img[0]);
-
- glBindTexture(GL_TEXTURE_2D, imgTextures[1]);
- img[1] = eglCreateImageKHR(eglGetDisplay(EGL_DEFAULT_DISPLAY), EGL_NO_CONTEXT,
- EGL_NATIVE_PIXMAP_KHR,
- m_screenPixmaps[1],
- 0);
-
- glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, img[1]);
-
- if (img[0] == 0 || img[1] == 0) {
- qWarning() << "Failed to create KHR images" << img[0] << img[1] << strerror(errno) << errno;
- m_eglImageSupported = false;
- } else {
- m_eglImagesInitialized = true;
- }
-}
void WindowGrabber::setWindowId(const QByteArray &windowId)
{
@@ -126,107 +99,14 @@ void WindowGrabber::start()
if (m_active)
return;
- int result = 0;
-
- result = screen_create_context(&m_screenContext, SCREEN_APPLICATION_CONTEXT);
- if (result != 0) {
- qWarning() << "WindowGrabber: cannot create screen context:" << strerror(errno);
- return;
- } else {
- m_screenContextInitialized = true;
- }
-
- result = screen_create_pixmap(&m_screenPixmaps[0], m_screenContext);
- result = screen_create_pixmap(&m_screenPixmaps[1], m_screenContext);
- if (result != 0) {
- cleanup();
- qWarning() << "WindowGrabber: cannot create pixmaps:" << strerror(errno);
- return;
- }
-
- const int usage = SCREEN_USAGE_NATIVE;
- result = screen_set_pixmap_property_iv(m_screenPixmaps[0], SCREEN_PROPERTY_USAGE, &usage);
- result |= screen_set_pixmap_property_iv(m_screenPixmaps[1], SCREEN_PROPERTY_USAGE, &usage);
-
- const int format = SCREEN_FORMAT_RGBX8888;
- screen_set_pixmap_property_iv(m_screenPixmaps[0], SCREEN_PROPERTY_FORMAT, &format);
- screen_set_pixmap_property_iv(m_screenPixmaps[1], SCREEN_PROPERTY_FORMAT, &format);
-
- int size[2] = { 0, 0 };
-
- result = screen_get_window_property_iv(m_window, SCREEN_PROPERTY_SOURCE_SIZE, size);
- if (result != 0) {
- cleanup();
- qWarning() << "WindowGrabber: cannot get window size:" << strerror(errno);
- return;
- }
-
- m_screenBufferWidth = size[0];
- m_screenBufferHeight = size[1];
-
- updateFrameSize();
+ if (!m_screenContext)
+ screen_get_window_property_pv(m_window, SCREEN_PROPERTY_CONTEXT, reinterpret_cast<void**>(&m_screenContext));
m_timer.start();
m_active = true;
}
-void WindowGrabber::updateFrameSize()
-{
- int size[2] = { m_screenBufferWidth, m_screenBufferHeight };
-
- screen_set_pixmap_property_iv(m_screenPixmaps[0], SCREEN_PROPERTY_BUFFER_SIZE, size);
- if (eglImageSupported())
- screen_set_pixmap_property_iv(m_screenPixmaps[1], SCREEN_PROPERTY_BUFFER_SIZE, size);
-
- int result = screen_create_pixmap_buffer(m_screenPixmaps[0]);
- if (eglImageSupported())
- result |= screen_create_pixmap_buffer(m_screenPixmaps[1]);
-
- if (result != 0) {
- cleanup();
- qWarning() << "WindowGrabber: cannot create pixmap buffer:" << strerror(errno);
- return;
- } else {
- m_screenPixmapBuffersInitialized = true;
- }
-
- result = screen_get_pixmap_property_pv(m_screenPixmaps[0], SCREEN_PROPERTY_RENDER_BUFFERS,
- (void**)&m_screenPixmapBuffers[0]);
- if (eglImageSupported()) {
- result |= screen_get_pixmap_property_pv(m_screenPixmaps[1], SCREEN_PROPERTY_RENDER_BUFFERS,
- (void**)&m_screenPixmapBuffers[1]);
- }
-
- if (result != 0) {
- cleanup();
- qWarning() << "WindowGrabber: cannot get pixmap buffer:" << strerror(errno);
- return;
- }
-
- result = screen_get_buffer_property_pv(m_screenPixmapBuffers[0], SCREEN_PROPERTY_POINTER,
- (void**)&m_screenBuffers[0]);
- if (eglImageSupported()) {
- result |= screen_get_buffer_property_pv(m_screenPixmapBuffers[1], SCREEN_PROPERTY_POINTER,
- (void**)&m_screenBuffers[1]);
- }
-
- if (result != 0) {
- cleanup();
- qWarning() << "WindowGrabber: cannot get pixmap buffer pointer:" << strerror(errno);
- return;
- }
-
- result = screen_get_buffer_property_iv(m_screenPixmapBuffers[0], SCREEN_PROPERTY_STRIDE,
- &m_screenBufferStride);
-
- if (result != 0) {
- cleanup();
- qWarning() << "WindowGrabber: cannot get pixmap buffer stride:" << strerror(errno);
- return;
- }
-}
-
void WindowGrabber::stop()
{
if (!m_active)
@@ -288,20 +168,10 @@ bool WindowGrabber::handleScreenEvent(screen_event_t screen_event)
bool WindowGrabber::nativeEventFilter(const QByteArray &eventType, void *message, long*)
{
-#ifdef Q_OS_BLACKBERRY
- Q_UNUSED(eventType)
- bps_event_t * const event = static_cast<bps_event_t *>(message);
-
- if (event && bps_event_get_domain(event) == screen_get_domain()) {
- const screen_event_t screen_event = screen_event_get_event(event);
- return handleScreenEvent(screen_event);
- }
-#else
if (eventType == "screen_event_t") {
const screen_event_t event = static_cast<screen_event_t>(message);
return handleScreenEvent(event);
}
-#endif
return false;
}
@@ -342,7 +212,8 @@ void WindowGrabber::checkForEglImageExtension()
QByteArray eglExtensions = QByteArray(eglQueryString(eglGetDisplay(EGL_DEFAULT_DISPLAY),
EGL_EXTENSIONS));
m_eglImageSupported = m_context->hasExtension(QByteArrayLiteral("GL_OES_EGL_image"))
- && eglExtensions.contains(QByteArrayLiteral("EGL_KHR_image"));
+ && eglExtensions.contains(QByteArrayLiteral("EGL_KHR_image"))
+ && s_eglCreateImageKHR && s_eglDestroyImageKHR;
if (strstr(reinterpret_cast<const char*>(glGetString(GL_VENDOR)), "VMware"))
m_eglImageSupported = false;
@@ -350,21 +221,11 @@ void WindowGrabber::checkForEglImageExtension()
m_eglImageCheck = true;
}
-bool WindowGrabber::eglImagesInitialized()
-{
- return m_eglImagesInitialized;
-}
-
-void WindowGrabber::grab()
+void WindowGrabber::triggerUpdate()
{
if (!m_eglImageCheck) // We did not check for egl images yet
return;
- if (eglImageSupported())
- m_currentFrame = (m_currentFrame + 1) % 2;
- else
- m_currentFrame = 0;
-
int size[2] = { 0, 0 };
int result = screen_get_window_property_iv(m_window, SCREEN_PROPERTY_SOURCE_SIZE, size);
@@ -374,40 +235,173 @@ void WindowGrabber::grab()
return;
}
- if (m_screenBufferWidth != size[0] || m_screenBufferHeight != size[1]) {
- // The source viewport size changed, so we have to adapt our buffers
+ if (m_size.width() != size[0] || m_size.height() != size[1])
+ m_size = QSize(size[0], size[1]);
- if (m_screenPixmapBuffersInitialized) {
- screen_destroy_pixmap_buffer(m_screenPixmaps[0]);
- if (eglImageSupported())
- screen_destroy_pixmap_buffer(m_screenPixmaps[1]);
- }
+ emit updateScene(m_size);
+}
- m_screenBufferWidth = size[0];
- m_screenBufferHeight = size[1];
+bool WindowGrabber::selectBuffer()
+{
+ // If we're using egl images we need to double buffer since the gpu may still be using the last
+ // video frame. If we're not, it doesn't matter since the data is immediately copied.
+ if (eglImageSupported())
+ m_currentFrame = (m_currentFrame + 1) % 2;
- updateFrameSize();
- m_eglImagesInitialized = false;
+ if (!m_images[m_currentFrame]) {
+ m_images[m_currentFrame] = new WindowGrabberImage();
+ if (!m_images[m_currentFrame]->initialize(m_screenContext)) {
+ delete m_images[m_currentFrame];
+ m_images[m_currentFrame] = 0;
+ return false;
+ }
}
+ return true;
+}
- const int rect[] = { 0, 0, m_screenBufferWidth, m_screenBufferHeight };
- result = screen_read_window(m_window, m_screenPixmapBuffers[m_currentFrame], 1, rect, 0);
- if (result != 0)
- return;
+int WindowGrabber::getNextTextureId()
+{
+ if (!selectBuffer())
+ return 0;
+ return m_images[m_currentFrame]->getTexture(m_window, m_size);
+}
- const QImage frame((unsigned char*)m_screenBuffers[m_currentFrame], m_screenBufferWidth,
- m_screenBufferHeight, m_screenBufferStride, QImage::Format_ARGB32);
+QImage WindowGrabber::getNextImage()
+{
+ if (!selectBuffer())
+ return QImage();
- emit frameGrabbed(frame, imgTextures[m_currentFrame]);
+ return m_images[m_currentFrame]->getImage(m_window, m_size);
}
void WindowGrabber::cleanup()
{
- //We only need to destroy the context as it frees all resources associated with it
- if (m_screenContextInitialized) {
- screen_destroy_context(m_screenContext);
- m_screenContextInitialized = false;
+ for ( int i = 0; i < 2; ++i ) {
+ if (m_images[i]) {
+ m_images[i]->destroy();
+ m_images[i] = 0;
+ }
+ }
+}
+
+
+WindowGrabberImage::WindowGrabberImage()
+ : m_pixmap(0), m_pixmapBuffer(0), m_eglImage(0), m_glTexture(0), m_bufferAddress(0), m_bufferStride(0)
+{
+}
+
+WindowGrabberImage::~WindowGrabberImage()
+{
+ if (m_glTexture)
+ glDeleteTextures(1, &m_glTexture);
+ if (m_eglImage)
+ s_eglDestroyImageKHR(eglGetDisplay(EGL_DEFAULT_DISPLAY), m_eglImage);
+ if (m_pixmap)
+ screen_destroy_pixmap(m_pixmap);
+}
+
+bool
+WindowGrabberImage::initialize(screen_context_t screenContext)
+{
+ if (screen_create_pixmap(&m_pixmap, screenContext) != 0) {
+ qWarning() << "WindowGrabber: cannot create pixmap:" << strerror(errno);
+ return false;
+ }
+ const int usage = SCREEN_USAGE_WRITE | SCREEN_USAGE_READ | SCREEN_USAGE_NATIVE;
+ screen_set_pixmap_property_iv(m_pixmap, SCREEN_PROPERTY_USAGE, &usage);
+
+ const int format = SCREEN_FORMAT_RGBX8888;
+ screen_set_pixmap_property_iv(m_pixmap, SCREEN_PROPERTY_FORMAT, &format);
+
+ return true;
+}
+
+void
+WindowGrabberImage::destroy()
+{
+ // We want to delete in the thread we were created in since we need the thread that
+ // has called eglMakeCurrent on the right EGL context. This doesn't actually guarantee
+ // this but that would be hard to achieve and in practice it works.
+ if (QThread::currentThread() == thread())
+ delete this;
+ else
+ deleteLater();
+}
+
+bool
+WindowGrabberImage::resize(const QSize &newSize)
+{
+ if (m_pixmapBuffer) {
+ screen_destroy_pixmap_buffer(m_pixmap);
+ m_pixmapBuffer = 0;
+ m_bufferAddress = 0;
+ m_bufferStride = 0;
+ }
+
+ int size[2] = { newSize.width(), newSize.height() };
+
+ screen_set_pixmap_property_iv(m_pixmap, SCREEN_PROPERTY_BUFFER_SIZE, size);
+
+ if (screen_create_pixmap_buffer(m_pixmap) == 0) {
+ screen_get_pixmap_property_pv(m_pixmap, SCREEN_PROPERTY_RENDER_BUFFERS,
+ reinterpret_cast<void**>(&m_pixmapBuffer));
+ screen_get_buffer_property_pv(m_pixmapBuffer, SCREEN_PROPERTY_POINTER,
+ reinterpret_cast<void**>(&m_bufferAddress));
+ screen_get_buffer_property_iv(m_pixmapBuffer, SCREEN_PROPERTY_STRIDE, &m_bufferStride);
+ m_size = newSize;
+
+ return true;
+ } else {
+ m_size = QSize();
+ return false;
}
}
+bool
+WindowGrabberImage::grab(screen_window_t window)
+{
+ const int rect[] = { 0, 0, m_size.width(), m_size.height() };
+ return screen_read_window(window, m_pixmapBuffer, 1, rect, 0) == 0;
+}
+
+QImage
+WindowGrabberImage::getImage(screen_window_t window, const QSize &size)
+{
+ if (size != m_size) {
+ if (!resize(size))
+ return QImage();
+ }
+ if (!m_bufferAddress || !grab(window))
+ return QImage();
+
+ return QImage(m_bufferAddress, m_size.width(), m_size.height(), m_bufferStride, QImage::Format_ARGB32);
+}
+
+GLuint
+WindowGrabberImage::getTexture(screen_window_t window, const QSize &size)
+{
+ if (size != m_size) {
+ if (!m_glTexture)
+ glGenTextures(1, &m_glTexture);
+ glBindTexture(GL_TEXTURE_2D, m_glTexture);
+ if (m_eglImage) {
+ glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, 0);
+ s_eglDestroyImageKHR(eglGetDisplay(EGL_DEFAULT_DISPLAY), m_eglImage);
+ m_eglImage = 0;
+ }
+ if (!resize(size))
+ return 0;
+ m_eglImage = s_eglCreateImageKHR(eglGetDisplay(EGL_DEFAULT_DISPLAY), EGL_NO_CONTEXT,
+ EGL_NATIVE_PIXMAP_KHR, m_pixmap, 0);
+ glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_eglImage);
+ }
+
+ if (!m_pixmap || !grab(window))
+ return 0;
+
+ return m_glTexture;
+}
+
+
+
QT_END_NAMESPACE
diff --git a/src/plugins/qnx/common/windowgrabber.h b/src/plugins/qnx/common/windowgrabber.h
index bcf0ce66c..06ed6f435 100644
--- a/src/plugins/qnx/common/windowgrabber.h
+++ b/src/plugins/qnx/common/windowgrabber.h
@@ -41,12 +41,41 @@
#include <EGL/eglext.h>
#include <QAbstractNativeEventFilter>
#include <QObject>
+#include <QSize>
#include <QTimer>
#include <screen/screen.h>
QT_BEGIN_NAMESPACE
+class WindowGrabberImage : public QObject
+{
+ Q_OBJECT
+
+public:
+ WindowGrabberImage();
+ ~WindowGrabberImage();
+
+ bool initialize(screen_context_t screenContext);
+
+ void destroy();
+
+ QImage getImage(screen_window_t window, const QSize &size);
+ GLuint getTexture(screen_window_t window, const QSize &size);
+
+private:
+ bool grab(screen_window_t window);
+ bool resize(const QSize &size);
+
+ QSize m_size;
+ screen_pixmap_t m_pixmap;
+ screen_buffer_t m_pixmapBuffer;
+ EGLImageKHR m_eglImage;
+ GLuint m_glTexture;
+ unsigned char *m_bufferAddress;
+ int m_bufferStride;
+};
+
class WindowGrabber : public QObject, public QAbstractNativeEventFilter
{
Q_OBJECT
@@ -57,8 +86,6 @@ public:
void setFrameRate(int frameRate);
- void createEglImages();
-
void setWindowId(const QByteArray &windowId);
void start();
@@ -75,17 +102,19 @@ public:
bool eglImageSupported();
void checkForEglImageExtension();
- bool eglImagesInitialized();
+
+ int getNextTextureId();
+ QImage getNextImage();
signals:
- void frameGrabbed(const QImage &frame, int);
+ void updateScene(const QSize &size);
private slots:
- void grab();
+ void triggerUpdate();
private:
+ bool selectBuffer();
void cleanup();
- void updateFrameSize();
QTimer m_timer;
@@ -93,24 +122,14 @@ private:
screen_window_t m_window;
screen_context_t m_screenContext;
- screen_pixmap_t m_screenPixmaps[2];
- screen_buffer_t m_screenPixmapBuffers[2];
-
- char *m_screenBuffers[2];
- int m_screenBufferWidth;
- int m_screenBufferHeight;
- int m_screenBufferStride;
+ WindowGrabberImage *m_images[2];
+ QSize m_size;
- bool m_active : 1;
- bool m_screenContextInitialized : 1;
- bool m_screenPixmapBuffersInitialized : 1;
+ bool m_active;
int m_currentFrame;
- EGLImageKHR img[2];
- GLuint imgTextures[2];
- bool m_eglImageSupported : 1;
- bool m_eglImagesInitialized : 1;
- bool m_eglImageCheck : 1; // We must not send a grabed frame before this is true
+ bool m_eglImageSupported;
+ bool m_eglImageCheck; // We must not send a grabed frame before this is true
};
QT_END_NAMESPACE
diff --git a/src/plugins/qnx/mediaplayer/mmrendererplayervideorenderercontrol.cpp b/src/plugins/qnx/mediaplayer/mmrendererplayervideorenderercontrol.cpp
index 9e83ba2b2..5483e1423 100644
--- a/src/plugins/qnx/mediaplayer/mmrendererplayervideorenderercontrol.cpp
+++ b/src/plugins/qnx/mediaplayer/mmrendererplayervideorenderercontrol.cpp
@@ -52,7 +52,7 @@ MmRendererPlayerVideoRendererControl::MmRendererPlayerVideoRendererControl(QObje
, m_context(0)
, m_videoId(-1)
{
- connect(m_windowGrabber, SIGNAL(frameGrabbed(QImage, int)), SLOT(frameGrabbed(QImage, int)));
+ connect(m_windowGrabber, SIGNAL(updateScene(const QSize &)), SLOT(updateScene(const QSize &)));
}
MmRendererPlayerVideoRendererControl::~MmRendererPlayerVideoRendererControl()
@@ -136,13 +136,14 @@ void MmRendererPlayerVideoRendererControl::resume()
m_windowGrabber->resume();
}
-class BBTextureBuffer : public QAbstractVideoBuffer
+class QnxTextureBuffer : public QAbstractVideoBuffer
{
public:
- BBTextureBuffer(int handle) :
+ QnxTextureBuffer(WindowGrabber *windowGrabber) :
QAbstractVideoBuffer(QAbstractVideoBuffer::GLTextureHandle)
{
- m_handle = handle;
+ m_windowGrabber = windowGrabber;
+ m_handle = 0;
}
MapMode mapMode() const {
return QAbstractVideoBuffer::ReadWrite;
@@ -157,54 +158,46 @@ public:
return 0;
}
QVariant handle() const {
+ if (!m_handle) {
+ const_cast<QnxTextureBuffer*>(this)->m_handle = m_windowGrabber->getNextTextureId();
+ }
return m_handle;
}
private:
+ WindowGrabber *m_windowGrabber;
int m_handle;
};
-void MmRendererPlayerVideoRendererControl::frameGrabbed(const QImage &frame, int handle)
+void MmRendererPlayerVideoRendererControl::updateScene(const QSize &size)
{
if (m_surface) {
if (!m_surface->isActive()) {
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));
+ m_surface->start(QVideoSurfaceFormat(size, QVideoFrame::Format_BGR32,
+ QAbstractVideoBuffer::GLTextureHandle));
} else {
- m_surface->start(QVideoSurfaceFormat(frame.size(), QVideoFrame::Format_ARGB32));
+ m_surface->start(QVideoSurfaceFormat(size, QVideoFrame::Format_ARGB32));
}
} else {
- if (m_surface->surfaceFormat().frameSize() != frame.size()) {
- QAbstractVideoBuffer::HandleType type = m_surface->surfaceFormat().handleType();
+ if (m_surface->surfaceFormat().frameSize() != size) {
m_surface->stop();
- if (type != QAbstractVideoBuffer::NoHandle) {
- m_surface->setProperty("_q_GLThreadCallback", QVariant::fromValue<QObject*>(this));
- m_surface->start(QVideoSurfaceFormat(frame.size(), QVideoFrame::Format_BGR32,
- QAbstractVideoBuffer::GLTextureHandle));
+ if (m_windowGrabber->eglImageSupported()) {
+ m_surface->start(QVideoSurfaceFormat(size, QVideoFrame::Format_BGR32,
+ QAbstractVideoBuffer::GLTextureHandle));
} else {
- m_surface->start(QVideoSurfaceFormat(frame.size(), QVideoFrame::Format_ARGB32));
+ m_surface->start(QVideoSurfaceFormat(size, QVideoFrame::Format_ARGB32));
}
}
}
// 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);
+ if (m_windowGrabber->eglImageSupported()) {
+ QnxTextureBuffer *textBuffer = new QnxTextureBuffer(m_windowGrabber);
+ QVideoFrame actualFrame(textBuffer, size, QVideoFrame::Format_BGR32);
m_surface->present(actualFrame);
} else {
- m_surface->present(frame.copy());
+ m_surface->present(m_windowGrabber->getNextImage().copy());
}
}
}
@@ -214,8 +207,6 @@ 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 22833040c..c63d88f4d 100644
--- a/src/plugins/qnx/mediaplayer/mmrendererplayervideorenderercontrol.h
+++ b/src/plugins/qnx/mediaplayer/mmrendererplayervideorenderercontrol.h
@@ -62,7 +62,7 @@ public:
void customEvent(QEvent *) Q_DECL_OVERRIDE;
private Q_SLOTS:
- void frameGrabbed(const QImage &frame, int);
+ void updateScene(const QSize &size);
private:
QPointer<QAbstractVideoSurface> m_surface;
diff --git a/src/qtmultimediaquicktools/qdeclarativevideooutput_render.cpp b/src/qtmultimediaquicktools/qdeclarativevideooutput_render.cpp
index 70d48dd97..fbe8a62f9 100644
--- a/src/qtmultimediaquicktools/qdeclarativevideooutput_render.cpp
+++ b/src/qtmultimediaquicktools/qdeclarativevideooutput_render.cpp
@@ -282,16 +282,6 @@ QSGNode *QDeclarativeVideoRendererBackend::updatePaintNode(QSGNode *oldNode,
obj->event(&ev);
}
}
-#if defined (Q_OS_QNX) // On QNX we need to be called back again for creating the egl images
- else {
- // Internal mechanism to call back the surface renderer from the QtQuick render thread
- QObject *obj = m_surface->property("_q_GLThreadCallback").value<QObject*>();
- if (obj) {
- QEvent ev(static_cast<QEvent::Type>(QEvent::User + 1));
- obj->event(&ev);
- }
- }
-#endif
bool isFrameModified = false;
if (m_frameChanged) {