/**************************************************************************** ** ** Copyright (C) 2016 Research In Motion ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "mmrendererplayervideorenderercontrol.h" #include "windowgrabber.h" #include #include #include #include #include QT_BEGIN_NAMESPACE static int winIdCounter = 0; MmRendererPlayerVideoRendererControl::MmRendererPlayerVideoRendererControl(QObject *parent) : QVideoRendererControl(parent) , m_windowGrabber(new WindowGrabber(this)) , m_context(0) , m_videoId(-1) { connect(m_windowGrabber, SIGNAL(updateScene(const QSize &)), SLOT(updateScene(const QSize &))); } MmRendererPlayerVideoRendererControl::~MmRendererPlayerVideoRendererControl() { detachDisplay(); } QAbstractVideoSurface *MmRendererPlayerVideoRendererControl::surface() const { return m_surface; } void MmRendererPlayerVideoRendererControl::setSurface(QAbstractVideoSurface *surface) { m_surface = QPointer(surface); if (QOpenGLContext::currentContext()) m_windowGrabber->checkForEglImageExtension(); else if (m_surface) m_surface->setProperty("_q_GLThreadCallback", QVariant::fromValue(this)); } void MmRendererPlayerVideoRendererControl::attachDisplay(mmr_context_t *context) { if (m_videoId != -1) { qWarning() << "MmRendererPlayerVideoRendererControl: Video output already attached!"; return; } if (!context) { qWarning() << "MmRendererPlayerVideoRendererControl: No media player context!"; return; } const QByteArray windowGroupId = m_windowGrabber->windowGroupId(); if (windowGroupId.isEmpty()) { qWarning() << "MmRendererPlayerVideoRendererControl: Unable to find window group"; return; } const QString windowName = QStringLiteral("MmRendererPlayerVideoRendererControl_%1_%2") .arg(winIdCounter++) .arg(QCoreApplication::applicationPid()); m_windowGrabber->setWindowId(windowName.toLatin1()); // Start with an invisible window, because we just want to grab the frames from it. const QString videoDeviceUrl = QStringLiteral("screen:?winid=%1&wingrp=%2&initflags=invisible&nodstviewport=1") .arg(windowName) .arg(QString::fromLatin1(windowGroupId)); m_videoId = mmr_output_attach(context, videoDeviceUrl.toLatin1(), "video"); if (m_videoId == -1) { qWarning() << "mmr_output_attach() for video failed"; return; } m_context = context; } void MmRendererPlayerVideoRendererControl::detachDisplay() { m_windowGrabber->stop(); if (m_surface) m_surface->stop(); if (m_context && m_videoId != -1) mmr_output_detach(m_context, m_videoId); m_context = 0; m_videoId = -1; } void MmRendererPlayerVideoRendererControl::pause() { m_windowGrabber->pause(); } void MmRendererPlayerVideoRendererControl::resume() { m_windowGrabber->resume(); } class QnxTextureBuffer : public QAbstractVideoBuffer { public: QnxTextureBuffer(WindowGrabber *windowGrabber) : QAbstractVideoBuffer(QAbstractVideoBuffer::GLTextureHandle) { m_windowGrabber = windowGrabber; m_handle = 0; } 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 { if (!m_handle) { const_cast(this)->m_handle = m_windowGrabber->getNextTextureId(); } return m_handle; } private: WindowGrabber *m_windowGrabber; int m_handle; }; void MmRendererPlayerVideoRendererControl::updateScene(const QSize &size) { if (m_surface) { if (!m_surface->isActive()) { if (m_windowGrabber->eglImageSupported()) { m_surface->start(QVideoSurfaceFormat(size, QVideoFrame::Format_BGR32, QAbstractVideoBuffer::GLTextureHandle)); } else { m_surface->start(QVideoSurfaceFormat(size, QVideoFrame::Format_ARGB32)); } } else { if (m_surface->surfaceFormat().frameSize() != size) { m_surface->stop(); if (m_windowGrabber->eglImageSupported()) { m_surface->start(QVideoSurfaceFormat(size, QVideoFrame::Format_BGR32, QAbstractVideoBuffer::GLTextureHandle)); } else { 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_windowGrabber->eglImageSupported()) { QnxTextureBuffer *textBuffer = new QnxTextureBuffer(m_windowGrabber); QVideoFrame actualFrame(textBuffer, size, QVideoFrame::Format_BGR32); m_surface->present(actualFrame); } else { m_surface->present(m_windowGrabber->getNextImage().copy()); } } } void MmRendererPlayerVideoRendererControl::customEvent(QEvent *e) { // This is running in the render thread (OpenGL enabled) if (e->type() == QEvent::User) m_windowGrabber->checkForEglImageExtension(); } QT_END_NAMESPACE