Some cleanup in the GStreamer plugin.
Removed QGstreamerVideoOverlay and related classes. It was used as 'Window' control but performs worse than QGstreamerVideoWindow which does basically the same thing using GStreamer ready-made components instead. Removed X11 dependencies and related configuration tests. It was only needed for QGstreamerVideoOverlay. Change-Id: I2ad2636ccf0060e56cd64f3d9e5b3c24dc75f5a3 Reviewed-by: Andy Nichols <andy.nichols@digia.com>
This commit is contained in:
committed by
The Qt Project
parent
ac029c65f2
commit
c3ca3a760e
@@ -49,6 +49,7 @@ PRIVATE_HEADERS += \
|
||||
qgstcodecsinfo_p.h \
|
||||
qgstreamervideoprobecontrol_p.h \
|
||||
qgstreameraudioprobecontrol_p.h \
|
||||
qgstreamervideowindow_p.h
|
||||
|
||||
SOURCES += \
|
||||
qgstbufferpoolinterface.cpp \
|
||||
@@ -65,33 +66,16 @@ SOURCES += \
|
||||
gstvideoconnector.c \
|
||||
qgstreamervideoprobecontrol.cpp \
|
||||
qgstreameraudioprobecontrol.cpp \
|
||||
qgstreamervideowindow.cpp
|
||||
|
||||
config_xvideo {
|
||||
DEFINES += HAVE_XVIDEO
|
||||
|
||||
LIBS += -lXv -lX11 -lXext
|
||||
qtHaveModule(widgets) {
|
||||
QT += multimediawidgets
|
||||
|
||||
PRIVATE_HEADERS += \
|
||||
qgstxvimagebuffer_p.h \
|
||||
qgstreamervideowidget_p.h
|
||||
|
||||
SOURCES += \
|
||||
qgstxvimagebuffer.cpp \
|
||||
|
||||
qtHaveModule(widgets) {
|
||||
QT += multimediawidgets
|
||||
|
||||
PRIVATE_HEADERS += \
|
||||
qgstreamervideooverlay_p.h \
|
||||
qgstreamervideowindow_p.h \
|
||||
qgstreamervideowidget_p.h \
|
||||
qx11videosurface_p.h \
|
||||
|
||||
SOURCES += \
|
||||
qgstreamervideooverlay.cpp \
|
||||
qgstreamervideowindow.cpp \
|
||||
qgstreamervideowidget.cpp \
|
||||
qx11videosurface.cpp \
|
||||
}
|
||||
qgstreamervideowidget.cpp
|
||||
}
|
||||
|
||||
maemo6 {
|
||||
|
||||
@@ -1,228 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** 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 Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/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 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, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia 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.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qgstreamervideooverlay_p.h"
|
||||
#include <private/qvideosurfacegstsink_p.h>
|
||||
|
||||
#include <qvideosurfaceformat.h>
|
||||
|
||||
#include <qx11videosurface_p.h>
|
||||
|
||||
QGstreamerVideoOverlay::QGstreamerVideoOverlay(QObject *parent)
|
||||
: QVideoWindowControl(parent)
|
||||
, m_surface(new QX11VideoSurface)
|
||||
, m_videoSink(reinterpret_cast<GstElement*>(QVideoSurfaceGstSink::createSink(m_surface)))
|
||||
, m_aspectRatioMode(Qt::KeepAspectRatio)
|
||||
, m_fullScreen(false)
|
||||
{
|
||||
if (m_videoSink) {
|
||||
gst_object_ref(GST_OBJECT(m_videoSink)); //Take ownership
|
||||
gst_object_sink(GST_OBJECT(m_videoSink));
|
||||
}
|
||||
|
||||
connect(m_surface, SIGNAL(surfaceFormatChanged(QVideoSurfaceFormat)),
|
||||
this, SLOT(surfaceFormatChanged()));
|
||||
}
|
||||
|
||||
QGstreamerVideoOverlay::~QGstreamerVideoOverlay()
|
||||
{
|
||||
if (m_videoSink)
|
||||
gst_object_unref(GST_OBJECT(m_videoSink));
|
||||
|
||||
delete m_surface;
|
||||
}
|
||||
|
||||
WId QGstreamerVideoOverlay::winId() const
|
||||
{
|
||||
return m_surface->winId();
|
||||
}
|
||||
|
||||
void QGstreamerVideoOverlay::setWinId(WId id)
|
||||
{
|
||||
bool wasReady = isReady();
|
||||
m_surface->setWinId(id);
|
||||
|
||||
if (isReady() != wasReady)
|
||||
emit readyChanged(!wasReady);
|
||||
}
|
||||
|
||||
QRect QGstreamerVideoOverlay::displayRect() const
|
||||
{
|
||||
return m_displayRect;
|
||||
}
|
||||
|
||||
void QGstreamerVideoOverlay::setDisplayRect(const QRect &rect)
|
||||
{
|
||||
m_displayRect = rect;
|
||||
|
||||
setScaledDisplayRect();
|
||||
}
|
||||
|
||||
Qt::AspectRatioMode QGstreamerVideoOverlay::aspectRatioMode() const
|
||||
{
|
||||
return m_aspectRatioMode;
|
||||
}
|
||||
|
||||
void QGstreamerVideoOverlay::setAspectRatioMode(Qt::AspectRatioMode mode)
|
||||
{
|
||||
m_aspectRatioMode = mode;
|
||||
|
||||
setScaledDisplayRect();
|
||||
}
|
||||
|
||||
void QGstreamerVideoOverlay::repaint()
|
||||
{
|
||||
}
|
||||
|
||||
int QGstreamerVideoOverlay::brightness() const
|
||||
{
|
||||
return m_surface->brightness();
|
||||
}
|
||||
|
||||
void QGstreamerVideoOverlay::setBrightness(int brightness)
|
||||
{
|
||||
m_surface->setBrightness(brightness);
|
||||
|
||||
emit brightnessChanged(m_surface->brightness());
|
||||
}
|
||||
|
||||
int QGstreamerVideoOverlay::contrast() const
|
||||
{
|
||||
return m_surface->contrast();
|
||||
}
|
||||
|
||||
void QGstreamerVideoOverlay::setContrast(int contrast)
|
||||
{
|
||||
m_surface->setContrast(contrast);
|
||||
|
||||
emit contrastChanged(m_surface->contrast());
|
||||
}
|
||||
|
||||
int QGstreamerVideoOverlay::hue() const
|
||||
{
|
||||
return m_surface->hue();
|
||||
}
|
||||
|
||||
void QGstreamerVideoOverlay::setHue(int hue)
|
||||
{
|
||||
m_surface->setHue(hue);
|
||||
|
||||
emit hueChanged(m_surface->hue());
|
||||
}
|
||||
|
||||
int QGstreamerVideoOverlay::saturation() const
|
||||
{
|
||||
return m_surface->saturation();
|
||||
}
|
||||
|
||||
void QGstreamerVideoOverlay::setSaturation(int saturation)
|
||||
{
|
||||
m_surface->setSaturation(saturation);
|
||||
|
||||
emit saturationChanged(m_surface->saturation());
|
||||
}
|
||||
|
||||
bool QGstreamerVideoOverlay::isFullScreen() const
|
||||
{
|
||||
return m_fullScreen;
|
||||
}
|
||||
|
||||
void QGstreamerVideoOverlay::setFullScreen(bool fullScreen)
|
||||
{
|
||||
emit fullScreenChanged(m_fullScreen = fullScreen);
|
||||
}
|
||||
|
||||
QSize QGstreamerVideoOverlay::nativeSize() const
|
||||
{
|
||||
return m_surface->surfaceFormat().sizeHint();
|
||||
}
|
||||
|
||||
QAbstractVideoSurface *QGstreamerVideoOverlay::surface() const
|
||||
{
|
||||
return m_surface;
|
||||
}
|
||||
|
||||
GstElement *QGstreamerVideoOverlay::videoSink()
|
||||
{
|
||||
return m_videoSink;
|
||||
}
|
||||
|
||||
void QGstreamerVideoOverlay::surfaceFormatChanged()
|
||||
{
|
||||
setScaledDisplayRect();
|
||||
|
||||
emit nativeSizeChanged();
|
||||
}
|
||||
|
||||
void QGstreamerVideoOverlay::setScaledDisplayRect()
|
||||
{
|
||||
QRect formatViewport = m_surface->surfaceFormat().viewport();
|
||||
|
||||
switch (m_aspectRatioMode) {
|
||||
case Qt::KeepAspectRatio:
|
||||
{
|
||||
QSize size = m_surface->surfaceFormat().sizeHint();
|
||||
size.scale(m_displayRect.size(), Qt::KeepAspectRatio);
|
||||
|
||||
QRect rect(QPoint(0, 0), size);
|
||||
rect.moveCenter(m_displayRect.center());
|
||||
|
||||
m_surface->setDisplayRect(rect);
|
||||
m_surface->setViewport(formatViewport);
|
||||
}
|
||||
break;
|
||||
case Qt::IgnoreAspectRatio:
|
||||
m_surface->setDisplayRect(m_displayRect);
|
||||
m_surface->setViewport(formatViewport);
|
||||
break;
|
||||
case Qt::KeepAspectRatioByExpanding:
|
||||
{
|
||||
QSize size = m_displayRect.size();
|
||||
size.scale(m_surface->surfaceFormat().sizeHint(), Qt::KeepAspectRatio);
|
||||
|
||||
QRect viewport(QPoint(0, 0), size);
|
||||
viewport.moveCenter(formatViewport.center());
|
||||
m_surface->setDisplayRect(m_displayRect);
|
||||
m_surface->setViewport(viewport);
|
||||
}
|
||||
break;
|
||||
};
|
||||
}
|
||||
@@ -47,9 +47,6 @@
|
||||
#include <QtWidgets/qapplication.h>
|
||||
#include <QtGui/qpainter.h>
|
||||
|
||||
#ifdef Q_WS_X11
|
||||
# include <X11/Xlib.h>
|
||||
#endif
|
||||
#include <gst/gst.h>
|
||||
#include <gst/interfaces/xoverlay.h>
|
||||
#include <gst/interfaces/propertyprobe.h>
|
||||
|
||||
@@ -48,14 +48,6 @@
|
||||
#include <gst/interfaces/xoverlay.h>
|
||||
#include <gst/interfaces/propertyprobe.h>
|
||||
|
||||
/*
|
||||
QGstreamerVideoWindow is similar to QGstreamerVideoOverlay,
|
||||
but uses xvimagesink like gstreamer element instead of QX11VideoSurface.
|
||||
|
||||
This allows to use the accelerated elements if available on the target platform,
|
||||
but requires at least 0.10.29 gstreamer version
|
||||
with gst_x_overlay_set_render_rectangle to set display rect.
|
||||
*/
|
||||
|
||||
QGstreamerVideoWindow::QGstreamerVideoWindow(QObject *parent, const char *elementName)
|
||||
: QVideoWindowControl(parent)
|
||||
@@ -95,8 +87,6 @@ void QGstreamerVideoWindow::setWinId(WId id)
|
||||
if (m_windowId == id)
|
||||
return;
|
||||
|
||||
qDebug() << Q_FUNC_INFO << id;
|
||||
|
||||
WId oldId = m_windowId;
|
||||
|
||||
m_windowId = id;
|
||||
|
||||
@@ -1,329 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** 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 Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/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 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, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia 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.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include <QtCore/qdebug.h>
|
||||
#include <QtCore/qthread.h>
|
||||
#include <QtCore/qvariant.h>
|
||||
#include <QtGui/qguiapplication.h>
|
||||
#include <QtGui/qwindow.h>
|
||||
#include <qpa/qplatformnativeinterface.h>
|
||||
|
||||
#include "qgstxvimagebuffer_p.h"
|
||||
#include "qvideosurfacegstsink_p.h"
|
||||
#include "qgstvideobuffer_p.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
GstBufferClass *QGstXvImageBuffer::parent_class = NULL;
|
||||
|
||||
GType QGstXvImageBuffer::get_type(void)
|
||||
{
|
||||
static GType buffer_type = 0;
|
||||
|
||||
if (buffer_type == 0) {
|
||||
static const GTypeInfo buffer_info = {
|
||||
sizeof (GstBufferClass),
|
||||
NULL,
|
||||
NULL,
|
||||
QGstXvImageBuffer::class_init,
|
||||
NULL,
|
||||
NULL,
|
||||
sizeof(QGstXvImageBuffer),
|
||||
0,
|
||||
(GInstanceInitFunc)QGstXvImageBuffer::buffer_init,
|
||||
NULL
|
||||
};
|
||||
buffer_type = g_type_register_static(GST_TYPE_BUFFER,
|
||||
"QGstXvImageBuffer", &buffer_info, GTypeFlags(0));
|
||||
}
|
||||
return buffer_type;
|
||||
}
|
||||
|
||||
void QGstXvImageBuffer::class_init(gpointer g_class, gpointer class_data)
|
||||
{
|
||||
Q_UNUSED(class_data);
|
||||
GST_MINI_OBJECT_CLASS(g_class)->finalize =
|
||||
(GstMiniObjectFinalizeFunction)buffer_finalize;
|
||||
parent_class = (GstBufferClass*)g_type_class_peek_parent(g_class);
|
||||
}
|
||||
|
||||
void QGstXvImageBuffer::buffer_init(QGstXvImageBuffer *xvImage, gpointer g_class)
|
||||
{
|
||||
Q_UNUSED(g_class);
|
||||
xvImage->pool = 0;
|
||||
xvImage->shmInfo.shmaddr = ((char *) -1);
|
||||
xvImage->shmInfo.shmid = -1;
|
||||
xvImage->markedForDeletion = false;
|
||||
}
|
||||
|
||||
void QGstXvImageBuffer::buffer_finalize(QGstXvImageBuffer * xvImage)
|
||||
{
|
||||
if (xvImage->pool) {
|
||||
if (xvImage->markedForDeletion)
|
||||
xvImage->pool->destroyBuffer(xvImage);
|
||||
else
|
||||
xvImage->pool->recycleBuffer(xvImage);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QGstXvImageBufferPool::QGstXvImageBufferPool(QObject *parent)
|
||||
:QObject(parent)
|
||||
{
|
||||
m_threadId = QThread::currentThreadId();
|
||||
}
|
||||
|
||||
QGstXvImageBufferPool::~QGstXvImageBufferPool()
|
||||
{
|
||||
}
|
||||
|
||||
bool QGstXvImageBufferPool::isFormatSupported(const QVideoSurfaceFormat &surfaceFormat) const
|
||||
{
|
||||
bool ok = true;
|
||||
surfaceFormat.property("portId").toULongLong(&ok);
|
||||
if (!ok)
|
||||
return false;
|
||||
|
||||
int xvFormatId = surfaceFormat.property("xvFormatId").toInt(&ok);
|
||||
if (!ok || xvFormatId < 0)
|
||||
return false;
|
||||
|
||||
int dataSize = surfaceFormat.property("dataSize").toInt(&ok);
|
||||
if (!ok || dataSize<=0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
GType QGstXvImageBufferPool::bufferType() const
|
||||
{
|
||||
return QGstXvImageBuffer::get_type();
|
||||
}
|
||||
|
||||
GstBuffer *QGstXvImageBufferPool::takeBuffer(
|
||||
const QVideoSurfaceFormat &format, GstCaps *caps)
|
||||
{
|
||||
m_poolMutex.lock();
|
||||
|
||||
m_caps = caps;
|
||||
if (format != m_format) {
|
||||
doClear();
|
||||
m_format = format;
|
||||
}
|
||||
|
||||
|
||||
if (m_pool.isEmpty()) {
|
||||
//qDebug() << "QGstXvImageBufferPool::takeBuffer: no buffer available, allocate the new one" << QThread::currentThreadId() << m_threadId;
|
||||
if (QThread::currentThreadId() == m_threadId) {
|
||||
doAlloc();
|
||||
} else {
|
||||
QMetaObject::invokeMethod(this, "queuedAlloc", Qt::QueuedConnection);
|
||||
m_allocWaitCondition.wait(&m_poolMutex, 300);
|
||||
}
|
||||
}
|
||||
QGstXvImageBuffer *res = 0;
|
||||
|
||||
if (!m_pool.isEmpty()) {
|
||||
res = m_pool.takeLast();
|
||||
}
|
||||
|
||||
m_poolMutex.unlock();
|
||||
|
||||
return GST_BUFFER(res);
|
||||
}
|
||||
|
||||
QAbstractVideoBuffer::HandleType QGstXvImageBufferPool::handleType() const
|
||||
{
|
||||
return QAbstractVideoBuffer::XvShmImageHandle;
|
||||
}
|
||||
|
||||
QAbstractVideoBuffer *QGstXvImageBufferPool::prepareVideoBuffer(GstBuffer *buffer, int bytesPerLine)
|
||||
{
|
||||
if (!G_TYPE_CHECK_INSTANCE_TYPE(buffer, bufferType()))
|
||||
return 0;
|
||||
|
||||
QGstXvImageBuffer *xvBuffer = reinterpret_cast<QGstXvImageBuffer *>(buffer);
|
||||
QVariant handle = QVariant::fromValue(xvBuffer->xvImage);
|
||||
return new QGstVideoBuffer(buffer, bytesPerLine, QAbstractVideoBuffer::XvShmImageHandle, handle);
|
||||
}
|
||||
|
||||
QStringList QGstXvImageBufferPool::keys() const
|
||||
{
|
||||
return QStringList() << QGstBufferPoolPluginKey;
|
||||
}
|
||||
|
||||
void QGstXvImageBufferPool::queuedAlloc()
|
||||
{
|
||||
QMutexLocker lock(&m_poolMutex);
|
||||
doAlloc();
|
||||
m_allocWaitCondition.wakeOne();
|
||||
}
|
||||
|
||||
void QGstXvImageBufferPool::doAlloc()
|
||||
{
|
||||
//should be always called from the main thread with m_poolMutex locked
|
||||
//Q_ASSERT(QThread::currentThread() == thread());
|
||||
|
||||
XSync(display(), false);
|
||||
|
||||
QGstXvImageBuffer *xvBuffer = (QGstXvImageBuffer *)gst_mini_object_new(QGstXvImageBuffer::get_type());
|
||||
|
||||
quint64 portId = m_format.property("portId").toULongLong();
|
||||
int xvFormatId = m_format.property("xvFormatId").toInt();
|
||||
|
||||
xvBuffer->xvImage = XvShmCreateImage(
|
||||
display(),
|
||||
portId,
|
||||
xvFormatId,
|
||||
0,
|
||||
m_format.frameWidth(),
|
||||
m_format.frameHeight(),
|
||||
&xvBuffer->shmInfo
|
||||
);
|
||||
|
||||
if (!xvBuffer->xvImage) {
|
||||
qWarning() << "QGstXvImageBufferPool: XvShmCreateImage failed";
|
||||
return;
|
||||
}
|
||||
|
||||
XSync(display(), false);
|
||||
|
||||
xvBuffer->shmInfo.shmid = shmget(IPC_PRIVATE, xvBuffer->xvImage->data_size, IPC_CREAT | 0777);
|
||||
xvBuffer->shmInfo.shmaddr = xvBuffer->xvImage->data = (char*)shmat(xvBuffer->shmInfo.shmid, 0, 0);
|
||||
xvBuffer->shmInfo.readOnly = False;
|
||||
|
||||
if (!XShmAttach(display(), &xvBuffer->shmInfo)) {
|
||||
qWarning() << "QGstXvImageBufferPool: XShmAttach failed";
|
||||
return;
|
||||
}
|
||||
|
||||
XSync(display(), false);
|
||||
|
||||
shmctl (xvBuffer->shmInfo.shmid, IPC_RMID, NULL);
|
||||
|
||||
xvBuffer->pool = this;
|
||||
GST_MINI_OBJECT_CAST(xvBuffer)->flags = 0;
|
||||
gst_buffer_set_caps(GST_BUFFER_CAST(xvBuffer), m_caps);
|
||||
GST_BUFFER_DATA(xvBuffer) = (uchar*)xvBuffer->xvImage->data;
|
||||
GST_BUFFER_SIZE(xvBuffer) = xvBuffer->xvImage->data_size;
|
||||
|
||||
m_allBuffers.append(xvBuffer);
|
||||
m_pool.append(xvBuffer);
|
||||
|
||||
XSync(display(), false);
|
||||
}
|
||||
|
||||
|
||||
void QGstXvImageBufferPool::clear()
|
||||
{
|
||||
QMutexLocker lock(&m_poolMutex);
|
||||
doClear();
|
||||
}
|
||||
|
||||
void QGstXvImageBufferPool::doClear()
|
||||
{
|
||||
foreach (QGstXvImageBuffer *xvBuffer, m_allBuffers) {
|
||||
xvBuffer->markedForDeletion = true;
|
||||
}
|
||||
m_allBuffers.clear();
|
||||
|
||||
foreach (QGstXvImageBuffer *xvBuffer, m_pool) {
|
||||
gst_buffer_unref(GST_BUFFER(xvBuffer));
|
||||
}
|
||||
m_pool.clear();
|
||||
|
||||
m_format = QVideoSurfaceFormat();
|
||||
}
|
||||
|
||||
void QGstXvImageBufferPool::queuedDestroy()
|
||||
{
|
||||
QMutexLocker lock(&m_destroyMutex);
|
||||
|
||||
XSync(display(), false);
|
||||
|
||||
foreach(XvShmImage xvImage, m_imagesToDestroy) {
|
||||
if (xvImage.shmInfo.shmaddr != ((void *) -1)) {
|
||||
XShmDetach(display(), &xvImage.shmInfo);
|
||||
XSync(display(), false);
|
||||
|
||||
shmdt(xvImage.shmInfo.shmaddr);
|
||||
}
|
||||
|
||||
if (xvImage.xvImage)
|
||||
XFree(xvImage.xvImage);
|
||||
}
|
||||
|
||||
m_imagesToDestroy.clear();
|
||||
|
||||
XSync(display(), false);
|
||||
}
|
||||
|
||||
void QGstXvImageBufferPool::recycleBuffer(QGstXvImageBuffer *xvBuffer)
|
||||
{
|
||||
QMutexLocker lock(&m_poolMutex);
|
||||
gst_buffer_ref(GST_BUFFER_CAST(xvBuffer));
|
||||
m_pool.append(xvBuffer);
|
||||
}
|
||||
|
||||
void QGstXvImageBufferPool::destroyBuffer(QGstXvImageBuffer *xvBuffer)
|
||||
{
|
||||
XvShmImage imageToDestroy;
|
||||
imageToDestroy.xvImage = xvBuffer->xvImage;
|
||||
imageToDestroy.shmInfo = xvBuffer->shmInfo;
|
||||
|
||||
m_destroyMutex.lock();
|
||||
m_imagesToDestroy.append(imageToDestroy);
|
||||
m_destroyMutex.unlock();
|
||||
|
||||
if (m_imagesToDestroy.size() == 1)
|
||||
QMetaObject::invokeMethod(this, "queuedDestroy", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
Display *QGstXvImageBufferPool::display() const
|
||||
{
|
||||
QWindow *window = QGuiApplication::topLevelWindows().first();
|
||||
Display *display = static_cast<Display *>(QGuiApplication::platformNativeInterface()->nativeResourceForWindow("Display", window));
|
||||
|
||||
return display;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
@@ -49,10 +49,6 @@
|
||||
#include <private/qmediapluginloader_p.h>
|
||||
#include "qgstvideobuffer_p.h"
|
||||
|
||||
#if defined(HAVE_XVIDEO)
|
||||
#include "qgstxvimagebuffer_p.h"
|
||||
#endif
|
||||
|
||||
#include "qvideosurfacegstsink_p.h"
|
||||
|
||||
//#define DEBUG_VIDEO_SURFACE_SINK
|
||||
@@ -79,9 +75,6 @@ QVideoSurfaceGstDelegate::QVideoSurfaceGstDelegate(
|
||||
m_pools.append(plugin);
|
||||
}
|
||||
}
|
||||
#ifdef HAVE_XVIDEO
|
||||
m_pools.append(new QGstXvImageBufferPool(this));
|
||||
#endif
|
||||
updateSupportedFormats();
|
||||
connect(m_surface, SIGNAL(supportedFormatsChanged()), this, SLOT(updateSupportedFormats()));
|
||||
}
|
||||
|
||||
@@ -1,534 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** 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 Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/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 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, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia 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.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include <QtCore/qvariant.h>
|
||||
#include <QtCore/qdebug.h>
|
||||
#include <QtGui/qguiapplication.h>
|
||||
#include <qpa/qplatformnativeinterface.h>
|
||||
#include <qvideosurfaceformat.h>
|
||||
|
||||
#include "qx11videosurface_p.h"
|
||||
|
||||
Q_DECLARE_METATYPE(XvImage*);
|
||||
|
||||
struct XvFormatRgb
|
||||
{
|
||||
QVideoFrame::PixelFormat pixelFormat;
|
||||
int bits_per_pixel;
|
||||
int format;
|
||||
int num_planes;
|
||||
|
||||
int depth;
|
||||
unsigned int red_mask;
|
||||
unsigned int green_mask;
|
||||
unsigned int blue_mask;
|
||||
|
||||
};
|
||||
|
||||
bool operator ==(const XvImageFormatValues &format, const XvFormatRgb &rgb)
|
||||
{
|
||||
return format.type == XvRGB
|
||||
&& format.bits_per_pixel == rgb.bits_per_pixel
|
||||
&& format.format == rgb.format
|
||||
&& format.num_planes == rgb.num_planes
|
||||
&& format.depth == rgb.depth
|
||||
&& format.red_mask == rgb.red_mask
|
||||
&& format.blue_mask == rgb.blue_mask;
|
||||
}
|
||||
|
||||
static const XvFormatRgb qt_xvRgbLookup[] =
|
||||
{
|
||||
{ QVideoFrame::Format_ARGB32, 32, XvPacked, 1, 32, 0x00FF0000, 0x0000FF00, 0x000000FF },
|
||||
{ QVideoFrame::Format_RGB32 , 32, XvPacked, 1, 24, 0x00FF0000, 0x0000FF00, 0x000000FF },
|
||||
{ QVideoFrame::Format_RGB24 , 24, XvPacked, 1, 24, 0x00FF0000, 0x0000FF00, 0x000000FF },
|
||||
{ QVideoFrame::Format_RGB565, 16, XvPacked, 1, 16, 0x0000F800, 0x000007E0, 0x0000001F },
|
||||
{ QVideoFrame::Format_BGRA32, 32, XvPacked, 1, 32, 0xFF000000, 0x00FF0000, 0x0000FF00 },
|
||||
{ QVideoFrame::Format_BGR32 , 32, XvPacked, 1, 24, 0x00FF0000, 0x0000FF00, 0x000000FF },
|
||||
{ QVideoFrame::Format_BGR24 , 24, XvPacked, 1, 24, 0x00FF0000, 0x0000FF00, 0x000000FF },
|
||||
{ QVideoFrame::Format_BGR565, 16, XvPacked, 1, 16, 0x0000F800, 0x000007E0, 0x0000001F }
|
||||
};
|
||||
|
||||
struct XvFormatYuv
|
||||
{
|
||||
QVideoFrame::PixelFormat pixelFormat;
|
||||
int bits_per_pixel;
|
||||
int format;
|
||||
int num_planes;
|
||||
|
||||
unsigned int y_sample_bits;
|
||||
unsigned int u_sample_bits;
|
||||
unsigned int v_sample_bits;
|
||||
unsigned int horz_y_period;
|
||||
unsigned int horz_u_period;
|
||||
unsigned int horz_v_period;
|
||||
unsigned int vert_y_period;
|
||||
unsigned int vert_u_period;
|
||||
unsigned int vert_v_period;
|
||||
char component_order[32];
|
||||
};
|
||||
|
||||
bool operator ==(const XvImageFormatValues &format, const XvFormatYuv &yuv)
|
||||
{
|
||||
return format.type == XvYUV
|
||||
&& format.bits_per_pixel == yuv.bits_per_pixel
|
||||
&& format.format == yuv.format
|
||||
&& format.num_planes == yuv.num_planes
|
||||
&& format.y_sample_bits == yuv.y_sample_bits
|
||||
&& format.u_sample_bits == yuv.u_sample_bits
|
||||
&& format.v_sample_bits == yuv.v_sample_bits
|
||||
&& format.horz_y_period == yuv.horz_y_period
|
||||
&& format.horz_u_period == yuv.horz_u_period
|
||||
&& format.horz_v_period == yuv.horz_v_period
|
||||
&& format.horz_y_period == yuv.vert_y_period
|
||||
&& format.vert_u_period == yuv.vert_u_period
|
||||
&& format.vert_v_period == yuv.vert_v_period
|
||||
&& qstrncmp(format.component_order, yuv.component_order, 32) == 0;
|
||||
}
|
||||
|
||||
static const XvFormatYuv qt_xvYuvLookup[] =
|
||||
{
|
||||
{ QVideoFrame::Format_YUV444 , 24, XvPacked, 1, 8, 8, 8, 1, 1, 1, 1, 1, 1, "YUV" },
|
||||
{ QVideoFrame::Format_YUV420P, 12, XvPlanar, 3, 8, 8, 8, 1, 2, 2, 1, 2, 2, "YUV" },
|
||||
{ QVideoFrame::Format_YV12 , 12, XvPlanar, 3, 8, 8, 8, 1, 2, 2, 1, 2, 2, "YVU" },
|
||||
{ QVideoFrame::Format_UYVY , 16, XvPacked, 1, 8, 8, 8, 1, 2, 2, 1, 1, 1, "UYVY" },
|
||||
{ QVideoFrame::Format_YUYV , 16, XvPacked, 1, 8, 8, 8, 1, 2, 2, 1, 1, 1, "YUY2" },
|
||||
{ QVideoFrame::Format_YUYV , 16, XvPacked, 1, 8, 8, 8, 1, 2, 2, 1, 1, 1, "YUYV" },
|
||||
{ QVideoFrame::Format_NV12 , 12, XvPlanar, 2, 8, 8, 8, 1, 2, 2, 1, 2, 2, "YUV" },
|
||||
{ QVideoFrame::Format_NV12 , 12, XvPlanar, 2, 8, 8, 8, 1, 2, 2, 1, 2, 2, "YVU" },
|
||||
{ QVideoFrame::Format_Y8 , 8 , XvPlanar, 1, 8, 0, 0, 1, 0, 0, 1, 0, 0, "Y" }
|
||||
};
|
||||
|
||||
QX11VideoSurface::QX11VideoSurface(QObject *parent)
|
||||
: QAbstractVideoSurface(parent)
|
||||
, m_winId(0)
|
||||
, m_portId(0)
|
||||
, m_gc(0)
|
||||
, m_image(0)
|
||||
{
|
||||
}
|
||||
|
||||
QX11VideoSurface::~QX11VideoSurface()
|
||||
{
|
||||
if (m_gc)
|
||||
XFreeGC(display(), m_gc);
|
||||
|
||||
if (m_portId != 0)
|
||||
XvUngrabPort(display(), m_portId, 0);
|
||||
}
|
||||
|
||||
WId QX11VideoSurface::winId() const
|
||||
{
|
||||
return m_winId;
|
||||
}
|
||||
|
||||
void QX11VideoSurface::setWinId(WId id)
|
||||
{
|
||||
//qDebug() << "setWinID:" << id;
|
||||
|
||||
if (id == m_winId)
|
||||
return;
|
||||
|
||||
if (m_image)
|
||||
XFree(m_image);
|
||||
|
||||
if (m_gc) {
|
||||
XFreeGC(display(), m_gc);
|
||||
m_gc = 0;
|
||||
}
|
||||
|
||||
if (m_portId != 0)
|
||||
XvUngrabPort(display(), m_portId, 0);
|
||||
|
||||
m_supportedPixelFormats.clear();
|
||||
m_formatIds.clear();
|
||||
|
||||
m_winId = id;
|
||||
|
||||
if (m_winId && findPort()) {
|
||||
querySupportedFormats();
|
||||
|
||||
m_gc = XCreateGC(display(), m_winId, 0, 0);
|
||||
|
||||
if (m_image) {
|
||||
m_image = 0;
|
||||
|
||||
if (!start(surfaceFormat())) {
|
||||
QAbstractVideoSurface::stop();
|
||||
qWarning() << "Failed to start video surface with format" << surfaceFormat();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
qWarning() << "Failed to find XVideo port";
|
||||
if (m_image) {
|
||||
m_image = 0;
|
||||
|
||||
QAbstractVideoSurface::stop();
|
||||
}
|
||||
}
|
||||
|
||||
emit supportedFormatsChanged();
|
||||
}
|
||||
|
||||
QRect QX11VideoSurface::displayRect() const
|
||||
{
|
||||
return m_displayRect;
|
||||
}
|
||||
|
||||
void QX11VideoSurface::setDisplayRect(const QRect &rect)
|
||||
{
|
||||
m_displayRect = rect;
|
||||
}
|
||||
|
||||
QRect QX11VideoSurface::viewport() const
|
||||
{
|
||||
return m_viewport;
|
||||
}
|
||||
|
||||
void QX11VideoSurface::setViewport(const QRect &rect)
|
||||
{
|
||||
m_viewport = rect;
|
||||
}
|
||||
|
||||
int QX11VideoSurface::brightness() const
|
||||
{
|
||||
return getAttribute("XV_BRIGHTNESS", m_brightnessRange.first, m_brightnessRange.second);
|
||||
}
|
||||
|
||||
void QX11VideoSurface::setBrightness(int brightness)
|
||||
{
|
||||
setAttribute("XV_BRIGHTNESS", brightness, m_brightnessRange.first, m_brightnessRange.second);
|
||||
}
|
||||
|
||||
int QX11VideoSurface::contrast() const
|
||||
{
|
||||
return getAttribute("XV_CONTRAST", m_contrastRange.first, m_contrastRange.second);
|
||||
}
|
||||
|
||||
void QX11VideoSurface::setContrast(int contrast)
|
||||
{
|
||||
setAttribute("XV_CONTRAST", contrast, m_contrastRange.first, m_contrastRange.second);
|
||||
}
|
||||
|
||||
int QX11VideoSurface::hue() const
|
||||
{
|
||||
return getAttribute("XV_HUE", m_hueRange.first, m_hueRange.second);
|
||||
}
|
||||
|
||||
void QX11VideoSurface::setHue(int hue)
|
||||
{
|
||||
setAttribute("XV_HUE", hue, m_hueRange.first, m_hueRange.second);
|
||||
}
|
||||
|
||||
int QX11VideoSurface::saturation() const
|
||||
{
|
||||
return getAttribute("XV_SATURATION", m_saturationRange.first, m_saturationRange.second);
|
||||
}
|
||||
|
||||
void QX11VideoSurface::setSaturation(int saturation)
|
||||
{
|
||||
setAttribute("XV_SATURATION", saturation, m_saturationRange.first, m_saturationRange.second);
|
||||
}
|
||||
|
||||
int QX11VideoSurface::getAttribute(const char *attribute, int minimum, int maximum) const
|
||||
{
|
||||
if (m_portId != 0) {
|
||||
Display *disp = display();
|
||||
|
||||
Atom atom = XInternAtom(disp, attribute, True);
|
||||
|
||||
int value = 0;
|
||||
|
||||
XvGetPortAttribute(disp, m_portId, atom, &value);
|
||||
|
||||
return redistribute(value, minimum, maximum, -100, 100);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void QX11VideoSurface::setAttribute(const char *attribute, int value, int minimum, int maximum)
|
||||
{
|
||||
if (m_portId != 0) {
|
||||
Display *disp = display();
|
||||
|
||||
Atom atom = XInternAtom(disp, attribute, True);
|
||||
|
||||
XvSetPortAttribute(
|
||||
disp, m_portId, atom, redistribute(value, -100, 100, minimum, maximum));
|
||||
}
|
||||
}
|
||||
|
||||
int QX11VideoSurface::redistribute(
|
||||
int value, int fromLower, int fromUpper, int toLower, int toUpper)
|
||||
{
|
||||
return fromUpper != fromLower
|
||||
? ((value - fromLower) * (toUpper - toLower) / (fromUpper - fromLower)) + toLower
|
||||
: 0;
|
||||
}
|
||||
|
||||
QList<QVideoFrame::PixelFormat> QX11VideoSurface::supportedPixelFormats(
|
||||
QAbstractVideoBuffer::HandleType handleType) const
|
||||
{
|
||||
return handleType == QAbstractVideoBuffer::NoHandle || handleType == QAbstractVideoBuffer::XvShmImageHandle
|
||||
? m_supportedPixelFormats
|
||||
: QList<QVideoFrame::PixelFormat>();
|
||||
}
|
||||
|
||||
bool QX11VideoSurface::start(const QVideoSurfaceFormat &format)
|
||||
{
|
||||
if (m_image)
|
||||
XFree(m_image);
|
||||
|
||||
int xvFormatId = 0;
|
||||
for (int i = 0; i < m_supportedPixelFormats.count(); ++i) {
|
||||
if (m_supportedPixelFormats.at(i) == format.pixelFormat()) {
|
||||
xvFormatId = m_formatIds.at(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (xvFormatId == 0) {
|
||||
setError(UnsupportedFormatError);
|
||||
} else {
|
||||
XvImage *image = XvCreateImage(
|
||||
display(),
|
||||
m_portId,
|
||||
xvFormatId,
|
||||
0,
|
||||
format.frameWidth(),
|
||||
format.frameHeight());
|
||||
|
||||
if (!image) {
|
||||
setError(ResourceError);
|
||||
} else {
|
||||
m_viewport = format.viewport();
|
||||
m_image = image;
|
||||
|
||||
QVideoSurfaceFormat newFormat = format;
|
||||
newFormat.setProperty("portId", QVariant(quint64(m_portId)));
|
||||
newFormat.setProperty("xvFormatId", xvFormatId);
|
||||
newFormat.setProperty("dataSize", image->data_size);
|
||||
|
||||
return QAbstractVideoSurface::start(newFormat);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_image) {
|
||||
m_image = 0;
|
||||
|
||||
QAbstractVideoSurface::stop();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void QX11VideoSurface::stop()
|
||||
{
|
||||
if (m_image) {
|
||||
XFree(m_image);
|
||||
m_image = 0;
|
||||
|
||||
QAbstractVideoSurface::stop();
|
||||
}
|
||||
}
|
||||
|
||||
bool QX11VideoSurface::present(const QVideoFrame &frame)
|
||||
{
|
||||
if (!m_image) {
|
||||
setError(StoppedError);
|
||||
return false;
|
||||
} else if (m_image->width != frame.width() || m_image->height != frame.height()) {
|
||||
setError(IncorrectFormatError);
|
||||
return false;
|
||||
} else {
|
||||
QVideoFrame frameCopy(frame);
|
||||
|
||||
if (!frameCopy.map(QAbstractVideoBuffer::ReadOnly)) {
|
||||
setError(IncorrectFormatError);
|
||||
return false;
|
||||
} else {
|
||||
bool presented = false;
|
||||
|
||||
if (frame.handleType() != QAbstractVideoBuffer::XvShmImageHandle &&
|
||||
m_image->data_size > frame.mappedBytes()) {
|
||||
qWarning("Insufficient frame buffer size");
|
||||
setError(IncorrectFormatError);
|
||||
} else if (frame.handleType() != QAbstractVideoBuffer::XvShmImageHandle &&
|
||||
m_image->num_planes > 0 &&
|
||||
m_image->pitches[0] != frame.bytesPerLine()) {
|
||||
qWarning("Incompatible frame pitches");
|
||||
setError(IncorrectFormatError);
|
||||
} else {
|
||||
if (frame.handleType() != QAbstractVideoBuffer::XvShmImageHandle) {
|
||||
m_image->data = reinterpret_cast<char *>(frameCopy.bits());
|
||||
|
||||
//qDebug() << "copy frame";
|
||||
XvPutImage(
|
||||
display(),
|
||||
m_portId,
|
||||
m_winId,
|
||||
m_gc,
|
||||
m_image,
|
||||
m_viewport.x(),
|
||||
m_viewport.y(),
|
||||
m_viewport.width(),
|
||||
m_viewport.height(),
|
||||
m_displayRect.x(),
|
||||
m_displayRect.y(),
|
||||
m_displayRect.width(),
|
||||
m_displayRect.height());
|
||||
|
||||
m_image->data = 0;
|
||||
} else {
|
||||
XvImage *img = frame.handle().value<XvImage*>();
|
||||
|
||||
//qDebug() << "render directly";
|
||||
if (img)
|
||||
XvShmPutImage(
|
||||
display(),
|
||||
m_portId,
|
||||
m_winId,
|
||||
m_gc,
|
||||
img,
|
||||
m_viewport.x(),
|
||||
m_viewport.y(),
|
||||
m_viewport.width(),
|
||||
m_viewport.height(),
|
||||
m_displayRect.x(),
|
||||
m_displayRect.y(),
|
||||
m_displayRect.width(),
|
||||
m_displayRect.height(),
|
||||
false);
|
||||
}
|
||||
|
||||
presented = true;
|
||||
}
|
||||
|
||||
frameCopy.unmap();
|
||||
|
||||
return presented;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Display *QX11VideoSurface::display() const
|
||||
{
|
||||
QWindow *window = QGuiApplication::focusWindow();
|
||||
Display *display = (Display *)QGuiApplication::platformNativeInterface()->nativeResourceForWindow("Display", window);
|
||||
|
||||
return display;
|
||||
}
|
||||
|
||||
bool QX11VideoSurface::findPort()
|
||||
{
|
||||
unsigned int count = 0;
|
||||
XvAdaptorInfo *adaptors = 0;
|
||||
bool portFound = false;
|
||||
|
||||
if (XvQueryAdaptors(display(), m_winId, &count, &adaptors) == Success) {
|
||||
for (unsigned int i = 0; i < count && !portFound; ++i) {
|
||||
if (adaptors[i].type & XvImageMask) {
|
||||
m_portId = adaptors[i].base_id;
|
||||
|
||||
for (unsigned int j = 0; j < adaptors[i].num_ports && !portFound; ++j, ++m_portId)
|
||||
portFound = XvGrabPort(display(), m_portId, 0) == Success;
|
||||
}
|
||||
}
|
||||
XvFreeAdaptorInfo(adaptors);
|
||||
}
|
||||
|
||||
return portFound;
|
||||
}
|
||||
|
||||
void QX11VideoSurface::querySupportedFormats()
|
||||
{
|
||||
int count = 0;
|
||||
if (XvImageFormatValues *imageFormats = XvListImageFormats(
|
||||
display(), m_portId, &count)) {
|
||||
const int rgbCount = sizeof(qt_xvRgbLookup) / sizeof(XvFormatRgb);
|
||||
const int yuvCount = sizeof(qt_xvYuvLookup) / sizeof(XvFormatYuv);
|
||||
|
||||
for (int i = 0; i < count; ++i) {
|
||||
switch (imageFormats[i].type) {
|
||||
case XvRGB:
|
||||
for (int j = 0; j < rgbCount; ++j) {
|
||||
if (imageFormats[i] == qt_xvRgbLookup[j]) {
|
||||
m_supportedPixelFormats.append(qt_xvRgbLookup[j].pixelFormat);
|
||||
m_formatIds.append(imageFormats[i].id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case XvYUV:
|
||||
for (int j = 0; j < yuvCount; ++j) {
|
||||
if (imageFormats[i] == qt_xvYuvLookup[j]) {
|
||||
m_supportedPixelFormats.append(qt_xvYuvLookup[j].pixelFormat);
|
||||
m_formatIds.append(imageFormats[i].id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
XFree(imageFormats);
|
||||
}
|
||||
|
||||
m_brightnessRange = qMakePair(0, 0);
|
||||
m_contrastRange = qMakePair(0, 0);
|
||||
m_hueRange = qMakePair(0, 0);
|
||||
m_saturationRange = qMakePair(0, 0);
|
||||
|
||||
if (XvAttribute *attributes = XvQueryPortAttributes(display(), m_portId, &count)) {
|
||||
for (int i = 0; i < count; ++i) {
|
||||
if (qstrcmp(attributes[i].name, "XV_BRIGHTNESS") == 0)
|
||||
m_brightnessRange = qMakePair(attributes[i].min_value, attributes[i].max_value);
|
||||
else if (qstrcmp(attributes[i].name, "XV_CONTRAST") == 0)
|
||||
m_contrastRange = qMakePair(attributes[i].min_value, attributes[i].max_value);
|
||||
else if (qstrcmp(attributes[i].name, "XV_HUE") == 0)
|
||||
m_hueRange = qMakePair(attributes[i].min_value, attributes[i].max_value);
|
||||
else if (qstrcmp(attributes[i].name, "XV_SATURATION") == 0)
|
||||
m_saturationRange = qMakePair(attributes[i].min_value, attributes[i].max_value);
|
||||
}
|
||||
|
||||
XFree(attributes);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user