Commit 4b4f758b authored by Gus Grubba's avatar Gus Grubba Committed by dogmaphobic

Video Streaming

parent bffd454c
......@@ -652,6 +652,17 @@ SOURCES += \
src/FactSystem/ParameterLoader.cc \
src/FactSystem/FactControls/FactPanelController.cc \
# Video Streaming
contains (DEFINES, DISABLE_VIDEOSTREAMING) {
message("Skipping support for video streaming (manual override from command line)")
DEFINES -= DISABLE_VIDEOSTREAMING
# Otherwise the user can still disable this feature in the user_config.pri file.
} else:exists(user_config.pri):infile(user_config.pri, DEFINES, DISABLE_VIDEOSTREAMING) {
message("Skipping support for video streaming (manual override from user_config.pri)")
} else {
include(src/VideoStreaming/VideoStreaming.pri)
}
# Android
AndroidBuild {
......
This diff is collapsed.
......@@ -40,6 +40,14 @@
#include <QDebug>
#if defined(QGC_GST_STREAMING)
#include <videoitem.h>
#include <videosurface.h>
G_BEGIN_DECLS
GST_PLUGIN_STATIC_DECLARE(QTVIDEOSINK_NAME);
G_END_DECLS
#endif
#include "configuration.h"
#include "QGC.h"
#include "QGCApplication.h"
......@@ -255,11 +263,28 @@ QGCApplication::QGCApplication(int &argc, char* argv[], bool unitTesting)
settings.clear();
settings.setValue(_settingsVersionKey, QGC_SETTINGS_VERSION);
}
#if defined(QGC_GST_STREAMING)
//----------------------------------------------------------------
//-- Video Streaming
qmlRegisterType<VideoItem>("QGroundControl.QgcQtGStreamer", 1, 0, "VideoItem");
qmlRegisterUncreatableType<VideoSurface>("QGroundControl.QgcQtGStreamer", 1, 0, "VideoSurface", QLatin1String("VideoSurface from QML is not supported"));
GError* error = NULL;
if (!gst_init_check(&argc, &argv, &error)) {
qCritical() << "gst_init_check() failed: " << error->message;
g_error_free(error);
}
GST_PLUGIN_STATIC_REGISTER(QTVIDEOSINK_NAME);
#endif
}
QGCApplication::~QGCApplication()
{
_destroySingletons();
#if defined(QGC_GST_STREAMING)
gst_deinit();
#endif
}
void QGCApplication::_initCommon(void)
......
......@@ -50,6 +50,7 @@ public:
Q_PROPERTY(bool isAndroid READ isAndroid CONSTANT)
Q_PROPERTY(bool isiOS READ isiOS CONSTANT)
Q_PROPERTY(bool isMobile READ isMobile CONSTANT)
Q_PROPERTY(bool hasVideo READ hasVideo CONSTANT)
//! Used to trigger a \c Canvas element repaint.
/*!
......@@ -110,6 +111,12 @@ public:
bool isMobile () { return false; }
#endif
#if defined(QGC_GST_STREAMING)
bool hasVideo () { return true; }
#else
bool hasVideo () { return false; }
#endif
signals:
void repaintRequested(void);
......
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009, 2015 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/**
* @file
* @brief QGC Video Item
* @author Gus Grubba <mavlink@grubba.com>
*/
#include <QtCore/QPointer>
#include <QtQuick/QSGNode>
#include <QtQuick/QSGFlatColorMaterial>
#include "videoitem.h"
#include "videosurface_p.h"
struct VideoItem::Private
{
QPointer<VideoSurface> surface;
bool surfaceDirty;
QRectF targetArea;
};
VideoItem::VideoItem(QQuickItem *parent)
: QQuickItem(parent), _data(new Private)
{
_data->surfaceDirty = true;
setFlag(QQuickItem::ItemHasContents, true);
}
VideoItem::~VideoItem()
{
setSurface(0);
delete _data;
}
VideoSurface *VideoItem::surface() const
{
return _data->surface.data();
}
void VideoItem::setSurface(VideoSurface *surface)
{
if (_data->surface) {
_data->surface.data()->_data->items.remove(this);
}
_data->surface = surface;
_data->surfaceDirty = true;
if (_data->surface) {
_data->surface.data()->_data->items.insert(this);
}
}
QSGNode* VideoItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData*)
{
QRectF r = boundingRect();
QSGNode* newNode = 0;
if (_data->surfaceDirty) {
delete oldNode;
oldNode = 0;
_data->surfaceDirty = false;
}
if (!_data->surface || _data->surface.data()->_data->videoSink == NULL) {
if (!oldNode) {
QSGFlatColorMaterial *material = new QSGFlatColorMaterial;
material->setColor(Qt::black);
QSGGeometryNode *node = new QSGGeometryNode;
node->setMaterial(material);
node->setFlag(QSGNode::OwnsMaterial);
node->setFlag(QSGNode::OwnsGeometry);
newNode = node;
_data->targetArea = QRectF(); //force geometry to be set
} else {
newNode = oldNode;
}
if (r != _data->targetArea) {
QSGGeometry *geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 4);
geometry->vertexDataAsPoint2D()[0].set(r.x(), r.y());
geometry->vertexDataAsPoint2D()[1].set(r.x(), r.height());
geometry->vertexDataAsPoint2D()[2].set(r.width(), r.y());
geometry->vertexDataAsPoint2D()[3].set(r.width(), r.height());
QSGGeometryNode *node = static_cast<QSGGeometryNode*>(newNode);
node->setGeometry(geometry);
_data->targetArea = r;
}
} else {
g_signal_emit_by_name(_data->surface.data()->_data->videoSink, "update-node", (void*)oldNode, r.x(), r.y(), r.width(), r.height(), (void**)&newNode);
}
return newNode;
}
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009, 2015 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/**
* @file
* @brief QGC Video Item
* @author Gus Grubba <mavlink@grubba.com>
*/
#ifndef VIDEO_ITEM_H
#define VIDEO_ITEM_H
#include <QtQuick/QQuickItem>
#include "videosurface.h"
class VideoItem : public QQuickItem
{
Q_OBJECT
Q_DISABLE_COPY(VideoItem)
Q_PROPERTY(VideoSurface* surface READ surface WRITE setSurface)
public:
explicit VideoItem(QQuickItem *parent = 0);
virtual ~VideoItem();
VideoSurface *surface() const;
void setSurface(VideoSurface *surface);
protected:
/*! Reimplemented from QQuickItem. */
virtual QSGNode* updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *updatePaintNodeData);
private:
struct Private;
Private* const _data;
};
#endif // VIDEO_ITEM_H
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009, 2015 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/**
* @file
* @brief QGC Video Receiver
* @author Gus Grubba <mavlink@grubba.com>
*/
#include "VideoReceiver.h"
#include <QDebug>
VideoReceiver::VideoReceiver(QObject* parent)
: QObject(parent)
, _pipeline(NULL)
, _videoSink(NULL)
{
}
VideoReceiver::~VideoReceiver()
{
stop();
setVideoSink(NULL);
}
void VideoReceiver::setVideoSink(GstElement* sink)
{
if (_videoSink) {
gst_object_unref(_videoSink);
_videoSink = NULL;
}
if (sink) {
_videoSink = sink;
gst_object_ref_sink(_videoSink);
}
}
void VideoReceiver::start()
{
if (_uri.isEmpty()) {
qCritical() << "VideoReceiver::start() failed because URI is not specified";
return;
}
if (_videoSink == NULL) {
qCritical() << "VideoReceiver::start() failed because video sink is not set";
return;
}
stop();
bool running = false;
GstElement* dataSource = NULL;
GstCaps* caps = NULL;
GstElement* demux = NULL;
GstElement* parser = NULL;
GstElement* decoder = NULL;
do {
if ((_pipeline = gst_pipeline_new("receiver")) == NULL) {
break;
}
if ((dataSource = gst_element_factory_make("udpsrc", "udp-source")) == NULL) {
break;
}
if ((caps = gst_caps_from_string("application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264")) == NULL) {
break;
}
g_object_set(G_OBJECT(dataSource), "uri", qPrintable(_uri), "caps", caps, NULL);
if ((demux = gst_element_factory_make("rtph264depay", "rtp-h264-depacketizer")) == NULL) {
break;
}
if ((parser = gst_element_factory_make("h264parse", "h264-parser")) == NULL) {
break;
}
if ((decoder = gst_element_factory_make("avdec_h264", "h264-decoder")) == NULL) {
break;
}
gst_bin_add_many(GST_BIN(_pipeline), dataSource, demux, parser, decoder, _videoSink, NULL);
if (gst_element_link_many(dataSource, demux, parser, decoder, _videoSink, NULL) != TRUE) {
break;
}
dataSource = demux = parser = decoder = NULL;
GstBus* bus = NULL;
if ((bus = gst_pipeline_get_bus(GST_PIPELINE(_pipeline))) != NULL) {
gst_bus_add_watch(bus, _onBusMessage, this);
gst_object_unref(bus);
bus = NULL;
}
running = gst_element_set_state(_pipeline, GST_STATE_PLAYING) != GST_STATE_CHANGE_FAILURE;
} while(0);
if (caps != NULL) {
gst_caps_unref(caps);
caps = NULL;
}
if (!running) {
qCritical() << "VideoReceiver::start() failed";
if (decoder != NULL) {
gst_object_unref(decoder);
decoder = NULL;
}
if (parser != NULL) {
gst_object_unref(parser);
parser = NULL;
}
if (demux != NULL) {
gst_object_unref(demux);
demux = NULL;
}
if (dataSource != NULL) {
gst_object_unref(dataSource);
dataSource = NULL;
}
if (_pipeline != NULL) {
gst_object_unref(_pipeline);
_pipeline = NULL;
}
}
}
void VideoReceiver::stop()
{
if (_pipeline != NULL) {
gst_element_set_state(_pipeline, GST_STATE_NULL);
gst_object_unref(_pipeline);
_pipeline = NULL;
}
}
void VideoReceiver::setUri(const QString & uri)
{
stop();
_uri = uri;
}
void VideoReceiver::_onBusMessage(GstMessage* msg)
{
switch (GST_MESSAGE_TYPE(msg)) {
case GST_MESSAGE_EOS:
stop();
break;
case GST_MESSAGE_ERROR:
do {
gchar* debug;
GError* error;
gst_message_parse_error(msg, &error, &debug);
g_free(debug);
qCritical() << error->message;
g_error_free(error);
} while(0);
stop();
break;
default:
break;
}
}
gboolean VideoReceiver::_onBusMessage(GstBus* bus, GstMessage* msg, gpointer data)
{
Q_UNUSED(bus)
Q_ASSERT(msg != NULL && data != NULL);
VideoReceiver* pThis = (VideoReceiver*)data;
pThis->_onBusMessage(msg);
return TRUE;
}
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009, 2015 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/**
* @file
* @brief QGC Video Receiver
* @author Gus Grubba <mavlink@grubba.com>
*/
#ifndef VIDEORECEIVER_H
#define VIDEORECEIVER_H
#include <QObject>
#include <gst/gst.h>
class VideoReceiver : public QObject
{
Q_OBJECT
public:
explicit VideoReceiver(QObject* parent = 0);
~VideoReceiver();
void setVideoSink(GstElement* sink);
public Q_SLOTS:
void start ();
void stop ();
void setUri (const QString& uri);
private:
void _onBusMessage(GstMessage* message);
static gboolean _onBusMessage(GstBus* bus, GstMessage* msg, gpointer data);
QString _uri;
GstElement* _pipeline;
GstElement* _videoSink;
};
#endif // VIDEORECEIVER_H
# -------------------------------------------------
# QGroundControl - Micro Air Vehicle Groundstation
# Please see our website at <http://qgroundcontrol.org>
# Maintainer:
# Lorenz Meier <lm@inf.ethz.ch>
# (c) 2009-2015 QGroundControl Developers
#
# This file is part of the open groundstation project
# QGroundControl is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# QGroundControl is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with QGroundControl. If not, see <http://www.gnu.org/licenses/>.
#
# Author: Gus Grubba <mavlink@grubba.com>
# -------------------------------------------------
#
#-- Depends on gstreamer, which can be found at: http://gstreamer.freedesktop.org/download/
#
LinuxBuild {
CONFIG += link_pkgconfig
packagesExist(gstreamer-1.0) {
message("Including support for video streaming")
DEFINES += QGC_GST_STREAMING
PKGCONFIG += gstreamer-1.0
CONFIG += VideoEnabled
}
} else:MacBuild {
#- gstreamer framework installed by the gstreamer devel installer
GST_ROOT = /Library/Frameworks/GStreamer.framework
exists($$GST_ROOT) {
message("Including support for video streaming")
DEFINES += QGC_GST_STREAMING
CONFIG += VideoEnabled
INCLUDEPATH += $$GST_ROOT/Headers
LIBS += -F/Library/Frameworks -framework GStreamer
}
}
VideoEnabled {
DEFINES += \
GST_PLUGIN_BUILD_STATIC \
QTGLVIDEOSINK_NAME=qt5glvideosink \
QTVIDEOSINK_NAME=qt5videosink
#QT_NO_KEYWORDS \
INCLUDEPATH += \
$$PWD \
$$PWD/gstqtvideosink \
$$PWD/gstqtvideosink/delegates \
$$PWD/gstqtvideosink/painters \
$$PWD/gstqtvideosink/utils \
HEADERS += \
$$PWD/VideoItem.h \
$$PWD/VideoReceiver.h \
$$PWD/VideoSurface.h \
$$PWD/VideoSurface_p.h \
SOURCES += \
$$PWD/VideoItem.cc \
$$PWD/VideoReceiver.cc \
$$PWD/VideoSurface.cc \
#-- QtGstreamer (gutted to our needs)
HEADERS += \
$$PWD/gstqtvideosink/delegates/basedelegate.h \
$$PWD/gstqtvideosink/delegates/qtquick2videosinkdelegate.h \
$$PWD/gstqtvideosink/delegates/qtvideosinkdelegate.h \
$$PWD/gstqtvideosink/delegates/qwidgetvideosinkdelegate.h \
$$PWD/gstqtvideosink/gstqtglvideosink.h \
$$PWD/gstqtvideosink/gstqtglvideosinkbase.h \
$$PWD/gstqtvideosink/gstqtquick2videosink.h \
$$PWD/gstqtvideosink/gstqtvideosink.h \
$$PWD/gstqtvideosink/gstqtvideosinkbase.h \
$$PWD/gstqtvideosink/gstqtvideosinkmarshal.h \
$$PWD/gstqtvideosink/gstqtvideosinkplugin.h \
$$PWD/gstqtvideosink/gstqwidgetvideosink.h \
$$PWD/gstqtvideosink/painters/abstractsurfacepainter.h \
$$PWD/gstqtvideosink/painters/genericsurfacepainter.h \
$$PWD/gstqtvideosink/painters/openglsurfacepainter.h \
$$PWD/gstqtvideosink/painters/videomaterial.h \
$$PWD/gstqtvideosink/painters/videonode.h \
$$PWD/gstqtvideosink/utils/bufferformat.h \
$$PWD/gstqtvideosink/utils/utils.h \
SOURCES += \
$$PWD/gstqtvideosink/delegates/basedelegate.cpp \
$$PWD/gstqtvideosink/delegates/qtquick2videosinkdelegate.cpp \
$$PWD/gstqtvideosink/delegates/qtvideosinkdelegate.cpp \
$$PWD/gstqtvideosink/delegates/qwidgetvideosinkdelegate.cpp \
$$PWD/gstqtvideosink/gstqtglvideosink.cpp \
$$PWD/gstqtvideosink/gstqtglvideosinkbase.cpp \
$$PWD/gstqtvideosink/gstqtvideosinkmarshal.c \
$$PWD/gstqtvideosink/gstqtquick2videosink.cpp \
$$PWD/gstqtvideosink/gstqtvideosink.cpp \
$$PWD/gstqtvideosink/gstqtvideosinkbase.cpp \
$$PWD/gstqtvideosink/gstqtvideosinkplugin.cpp \
$$PWD/gstqtvideosink/gstqwidgetvideosink.cpp \
$$PWD/gstqtvideosink/painters/genericsurfacepainter.cpp \
$$PWD/gstqtvideosink/painters/openglsurfacepainter.cpp \
$$PWD/gstqtvideosink/painters/videomaterial.cpp \
$$PWD/gstqtvideosink/painters/videonode.cpp \
$$PWD/gstqtvideosink/utils/bufferformat.cpp \
$$PWD/gstqtvideosink/utils/utils.cpp \
} else {
message("Skipping support for video streaming (Unsupported platform)")
}
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009, 2015 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/**
* @file
* @brief QGC Video Surface
* @author Gus Grubba <mavlink@grubba.com>
*/
#include "videosurface_p.h"
#include <QtCore/QDebug>
#include <QtQuick/QQuickItem>
VideoSurface::VideoSurface(QObject *parent)
: QObject(parent)
, _data(new VideoSurfacePrivate)
{
}
VideoSurface::~VideoSurface()
{
if (_data->videoSink != NULL) {
gst_element_set_state(_data->videoSink, GST_STATE_NULL);
}
delete _data;
}
GstElement* VideoSurface::videoSink() const
{
if (_data->videoSink == NULL) {
if ((_data->videoSink = gst_element_factory_make("qtquick2videosink", NULL)) == NULL) {
qCritical("Failed to create qtquick2videosink. Make sure it is installed correctly");
return NULL;
}
g_signal_connect(_data->videoSink, "update", G_CALLBACK(onUpdateThunk), (void* )this);
}
return _data->videoSink;
}
void VideoSurface::onUpdate()
{
Q_FOREACH(QQuickItem *item, _data->items) {
item->update();
}
}
void VideoSurface::onUpdateThunk(GstElement* sink, gpointer data)
{
Q_UNUSED(sink);
VideoSurface* pThis = (VideoSurface* )data;
pThis->onUpdate();
}
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009, 2015 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/**
* @file
* @brief QGC Video Surface
* @author Gus Grubba <mavlink@grubba.com>
*/
#ifndef VIDEO_SURFACE_H
#define VIDEO_SURFACE_H
#include <QtCore/QObject>
#include <gst/gst.h>
class VideoSurfacePrivate;
class VideoSurface : public QObject
{
Q_OBJECT
Q_DISABLE_COPY(VideoSurface)
public:
explicit VideoSurface(QObject *parent = 0);
virtual ~VideoSurface();
/*! Returns the video sink element that provides this surface's image.
* The element will be constructed the first time that this function
* is called. The surface will always keep a reference to this element.
*/
GstElement* videoSink() const;
protected:
void onUpdate();
static void onUpdateThunk(GstElement* sink, gpointer data);
private:
friend class VideoItem;
VideoSurfacePrivate * const _data;
};
Q_DECLARE_METATYPE(VideoSurface*)
#endif // VIDEO_SURFACE_H
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011-2013 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#include "basedelegate.h"
#include <QCoreApplication>
BaseDelegate::BaseDelegate(GstElement * sink, QObject * parent)
: QObject(parent)
, m_colorsDirty(true)
, m_brightness(0)
, m_contrast(0)
, m_hue(0)
, m_saturation(0)
, m_pixelAspectRatio(1, 1)
, m_forceAspectRatioDirty(true)
, m_forceAspectRatio(false)
, m_formatDirty(true)
, m_isActive(false)
, m_buffer(NULL)
, m_sink(sink)
{
}
BaseDelegate::~BaseDelegate()
{
Q_ASSERT(!isActive());
}
//-------------------------------------
bool BaseDelegate::isActive() const
{
QReadLocker l(&m_isActiveLock);
return m_isActive;
}
void BaseDelegate::setActive(bool active)
{
GST_INFO_OBJECT(m_sink, active ? "Activating" : "Deactivating");
QWriteLocker l(&m_isActiveLock);
m_isActive = active;
if (!active) {
QCoreApplication::postEvent(this, new DeactivateEvent());
}
}
//-------------------------------------
int BaseDelegate::brightness() const
{
QReadLocker l(&m_colorsLock);
return m_brightness;
}
void BaseDelegate::setBrightness(int brightness)
{
QWriteLocker l(&m_colorsLock);
m_brightness = qBound(-100, brightness, 100);
m_colorsDirty = true;
}
int BaseDelegate::contrast() const
{
QReadLocker l(&m_colorsLock);
return m_contrast;
}
void BaseDelegate::setContrast(int contrast)
{
QWriteLocker l(&m_colorsLock);
m_contrast = qBound(-100, contrast, 100);
m_colorsDirty = true;
}
int BaseDelegate::hue() const
{
QReadLocker l(&m_colorsLock);
return m_hue;
}
void BaseDelegate::setHue(int hue)
{
QWriteLocker l(&m_colorsLock);
m_hue = qBound(-100, hue, 100);
m_colorsDirty = true;
}
int BaseDelegate::saturation() const
{
QReadLocker l(&m_colorsLock);
return m_saturation;
}
void BaseDelegate::setSaturation(int saturation)
{
QWriteLocker l(&m_colorsLock);
m_saturation = qBound(-100, saturation, 100);
m_colorsDirty = true;
}
//-------------------------------------
Fraction BaseDelegate::pixelAspectRatio() const
{
QReadLocker l(&m_pixelAspectRatioLock);
return m_pixelAspectRatio;
}
void BaseDelegate::setPixelAspectRatio(const Fraction & f)
{
QWriteLocker l(&m_pixelAspectRatioLock);
m_pixelAspectRatio = f;
}
//-------------------------------------
bool BaseDelegate::forceAspectRatio() const
{
QReadLocker l(&m_forceAspectRatioLock);
return m_forceAspectRatio;
}
void BaseDelegate::setForceAspectRatio(bool force)
{
QWriteLocker l(&m_forceAspectRatioLock);
if (m_forceAspectRatio != force) {
m_forceAspectRatio = force;
m_forceAspectRatioDirty = true;
}
}
//-------------------------------------
bool BaseDelegate::event(QEvent *event)
{
switch((int) event->type()) {
case BufferEventType:
{
BufferEvent *bufEvent = dynamic_cast<BufferEvent*>(event);
Q_ASSERT(bufEvent);
GST_TRACE_OBJECT(m_sink, "Received buffer %"GST_PTR_FORMAT, bufEvent->buffer);
if (isActive()) {
gst_buffer_replace (&m_buffer, bufEvent->buffer);
update();
}
return true;
}
case BufferFormatEventType:
{
BufferFormatEvent *bufFmtEvent = dynamic_cast<BufferFormatEvent*>(event);
Q_ASSERT(bufFmtEvent);
GST_TRACE_OBJECT (m_sink, "Received buffer format event. New format: %s",
gst_video_format_to_string(bufFmtEvent->format.videoFormat()));
m_formatDirty = true;
m_bufferFormat = bufFmtEvent->format;
return true;
}
case DeactivateEventType:
{
GST_LOG_OBJECT(m_sink, "Received deactivate event");
gst_buffer_replace (&m_buffer, NULL);
update();
return true;
}
default:
return QObject::event(event);
}
}
void BaseDelegate::update()
{
g_signal_emit_by_name(m_sink, "update");
}
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011-2013 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#ifndef BASEDELEGATE_H
#define BASEDELEGATE_H
#include <gst/gst.h>
#include "../gstqtvideosinkplugin.h" //for debug category
#include "../utils/bufferformat.h"
#include "../utils/utils.h"
#include <QObject>
#include <QEvent>
#include <QReadWriteLock>
class BaseDelegate : public QObject
{
Q_OBJECT
public:
enum EventType {
BufferEventType = QEvent::User,
BufferFormatEventType,
DeactivateEventType
};
//-------------------------------------
class BufferEvent : public QEvent
{
public:
inline BufferEvent(GstBuffer *buf)
: QEvent(static_cast<QEvent::Type>(BufferEventType)),
buffer(gst_buffer_ref(buf))
{}
virtual ~BufferEvent() {
gst_buffer_unref(buffer);
}
GstBuffer *buffer;
};
class BufferFormatEvent : public QEvent
{
public:
inline BufferFormatEvent(const BufferFormat &format)
: QEvent(static_cast<QEvent::Type>(BufferFormatEventType)),
format(format)
{}
BufferFormat format;
};
class DeactivateEvent : public QEvent
{
public:
inline DeactivateEvent()
: QEvent(static_cast<QEvent::Type>(DeactivateEventType))
{
}
};
//-------------------------------------
explicit BaseDelegate(GstElement *sink, QObject *parent = 0);
virtual ~BaseDelegate();
bool isActive() const;
void setActive(bool playing);
// GstColorBalance interface
int brightness() const;
void setBrightness(int brightness);
int contrast() const;
void setContrast(int contrast);
int hue() const;
void setHue(int hue);
int saturation() const;
void setSaturation(int saturation);
// pixel-aspect-ratio property
Fraction pixelAspectRatio() const;
void setPixelAspectRatio(const Fraction & f);
// force-aspect-ratio property
bool forceAspectRatio() const;
void setForceAspectRatio(bool force);
protected:
// internal event handling
virtual bool event(QEvent *event);
// tells the surface to repaint itself
virtual void update();
protected:
// colorbalance interface properties
mutable QReadWriteLock m_colorsLock;
bool m_colorsDirty;
int m_brightness;
int m_contrast;
int m_hue;
int m_saturation;
// pixel-aspect-ratio property
mutable QReadWriteLock m_pixelAspectRatioLock;
Fraction m_pixelAspectRatio;
// force-aspect-ratio property
mutable QReadWriteLock m_forceAspectRatioLock;
bool m_forceAspectRatioDirty;
bool m_forceAspectRatio;
// format caching
bool m_formatDirty;
BufferFormat m_bufferFormat;
PaintAreas m_areas;
// whether the sink is active (PAUSED or PLAYING)
mutable QReadWriteLock m_isActiveLock;
bool m_isActive;
// the buffer to be drawn next
GstBuffer *m_buffer;
// the video sink element
GstElement * const m_sink;
};
#endif // BASEDELEGATE_H
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011-2013 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#include "qtquick2videosinkdelegate.h"
#include "../painters/videonode.h"
QtQuick2VideoSinkDelegate::QtQuick2VideoSinkDelegate(GstElement *sink, QObject *parent)
: BaseDelegate(sink, parent)
{
}
QSGNode* QtQuick2VideoSinkDelegate::updateNode(QSGNode *node, const QRectF & targetArea)
{
GST_TRACE_OBJECT(m_sink, "updateNode called");
bool sgnodeFormatChanged = false;
VideoNode *vnode = dynamic_cast<VideoNode*>(node);
if (!vnode) {
GST_INFO_OBJECT(m_sink, "creating new VideoNode");
vnode = new VideoNode;
}
if (!m_buffer) {
if (vnode->materialType() != VideoNode::MaterialTypeSolidBlack) {
vnode->setMaterialTypeSolidBlack();
sgnodeFormatChanged = true;
}
if (sgnodeFormatChanged || targetArea != m_areas.targetArea) {
m_areas.targetArea = targetArea;
vnode->updateGeometry(m_areas);
}
} else {
//change format before geometry, so that we change QSGGeometry as well
if (m_formatDirty) {
vnode->changeFormat(m_bufferFormat);
sgnodeFormatChanged = true;
}
//recalculate the video area if needed
QReadLocker forceAspectRatioLocker(&m_forceAspectRatioLock);
if (sgnodeFormatChanged || targetArea != m_areas.targetArea || m_forceAspectRatioDirty) {
m_forceAspectRatioDirty = false;
QReadLocker pixelAspectRatioLocker(&m_pixelAspectRatioLock);
Qt::AspectRatioMode aspectRatioMode = m_forceAspectRatio ?
Qt::KeepAspectRatio : Qt::IgnoreAspectRatio;
m_areas.calculate(targetArea, m_bufferFormat.frameSize(),
m_bufferFormat.pixelAspectRatio(), m_pixelAspectRatio,
aspectRatioMode);
pixelAspectRatioLocker.unlock();
GST_LOG_OBJECT(m_sink,
"Recalculated paint areas: "
"Frame size: " QSIZE_FORMAT ", "
"target area: " QRECTF_FORMAT ", "
"video area: " QRECTF_FORMAT ", "
"black1: " QRECTF_FORMAT ", "
"black2: " QRECTF_FORMAT,
QSIZE_FORMAT_ARGS(m_bufferFormat.frameSize()),
QRECTF_FORMAT_ARGS(m_areas.targetArea),
QRECTF_FORMAT_ARGS(m_areas.videoArea),
QRECTF_FORMAT_ARGS(m_areas.blackArea1),
QRECTF_FORMAT_ARGS(m_areas.blackArea2)
);
vnode->updateGeometry(m_areas);
}
forceAspectRatioLocker.unlock();
if (m_formatDirty) {
m_formatDirty = false;
//make sure to update the colors after changing material
m_colorsDirty = true;
}
QReadLocker colorsLocker(&m_colorsLock);
if (m_colorsDirty) {
vnode->updateColors(m_brightness, m_contrast, m_hue, m_saturation);
m_colorsDirty = false;
}
colorsLocker.unlock();
vnode->setCurrentFrame(m_buffer);
}
return vnode;
}
/*
Copyright (C) 2013 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#ifndef QTQUICK2VIDEOSINKDELEGATE_H
#define QTQUICK2VIDEOSINKDELEGATE_H
#include "basedelegate.h"
#include <QtQuick/QSGNode>
class QtQuick2VideoSinkDelegate : public BaseDelegate
{
Q_OBJECT
public:
explicit QtQuick2VideoSinkDelegate(GstElement * sink, QObject * parent = 0);
QSGNode *updateNode(QSGNode *node, const QRectF & targetArea);
};
#endif // QTQUICK2VIDEOSINKDELEGATE_H
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#include "qtvideosinkdelegate.h"
#include "../painters/genericsurfacepainter.h"
#include "../painters/openglsurfacepainter.h"
#include <QStack>
#include <QPainter>
QtVideoSinkDelegate::QtVideoSinkDelegate(GstElement *sink, QObject *parent)
: BaseDelegate(sink, parent)
, m_painter(0)
, m_supportedPainters(Generic)
#ifndef GST_QT_VIDEO_SINK_NO_OPENGL
, m_glContext(0)
#endif
{
}
QtVideoSinkDelegate::~QtVideoSinkDelegate()
{
destroyPainter();
}
void QtVideoSinkDelegate::paint(QPainter *painter, const QRectF & targetArea)
{
GST_TRACE_OBJECT(m_sink, "paint called");
#ifndef GST_QT_VIDEO_SINK_NO_OPENGL
if (m_glContext) {
Q_ASSERT_X(m_glContext == QGLContext::currentContext(),
"qtvideosink - paint",
"Please use a QPainter that is initialized to paint on the "
"GL surface that has the same context as the one given on the glcontext property"
);
}
#endif
if (!m_buffer) {
painter->fillRect(targetArea, Qt::black);
} else {
//recalculate the video area if needed
QReadLocker forceAspectRatioLocker(&m_forceAspectRatioLock);
if (targetArea != m_areas.targetArea || m_formatDirty
|| m_forceAspectRatioDirty)
{
m_forceAspectRatioDirty = false;
QReadLocker pixelAspectRatioLocker(&m_pixelAspectRatioLock);
Qt::AspectRatioMode aspectRatioMode = m_forceAspectRatio ?
Qt::KeepAspectRatio : Qt::IgnoreAspectRatio;
m_areas.calculate(targetArea, m_bufferFormat.frameSize(),
m_bufferFormat.pixelAspectRatio(), m_pixelAspectRatio,
aspectRatioMode);
pixelAspectRatioLocker.unlock();
GST_LOG_OBJECT(m_sink,
"Recalculated paint areas: "
"Frame size: " QSIZE_FORMAT ", "
"target area: " QRECTF_FORMAT ", "
"video area: " QRECTF_FORMAT ", "
"black1: " QRECTF_FORMAT ", "
"black2: " QRECTF_FORMAT,
QSIZE_FORMAT_ARGS(m_bufferFormat.frameSize()),
QRECTF_FORMAT_ARGS(m_areas.targetArea),
QRECTF_FORMAT_ARGS(m_areas.videoArea),
QRECTF_FORMAT_ARGS(m_areas.blackArea1),
QRECTF_FORMAT_ARGS(m_areas.blackArea2)
);
}
forceAspectRatioLocker.unlock();
//if either pixelFormat or frameSize have changed, we need to reset the painter
//and/or change painter, in case the current one does not handle the requested format
if ((m_formatDirty) || !m_painter)
{
changePainter(m_bufferFormat);
m_formatDirty = false;
//make sure to update the colors after changing painter
m_colorsDirty = true;
}
if (G_LIKELY(m_painter)) {
QReadLocker colorsLocker(&m_colorsLock);
if (m_colorsDirty) {
m_painter->updateColors(m_brightness, m_contrast, m_hue, m_saturation);
m_colorsDirty = false;
}
colorsLocker.unlock();
GstMapInfo mem_info;
if (gst_buffer_map(m_buffer, &mem_info, GST_MAP_READ)) {
m_painter->paint(mem_info.data, m_bufferFormat, painter, m_areas);
gst_buffer_unmap(m_buffer, &mem_info);
}
}
}
}
#ifndef GST_QT_VIDEO_SINK_NO_OPENGL
QGLContext *QtVideoSinkDelegate::glContext() const
{
return m_glContext;
}
void QtVideoSinkDelegate::setGLContext(QGLContext *context)
{
if (m_glContext == context)
return;
m_glContext = context;
m_supportedPainters = Generic;
if (m_glContext) {
m_glContext->makeCurrent();
const QByteArray extensions(reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS)));
GST_LOG_OBJECT(m_sink, "Available GL extensions: %s", extensions.constData());
#ifndef QT_OPENGL_ES
if (extensions.contains("ARB_fragment_program"))
m_supportedPainters |= ArbFp;
#endif
#ifndef QT_OPENGL_ES_2
if (QGLShaderProgram::hasOpenGLShaderPrograms(m_glContext)
&& extensions.contains("ARB_shader_objects"))
#endif
m_supportedPainters |= Glsl;
}
GST_LOG_OBJECT(m_sink, "Done setting GL context. m_supportedPainters=%x", (int) m_supportedPainters);
}
#endif
void QtVideoSinkDelegate::changePainter(const BufferFormat & format)
{
if (m_painter) {
m_painter->cleanup();
if (G_UNLIKELY(!m_painter->supportsFormat(format.videoFormat()))) {
destroyPainter();
}
}
QStack<PainterType> possiblePainters;
if (GenericSurfacePainter::supportedPixelFormats().contains(format.videoFormat())) {
possiblePainters.push(Generic);
}
#ifndef GST_QT_VIDEO_SINK_NO_OPENGL
if (OpenGLSurfacePainter::supportedPixelFormats().contains(format.videoFormat())) {
if (m_supportedPainters & ArbFp) {
possiblePainters.push(ArbFp);
}
if (m_supportedPainters & Glsl) {
possiblePainters.push(Glsl);
}
}
#endif
while (!possiblePainters.isEmpty()) {
if (!m_painter) {
PainterType type = possiblePainters.pop();
switch(type) {
#ifndef GST_QT_VIDEO_SINK_NO_OPENGL
case Glsl:
GST_LOG_OBJECT(m_sink, "Creating GLSL painter");
m_painter = new GlslSurfacePainter;
break;
# ifndef QT_OPENGL_ES
case ArbFp:
GST_LOG_OBJECT(m_sink, "Creating ARB Fragment Shader painter");
m_painter = new ArbFpSurfacePainter;
break;
# endif
#endif
case Generic:
GST_LOG_OBJECT(m_sink, "Creating Generic painter");
m_painter = new GenericSurfacePainter;
break;
default:
Q_ASSERT(false);
}
}
try {
m_painter->init(format);
return;
} catch (const QString & error) {
GST_ELEMENT_WARNING(m_sink, RESOURCE, FAILED,
("Failed to start painter"), ("%s", error.toUtf8().constData()));
delete m_painter;
m_painter = 0;
}
}
GST_ELEMENT_ERROR(m_sink, RESOURCE, FAILED,
("Failed to create a painter for the given format"), (NULL));
}
void QtVideoSinkDelegate::destroyPainter()
{
GST_LOG_OBJECT(m_sink, "Destroying painter");
delete m_painter;
m_painter = 0;
}
bool QtVideoSinkDelegate::event(QEvent *event)
{
if (event->type() == (QEvent::Type)DeactivateEventType) {
if (m_painter) {
m_painter->cleanup();
destroyPainter();
}
}
return BaseDelegate::event(event);
}
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#ifndef QT_VIDEO_SINK_DELEGATE_H
#define QT_VIDEO_SINK_DELEGATE_H
#include "basedelegate.h"
#include "../painters/abstractsurfacepainter.h"
class QGLContext;
class QtVideoSinkDelegate : public BaseDelegate
{
Q_OBJECT
public:
enum PainterType {
Generic = 0x00,
ArbFp = 0x01,
Glsl = 0x02
};
Q_DECLARE_FLAGS(PainterTypes, PainterType);
explicit QtVideoSinkDelegate(GstElement *sink, QObject *parent = 0);
virtual ~QtVideoSinkDelegate();
PainterTypes supportedPainterTypes() const { return m_supportedPainters; }
#ifndef GST_QT_VIDEO_SINK_NO_OPENGL
// glcontext property
QGLContext *glContext() const;
void setGLContext(QGLContext *context);
#endif
// paint action
void paint(QPainter *painter, const QRectF & targetArea);
protected:
// internal event handling
virtual bool event(QEvent *event);
private:
void changePainter(const BufferFormat & format);
void destroyPainter();
AbstractSurfacePainter *m_painter;
PainterTypes m_supportedPainters;
#ifndef GST_QT_VIDEO_SINK_NO_OPENGL
QGLContext *m_glContext;
#endif
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QtVideoSinkDelegate::PainterTypes)
#endif // QT_VIDEO_SINK_DELEGATE_H
/*
Copyright (C) 2010 George Kiagiadakis <kiagiadakis.george@gmail.com>
Copyright (C) 2012 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#include "qwidgetvideosinkdelegate.h"
#include <QPainter>
QWidgetVideoSinkDelegate::QWidgetVideoSinkDelegate(GstElement * sink, QObject * parent)
: QtVideoSinkDelegate(sink, parent)
{
}
QWidgetVideoSinkDelegate::~QWidgetVideoSinkDelegate()
{
setWidget(NULL);
}
QWidget *QWidgetVideoSinkDelegate::widget() const
{
return m_widget.data();
}
void QWidgetVideoSinkDelegate::setWidget(QWidget *widget)
{
GST_LOG_OBJECT(m_sink, "Setting \"widget\" property to %"GST_PTR_FORMAT, widget);
if (m_widget) {
m_widget.data()->removeEventFilter(this);
m_widget.data()->setAttribute(Qt::WA_OpaquePaintEvent, m_opaquePaintEventAttribute);
m_widget.data()->update();
m_widget = NULL;
}
if (widget) {
widget->installEventFilter(this);
m_opaquePaintEventAttribute = widget->testAttribute(Qt::WA_OpaquePaintEvent);
widget->setAttribute(Qt::WA_OpaquePaintEvent, true);
widget->update();
m_widget = widget;
}
}
bool QWidgetVideoSinkDelegate::eventFilter(QObject *filteredObject, QEvent *event)
{
if (filteredObject == m_widget.data()) {
switch(event->type()) {
case QEvent::Paint:
{
QPainter painter(m_widget.data());
paint(&painter, m_widget.data()->rect());
return true;
}
default:
return false;
}
} else {
return QtVideoSinkDelegate::eventFilter(filteredObject, event);
}
}
void QWidgetVideoSinkDelegate::update()
{
if (m_widget) {
m_widget.data()->update();
}
}
/*
Copyright (C) 2010 George Kiagiadakis <kiagiadakis.george@gmail.com>
Copyright (C) 2012 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#ifndef QWIDGET_VIDEO_SINK_DELEGATE_H
#define QWIDGET_VIDEO_SINK_DELEGATE_H
#include "qtvideosinkdelegate.h"
#include <QEvent>
#include <QPointer>
#include <QWidget>
class QWidgetVideoSinkDelegate : public QtVideoSinkDelegate
{
Q_OBJECT
public:
explicit QWidgetVideoSinkDelegate(GstElement * sink, QObject * parent = 0);
virtual ~QWidgetVideoSinkDelegate();
// "widget" property
QWidget *widget() const;
void setWidget(QWidget *widget);
protected:
virtual bool eventFilter(QObject *filteredObject, QEvent *event);
virtual void update();
private:
// "widget" property
QPointer<QWidget> m_widget;
// original value of the Qt::WA_OpaquePaintEvent attribute
bool m_opaquePaintEventAttribute;
};
#endif // QWIDGET_VIDEO_SINK_DELEGATE_H
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011-2012 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#include "gstqtglvideosink.h"
#include "gstqtvideosinkmarshal.h"
#include "delegates/qtvideosinkdelegate.h"
guint GstQtGLVideoSink::s_signals[];
DEFINE_TYPE(GstQtGLVideoSink, GST_TYPE_QT_GL_VIDEO_SINK_BASE)
//------------------------------
void GstQtGLVideoSink::emit_update(gpointer sink)
{
g_signal_emit(sink, GstQtGLVideoSink::s_signals[UPDATE_SIGNAL], 0, NULL);
}
//------------------------------
void GstQtGLVideoSink::base_init(gpointer g_class)
{
GstElementClass *element_class = GST_ELEMENT_CLASS(g_class);
gst_element_class_set_details_simple(element_class, "Qt GL video sink", "Sink/Video",
"A video sink that can draw on any Qt GL surface",
"George Kiagiadakis <george.kiagiadakis@collabora.com>");
}
void GstQtGLVideoSink::class_init(gpointer g_class, gpointer class_data)
{
Q_UNUSED(class_data);
GObjectClass *object_class = G_OBJECT_CLASS(g_class);
object_class->set_property = GstQtGLVideoSink::set_property;
GstQtGLVideoSinkClass *qt_video_sink_class = reinterpret_cast<GstQtGLVideoSinkClass*>(g_class);
qt_video_sink_class->paint = GstQtGLVideoSink::paint;
/**
* GstQtGLVideoSink::paint
* @painter: A valid QPainter pointer that will be used to paint the video
* @x: The x coordinate of the target area rectangle
* @y: The y coordinate of the target area rectangle
* @width: The width of the target area rectangle
* @height: The height of the target area rectangle
*
* This is an action signal that you can call from your Qt surface class inside
* its paint function to render the video. It takes a QPainter* and the target
* area rectangle as arguments. You should schedule to call this function to
* repaint the surface whenever the ::update signal is emited.
*
* Note that the x,y,width and height arguments are actually qreal. This means
* that on architectures like arm they will be float instead of double. You should
* cast the arguments to qreal if they are not already when emitting this signal.
*/
s_signals[PAINT_SIGNAL] =
g_signal_new("paint", G_TYPE_FROM_CLASS(g_class),
static_cast<GSignalFlags>(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
G_STRUCT_OFFSET(GstQtGLVideoSinkClass, paint),
NULL, NULL,
qRealIsDouble() ?
g_cclosure_user_marshal_VOID__POINTER_DOUBLE_DOUBLE_DOUBLE_DOUBLE :
g_cclosure_user_marshal_VOID__POINTER_FLOAT_FLOAT_FLOAT_FLOAT,
G_TYPE_NONE, 5,
G_TYPE_POINTER, G_TYPE_QREAL, G_TYPE_QREAL, G_TYPE_QREAL, G_TYPE_QREAL);
/**
* GstQtGLVideoSink::update
*
* This signal is emited when the surface should be repainted. It should
* be connected to QWidget::update() or QGraphicsItem::update() or any
* other similar function in your surface.
*/
s_signals[UPDATE_SIGNAL] =
g_signal_new("update", G_TYPE_FROM_CLASS(g_class),
G_SIGNAL_RUN_LAST,
0, NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
/**
* GstQtGLVideoSink::glcontext
*
* This property holds a pointer to the QGLContext that will be used to render
* the video using OpenGL acceleration. You must set this to a valid QGLContext
* pointer before the element changes state to READY, or else the state change will fail.
**/
g_object_class_install_property(object_class, PROP_GLCONTEXT,
g_param_spec_pointer("glcontext", "GL context",
"The QGLContext that will be used to do OpenGL-accelerated rendering",
static_cast<GParamFlags>(G_PARAM_WRITABLE)));
}
void GstQtGLVideoSink::init(GTypeInstance *instance, gpointer g_class)
{
Q_UNUSED(g_class);
GstQtVideoSinkBase *sinkBase = GST_QT_VIDEO_SINK_BASE(instance);
sinkBase->delegate = new QtVideoSinkDelegate(GST_ELEMENT(sinkBase));
}
//------------------------------
void GstQtGLVideoSink::set_property(GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec)
{
GstQtVideoSinkBase *sinkBase = GST_QT_VIDEO_SINK_BASE(object);
switch (prop_id) {
case PROP_GLCONTEXT:
sinkBase->delegate->setGLContext(static_cast<QGLContext*>(g_value_get_pointer(value)));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
}
}
//------------------------------
void GstQtGLVideoSink::paint(GstQtGLVideoSink *sink, gpointer painter,
qreal x, qreal y, qreal width, qreal height)
{
GST_QT_VIDEO_SINK_BASE(sink)->delegate->paint(static_cast<QPainter*>(painter),
QRectF(x, y, width, height));
}
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011-2012 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#ifndef GST_QT_GL_VIDEO_SINK_H
#define GST_QT_GL_VIDEO_SINK_H
#include "gstqtglvideosinkbase.h"
#ifndef GST_QT_VIDEO_SINK_NO_OPENGL
#define GST_TYPE_QT_GL_VIDEO_SINK \
(GstQtGLVideoSink::get_type())
struct GstQtGLVideoSink
{
public:
GstQtGLVideoSinkBase parent;
static GType get_type();
static void emit_update(gpointer sink);
private:
enum {
PROP_0,
PROP_GLCONTEXT
};
enum {
PAINT_SIGNAL,
UPDATE_SIGNAL,
LAST_SIGNAL
};
static void base_init(gpointer g_class);
static void class_init(gpointer g_class, gpointer class_data);
static void init(GTypeInstance *instance, gpointer g_class);
static void set_property(GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec);
static void paint(GstQtGLVideoSink *sink, gpointer painter,
qreal x, qreal y, qreal width, qreal height);
static guint s_signals[LAST_SIGNAL];
};
struct GstQtGLVideoSinkClass
{
GstQtGLVideoSinkBaseClass parent_class;
/* paint action signal */
void (*paint) (GstQtGLVideoSink *sink, gpointer painter,
qreal x, qreal y, qreal width, qreal height);
};
#endif // GST_QT_VIDEO_SINK_NO_OPENGL
#endif // GST_QT_GL_VIDEO_SINK_H
This diff is collapsed.
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011-2012 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#ifndef GST_QT_GL_VIDEO_SINK_BASE_H
#define GST_QT_GL_VIDEO_SINK_BASE_H
#include "gstqtvideosinkbase.h"
#include <gst/video/colorbalance.h>
#ifndef GST_QT_VIDEO_SINK_NO_OPENGL
#define GST_TYPE_QT_GL_VIDEO_SINK_BASE \
(GstQtGLVideoSinkBase::get_type())
#define GST_QT_GL_VIDEO_SINK_BASE(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_QT_GL_VIDEO_SINK_BASE, GstQtGLVideoSinkBase))
struct GstQtGLVideoSinkBase
{
public:
GstQtVideoSinkBase parent;
static GType get_type();
private:
enum {
PROP_0,
PROP_CONTRAST,
PROP_BRIGHTNESS,
PROP_HUE,
PROP_SATURATION
};
//index for s_colorbalance_labels
enum {
LABEL_CONTRAST = 0,
LABEL_BRIGHTNESS,
LABEL_HUE,
LABEL_SATURATION,
LABEL_LAST
};
static void init_interfaces(GType type);
static void base_init(gpointer g_class);
static void class_init(gpointer g_class, gpointer class_data);
static void init(GTypeInstance *instance, gpointer g_class);
static void finalize(GObject *object);
static void colorbalance_init(GstColorBalanceInterface *balance_interface, gpointer data);
static const GList *colorbalance_list_channels(GstColorBalance *balance);
static void colorbalance_set_value(GstColorBalance *balance,
GstColorBalanceChannel *channel,
gint value);
static gint colorbalance_get_value(GstColorBalance *balance,
GstColorBalanceChannel *channel);
static GstColorBalanceType colorbalance_get_balance_type(GstColorBalance *balance);
static void set_property(GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec);
static void get_property(GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec);
static gboolean start(GstBaseSink *sink);
static gboolean set_caps(GstBaseSink *sink, GstCaps *caps);
GList *m_channels_list;
static const char * const s_colorbalance_labels[];
static GstQtVideoSinkBaseClass *s_parent_class;
};
struct GstQtGLVideoSinkBaseClass
{
GstQtVideoSinkBaseClass parent_class;
};
#endif // GST_QT_VIDEO_SINK_NO_OPENGL
#endif // GST_QT_GL_VIDEO_SINK_BASE_H
This diff is collapsed.
/*
Copyright (C) 2013 Collabora Ltd.
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#ifndef __GST_QT_QUICK2_VIDEO_SINK_H__
#define __GST_QT_QUICK2_VIDEO_SINK_H__
#include <gst/video/gstvideosink.h>
#include <QtGlobal>
#define GST_TYPE_QT_QUICK2_VIDEO_SINK \
(gst_qt_quick2_video_sink_get_type ())
#define GST_QT_QUICK2_VIDEO_SINK(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_QT_QUICK2_VIDEO_SINK, GstQtQuick2VideoSink))
#define GST_IS_QT_QUICK2_VIDEO_SINK(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_QT_QUICK2_VIDEO_SINK))
#define GST_QT_QUICK2_VIDEO_SINK_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_QT_QUICK2_VIDEO_SINK, GstQtQuick2VideoSinkClass))
#define GST_IS_QT_QUICK2_VIDEO_SINK_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_QT_QUICK2_VIDEO_SINK))
#define GST_QT_QUICK2_VIDEO_SINK_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_QT_QUICK2_VIDEO_SINK, GstQtQuick2VideoSinkClass))
typedef struct _GstQtQuick2VideoSink GstQtQuick2VideoSink;
typedef struct _GstQtQuick2VideoSinkClass GstQtQuick2VideoSinkClass;
typedef struct _GstQtQuick2VideoSinkPrivate GstQtQuick2VideoSinkPrivate;
struct _GstQtQuick2VideoSink
{
GstVideoSink parent_instance;
GstQtQuick2VideoSinkPrivate *priv;
};
struct _GstQtQuick2VideoSinkClass
{
GstVideoSinkClass parent_class;
gpointer (*update_node)(GstQtQuick2VideoSink *self,
gpointer node, qreal x, qreal y, qreal w, qreal h);
};
GType gst_qt_quick2_video_sink_get_type (void);
#endif /* __GST_QT_QUICK2_VIDEO_SINK_H__ */
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011-2012 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#include "gstqtvideosink.h"
#include "gstqtvideosinkmarshal.h"
#include "delegates/qtvideosinkdelegate.h"
guint GstQtVideoSink::s_signals[];
DEFINE_TYPE(GstQtVideoSink, GST_TYPE_QT_VIDEO_SINK_BASE)
//------------------------------
void GstQtVideoSink::emit_update(gpointer sink)
{
g_signal_emit(sink, GstQtVideoSink::s_signals[UPDATE_SIGNAL], 0, NULL);
}
//------------------------------
void GstQtVideoSink::base_init(gpointer g_class)
{
GstElementClass *element_class = GST_ELEMENT_CLASS(g_class);
gst_element_class_set_details_simple(element_class, "Qt video sink", "Sink/Video",
"A video sink that can draw on any Qt surface",
"George Kiagiadakis <george.kiagiadakis@collabora.com>");
}
void GstQtVideoSink::class_init(gpointer g_class, gpointer class_data)
{
Q_UNUSED(class_data);
GstQtVideoSinkClass *qt_video_sink_class = reinterpret_cast<GstQtVideoSinkClass*>(g_class);
qt_video_sink_class->paint = GstQtVideoSink::paint;
/**
* GstQtVideoSink::paint
* @painter: A valid QPainter pointer that will be used to paint the video
* @x: The x coordinate of the target area rectangle
* @y: The y coordinate of the target area rectangle
* @width: The width of the target area rectangle
* @height: The height of the target area rectangle
*
* This is an action signal that you can call from your Qt surface class inside
* its paint function to render the video. It takes a QPainter* and the target
* area rectangle as arguments. You should schedule to call this function to
* repaint the surface whenever the ::update signal is emited.
*
* Note that the x,y,width and height arguments are actually qreal. This means
* that on architectures like arm they will be float instead of double. You should
* cast the arguments to qreal if they are not already when emitting this signal.
*/
s_signals[PAINT_SIGNAL] =
g_signal_new("paint", G_TYPE_FROM_CLASS(g_class),
static_cast<GSignalFlags>(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
G_STRUCT_OFFSET(GstQtVideoSinkClass, paint),
NULL, NULL,
qRealIsDouble() ?
g_cclosure_user_marshal_VOID__POINTER_DOUBLE_DOUBLE_DOUBLE_DOUBLE :
g_cclosure_user_marshal_VOID__POINTER_FLOAT_FLOAT_FLOAT_FLOAT,
G_TYPE_NONE, 5,
G_TYPE_POINTER, G_TYPE_QREAL, G_TYPE_QREAL, G_TYPE_QREAL, G_TYPE_QREAL);
/**
* GstQtVideoSink::update
*
* This signal is emited when the surface should be repainted. It should
* be connected to QWidget::update() or QGraphicsItem::update() or any
* other similar function in your surface.
*/
s_signals[UPDATE_SIGNAL] =
g_signal_new("update", G_TYPE_FROM_CLASS(g_class),
G_SIGNAL_RUN_LAST,
0, NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
}
void GstQtVideoSink::init(GTypeInstance *instance, gpointer g_class)
{
Q_UNUSED(g_class);
GstQtVideoSinkBase *sinkBase = GST_QT_VIDEO_SINK_BASE(instance);
sinkBase->delegate = new QtVideoSinkDelegate(GST_ELEMENT(sinkBase));
}
//------------------------------
void GstQtVideoSink::paint(GstQtVideoSink *sink, gpointer painter,
qreal x, qreal y, qreal width, qreal height)
{
GST_QT_VIDEO_SINK_BASE(sink)->delegate->paint(static_cast<QPainter*>(painter),
QRectF(x, y, width, height));
}
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011-2012 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#ifndef GST_QT_VIDEO_SINK_H
#define GST_QT_VIDEO_SINK_H
#include "gstqtvideosinkbase.h"
#define GST_TYPE_QT_VIDEO_SINK \
(GstQtVideoSink::get_type())
struct GstQtVideoSink
{
public:
GstQtVideoSinkBase parent;
static GType get_type();
static void emit_update(gpointer sink);
private:
enum {
PAINT_SIGNAL,
UPDATE_SIGNAL,
LAST_SIGNAL
};
static void base_init(gpointer g_class);
static void class_init(gpointer g_class, gpointer class_data);
static void init(GTypeInstance *instance, gpointer g_class);
static void paint(GstQtVideoSink *sink, gpointer painter,
qreal x, qreal y, qreal width, qreal height);
static guint s_signals[LAST_SIGNAL];
};
struct GstQtVideoSinkClass
{
GstQtVideoSinkBaseClass parent_class;
/* paint action signal */
void (*paint) (GstQtVideoSink *sink, gpointer painter,
qreal x, qreal y, qreal width, qreal height);
};
#endif
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011-2012 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#include "gstqtvideosinkbase.h"
#include "delegates/qtvideosinkdelegate.h"
#include "painters/genericsurfacepainter.h"
#include <cstring>
#include <QCoreApplication>
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
# define CAPS_FORMATS "{ ARGB, xRGB, RGB, RGB16 }"
#else
# define CAPS_FORMATS "{ BGRA, BGRx, RGB, RGB16 }"
#endif
GstVideoSinkClass *GstQtVideoSinkBase::s_parent_class = NULL;
DEFINE_TYPE(GstQtVideoSinkBase, GST_TYPE_VIDEO_SINK)
//------------------------------
void GstQtVideoSinkBase::base_init(gpointer g_class)
{
GstElementClass *element_class = GST_ELEMENT_CLASS(g_class);
static GstStaticPadTemplate sink_pad_template =
GST_STATIC_PAD_TEMPLATE("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE (CAPS_FORMATS))
);
gst_element_class_add_pad_template(
element_class, gst_static_pad_template_get(&sink_pad_template));
}
void GstQtVideoSinkBase::class_init(gpointer g_class, gpointer class_data)
{
Q_UNUSED(class_data);
s_parent_class = reinterpret_cast<GstVideoSinkClass*>(g_type_class_peek_parent(g_class));
GObjectClass *object_class = G_OBJECT_CLASS(g_class);
object_class->finalize = GstQtVideoSinkBase::finalize;
object_class->set_property = GstQtVideoSinkBase::set_property;
object_class->get_property = GstQtVideoSinkBase::get_property;
GstElementClass *element_class = GST_ELEMENT_CLASS(g_class);
element_class->change_state = GstQtVideoSinkBase::change_state;
GstBaseSinkClass *base_sink_class = GST_BASE_SINK_CLASS(g_class);
base_sink_class->set_caps = GstQtVideoSinkBase::set_caps;
GstVideoSinkClass *video_sink_class = GST_VIDEO_SINK_CLASS(g_class);
video_sink_class->show_frame = GstQtVideoSinkBase::show_frame;
/**
* GstQtVideoSinkBase::pixel-aspect-ratio
*
* The pixel aspect ratio of the display device.
**/
g_object_class_install_property(object_class, PROP_PIXEL_ASPECT_RATIO,
g_param_spec_string("pixel-aspect-ratio", "Pixel aspect ratio",
"The pixel aspect ratio of the display device",
"1/1", static_cast<GParamFlags>(G_PARAM_READWRITE)));
/**
* GstQtVideoSinkBase::force-aspect-ratio
*
* If set to TRUE, the sink will scale the video respecting its original aspect ratio
* and any remaining space will be filled with black.
* If set to FALSE, the sink will scale the video to fit the whole drawing area.
**/
g_object_class_install_property(object_class, PROP_FORCE_ASPECT_RATIO,
g_param_spec_boolean("force-aspect-ratio", "Force aspect ratio",
"When enabled, scaling will respect original aspect ratio",
FALSE, static_cast<GParamFlags>(G_PARAM_READWRITE)));
}
void GstQtVideoSinkBase::init(GTypeInstance *instance, gpointer g_class)
{
Q_UNUSED(instance);
Q_UNUSED(g_class);
/* sink->delegate is initialized in the subclasses */
}
void GstQtVideoSinkBase::finalize(GObject *object)
{
GstQtVideoSinkBase *sink = GST_QT_VIDEO_SINK_BASE(object);
delete sink->delegate;
sink->delegate = 0;
}
//------------------------------
void GstQtVideoSinkBase::set_property(GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec)
{
GstQtVideoSinkBase *sink = GST_QT_VIDEO_SINK_BASE(object);
switch (prop_id) {
case PROP_PIXEL_ASPECT_RATIO:
{
GValue tmp;
std::memset(&tmp, 0, sizeof(GValue));
g_value_init(&tmp, GST_TYPE_FRACTION);
if (g_value_transform(value, &tmp)) {
int n = gst_value_get_fraction_numerator(&tmp);
int d = gst_value_get_fraction_denominator(&tmp);
sink->delegate->setPixelAspectRatio(Fraction(n, d));
} else {
GST_WARNING_OBJECT(object, "Could not transform string to aspect ratio");
}
g_value_unset(&tmp);
break;
}
case PROP_FORCE_ASPECT_RATIO:
sink->delegate->setForceAspectRatio(g_value_get_boolean(value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
}
}
void GstQtVideoSinkBase::get_property(GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
{
GstQtVideoSinkBase *sink = GST_QT_VIDEO_SINK_BASE(object);
switch (prop_id) {
case PROP_PIXEL_ASPECT_RATIO:
{
GValue tmp;
Fraction par = sink->delegate->pixelAspectRatio();
std::memset(&tmp, 0, sizeof(GValue));
g_value_init(&tmp, GST_TYPE_FRACTION);
gst_value_set_fraction(&tmp, par.numerator, par.denominator);
g_value_transform(&tmp, value);
g_value_unset(&tmp);
break;
}
case PROP_FORCE_ASPECT_RATIO:
g_value_set_boolean(value, sink->delegate->forceAspectRatio());
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
}
}
//------------------------------
GstStateChangeReturn GstQtVideoSinkBase::change_state(GstElement *element, GstStateChange transition)
{
GstQtVideoSinkBase *sink = GST_QT_VIDEO_SINK_BASE(element);
switch (transition) {
case GST_STATE_CHANGE_READY_TO_PAUSED:
sink->delegate->setActive(true);
break;
case GST_STATE_CHANGE_PAUSED_TO_READY:
sink->delegate->setActive(false);
break;
default:
break;
}
return GST_ELEMENT_CLASS(s_parent_class)->change_state(element, transition);
}
//------------------------------
gboolean GstQtVideoSinkBase::set_caps(GstBaseSink *base, GstCaps *caps)
{
GstQtVideoSinkBase *sink = GST_QT_VIDEO_SINK_BASE(base);
GST_LOG_OBJECT(sink, "new caps %" GST_PTR_FORMAT, caps);
BufferFormat format = BufferFormat::fromCaps(caps);
if (GenericSurfacePainter::supportedPixelFormats().contains(format.videoFormat())) {
QCoreApplication::postEvent(sink->delegate,
new BaseDelegate::BufferFormatEvent(format));
return TRUE;
} else {
return FALSE;
}
}
//------------------------------
GstFlowReturn GstQtVideoSinkBase::show_frame(GstVideoSink *video_sink, GstBuffer *buffer)
{
GstQtVideoSinkBase *sink = GST_QT_VIDEO_SINK_BASE(video_sink);
GST_TRACE_OBJECT(sink, "Posting new buffer (%"GST_PTR_FORMAT") for rendering.", buffer);
QCoreApplication::postEvent(sink->delegate, new BaseDelegate::BufferEvent(buffer));
return GST_FLOW_OK;
}
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011-2012 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#ifndef GST_QT_VIDEO_SINK_BASE_H
#define GST_QT_VIDEO_SINK_BASE_H
#include "gstqtvideosinkplugin.h"
#include <gst/video/gstvideosink.h>
#define GST_TYPE_QT_VIDEO_SINK_BASE \
(GstQtVideoSinkBase::get_type())
#define GST_QT_VIDEO_SINK_BASE(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_QT_VIDEO_SINK_BASE, GstQtVideoSinkBase))
#define GST_QT_VIDEO_SINK_BASE_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_QT_VIDEO_SINK_BASE, GstQtVideoSinkBaseClass))
#define GST_QT_VIDEO_SINK_BASE_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_QT_VIDEO_SINK_BASE, GstQtVideoSinkBaseClass))
class QtVideoSinkDelegate;
struct GstQtVideoSinkBase
{
public:
GstVideoSink parent;
static GType get_type();
private:
enum {
PROP_0,
PROP_PIXEL_ASPECT_RATIO,
PROP_FORCE_ASPECT_RATIO,
};
static void base_init(gpointer g_class);
static void class_init(gpointer g_class, gpointer class_data);
static void init(GTypeInstance *instance, gpointer g_class);
static void finalize(GObject *object);
static void set_property(GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec);
static void get_property(GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec);
static GstStateChangeReturn change_state(GstElement *element, GstStateChange transition);
static gboolean set_caps(GstBaseSink *sink, GstCaps *caps);
static GstFlowReturn show_frame(GstVideoSink *sink, GstBuffer *buffer);
public:
QtVideoSinkDelegate *delegate;
private:
static GstVideoSinkClass *s_parent_class;
};
struct GstQtVideoSinkBaseClass
{
GstVideoSinkClass parent_class;
};
#endif
This diff is collapsed.
#ifndef __g_cclosure_user_marshal_MARSHAL_H__
#define __g_cclosure_user_marshal_MARSHAL_H__
#include <glib-object.h>
G_BEGIN_DECLS
/* VOID:POINTER,FLOAT,FLOAT,FLOAT,FLOAT (marshaller.src:1) */
extern void g_cclosure_user_marshal_VOID__POINTER_FLOAT_FLOAT_FLOAT_FLOAT (GClosure *closure,
GValue *return_value,
guint n_param_values,
const GValue *param_values,
gpointer invocation_hint,
gpointer marshal_data);
/* VOID:POINTER,DOUBLE,DOUBLE,DOUBLE,DOUBLE (marshaller.src:2) */
extern void g_cclosure_user_marshal_VOID__POINTER_DOUBLE_DOUBLE_DOUBLE_DOUBLE (GClosure *closure,
GValue *return_value,
guint n_param_values,
const GValue *param_values,
gpointer invocation_hint,
gpointer marshal_data);
/* POINTER:POINTER,FLOAT,FLOAT,FLOAT,FLOAT (marshaller.src:3) */
extern void g_cclosure_user_marshal_POINTER__POINTER_FLOAT_FLOAT_FLOAT_FLOAT (GClosure *closure,
GValue *return_value,
guint n_param_values,
const GValue *param_values,
gpointer invocation_hint,
gpointer marshal_data);
/* POINTER:POINTER,DOUBLE,DOUBLE,DOUBLE,DOUBLE (marshaller.src:4) */
extern void g_cclosure_user_marshal_POINTER__POINTER_DOUBLE_DOUBLE_DOUBLE_DOUBLE (GClosure *closure,
GValue *return_value,
guint n_param_values,
const GValue *param_values,
gpointer invocation_hint,
gpointer marshal_data);
G_END_DECLS
#endif /* __g_cclosure_user_marshal_MARSHAL_H__ */
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#include "gstqtvideosinkplugin.h"
#include "gstqtvideosink.h"
#include "gstqtglvideosink.h"
#include "gstqwidgetvideosink.h"
#define PACKAGE "mini-qt-gstreamer"
#define PACKAGE_NAME "QgcQtGStreamer"
#define PACKAGE_ORIGIN "http://gstreamer.freedesktop.org/"
#define PACKAGE_VERSION "1.2.0"
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
# include "gstqtquick2videosink.h"
#endif
GST_DEBUG_CATEGORY(gst_qt5gstvideosink_debug);
/* entry point to initialize the plug-in */
static gboolean plugin_init(GstPlugin *plugin)
{
GST_DEBUG_CATEGORY_INIT(gst_qt5gstvideosink_debug,
G_STRINGIFY(QTVIDEOSINK_NAME), 0,
"Debug category for GstQtVideoSink");
if(!gst_element_register(plugin, G_STRINGIFY(QTVIDEOSINK_NAME),
GST_RANK_NONE, GST_TYPE_QT_VIDEO_SINK)) {
GST_ERROR("Failed to register " G_STRINGIFY(QTVIDEOSINK_NAME));
return FALSE;
}
#ifndef GST_QT_VIDEO_SINK_NO_OPENGL
if(!gst_element_register(plugin, G_STRINGIFY(QTGLVIDEOSINK_NAME),
GST_RANK_NONE, GST_TYPE_QT_GL_VIDEO_SINK)) {
GST_ERROR("Failed to register " G_STRINGIFY(QTGLVIDEOSINK_NAME));
return FALSE;
}
#endif
if(!gst_element_register(plugin, G_STRINGIFY(QWIDGETVIDEOSINK_NAME),
GST_RANK_NONE, GST_TYPE_QWIDGET_VIDEO_SINK)) {
GST_ERROR("Failed to register " G_STRINGIFY(QWIDGETVIDEOSINK_NAME));
return FALSE;
}
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
if (!gst_element_register(plugin, "qtquick2videosink",
GST_RANK_NONE, GST_TYPE_QT_QUICK2_VIDEO_SINK)) {
GST_ERROR("Failed to register qtquick2videosink");
return FALSE;
}
#endif
return TRUE;
}
GST_PLUGIN_DEFINE (
GST_VERSION_MAJOR,
GST_VERSION_MINOR,
QTVIDEOSINK_NAME,
"A video sink that can draw on any Qt surface",
plugin_init,
PACKAGE_VERSION,
"LGPL",
PACKAGE_NAME,
PACKAGE_ORIGIN
)
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#ifndef GST_QT_VIDEO_SINK_PLUGIN_H
#define GST_QT_VIDEO_SINK_PLUGIN_H
#include <gst/gst.h>
#include <QtGlobal>
GST_DEBUG_CATEGORY_EXTERN(gst_qt5gstvideosink_debug);
#define GST_CAT_DEFAULT gst_qt5gstvideosink_debug
#define DEFINE_TYPE_FULL(cpp_type, type_name, parent_type, additional_initializations) \
GType cpp_type::get_type() \
{ \
static volatile gsize gonce_data = 0; \
if (g_once_init_enter(&gonce_data)) { \
GType type = 0; \
GTypeInfo info; \
info.class_size = sizeof(cpp_type##Class); \
info.base_init = &cpp_type::base_init; \
info.base_finalize = NULL; \
info.class_init = &cpp_type::class_init; \
info.class_finalize = NULL; \
info.class_data = NULL; \
info.instance_size = sizeof(cpp_type); \
info.n_preallocs = 0; \
info.instance_init = &cpp_type::init; \
info.value_table = 0; \
type = g_type_register_static(parent_type, g_intern_static_string(type_name), &info, (GTypeFlags)0); \
additional_initializations(type); \
g_once_init_leave(&gonce_data, (gsize) type); \
} \
return (GType) gonce_data; \
}
// To allow qt4 and qt5 versions of the plugin to be installed at the same time,
// use a different name for their GType, so that the glib type system can handle
// both plugins being loaded by the gstreamer registry
#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
# define DEFINE_TYPE(cpp_type, parent_type) \
DEFINE_TYPE_FULL(cpp_type, #cpp_type "_qt5", parent_type, Q_UNUSED)
# define DEFINE_TYPE_WITH_CODE(cpp_type, parent_type, additional_initializations) \
DEFINE_TYPE_FULL(cpp_type, #cpp_type "_qt5", parent_type, additional_initializations)
#else
# define DEFINE_TYPE(cpp_type, parent_type) \
DEFINE_TYPE_FULL(cpp_type, #cpp_type, parent_type, Q_UNUSED)
# define DEFINE_TYPE_WITH_CODE(cpp_type, parent_type, additional_initializations) \
DEFINE_TYPE_FULL(cpp_type, #cpp_type, parent_type, additional_initializations)
#endif
inline bool qRealIsDouble() { return sizeof(qreal) == sizeof(double); }
#define G_TYPE_QREAL qRealIsDouble() ? G_TYPE_DOUBLE : G_TYPE_FLOAT
#endif
/*
Copyright (C) 2010 George Kiagiadakis <kiagiadakis.george@gmail.com>
Copyright (C) 2012 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#include "gstqwidgetvideosink.h"
#include "delegates/qwidgetvideosinkdelegate.h"
DEFINE_TYPE(GstQWidgetVideoSink, GST_TYPE_QT_VIDEO_SINK_BASE)
//------------------------------
void GstQWidgetVideoSink::base_init(gpointer gclass)
{
GstElementClass *element_class = GST_ELEMENT_CLASS(gclass);
gst_element_class_set_details_simple(element_class, "QWidget video sink", "Sink/Video",
"A video sink that draws on a QWidget using QPainter",
"George Kiagiadakis <george.kiagiadakis@collabora.com>");
}
void GstQWidgetVideoSink::class_init(gpointer g_class, gpointer class_data)
{
Q_UNUSED(class_data);
GObjectClass *gobject_class = G_OBJECT_CLASS(g_class);
gobject_class->set_property = GstQWidgetVideoSink::set_property;
gobject_class->get_property = GstQWidgetVideoSink::get_property;
/**
* GstQWidgetVideoSink::widget
*
* This property holds a pointer to the QWidget on which the sink will paint the video.
* You can set this property at any time, even if the element is in PLAYING
* state. You can also set this property to NULL at any time to release
* the widget. In this case, qwidgetvideosink will behave like a fakesink,
* i.e. it will silently drop all the frames that it receives. It is also safe
* to delete the widget that has been set as this property; the sink will be
* signaled and this property will automatically be set to NULL.
**/
g_object_class_install_property(gobject_class, PROP_WIDGET,
g_param_spec_pointer("widget", "Widget",
"The widget on which this element will paint the video",
static_cast<GParamFlags>(G_PARAM_READWRITE)));
}
void GstQWidgetVideoSink::init(GTypeInstance *instance, gpointer g_class)
{
Q_UNUSED(g_class);
GstQtVideoSinkBase *sinkBase = GST_QT_VIDEO_SINK_BASE(instance);
sinkBase->delegate = new QWidgetVideoSinkDelegate(GST_ELEMENT(sinkBase));
}
void GstQWidgetVideoSink::set_property(GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec)
{
GstQtVideoSinkBase *sinkBase = GST_QT_VIDEO_SINK_BASE(object);
QWidgetVideoSinkDelegate *delegate = static_cast<QWidgetVideoSinkDelegate*>(sinkBase->delegate);
switch (prop_id) {
case PROP_WIDGET:
delegate->setWidget(static_cast<QWidget*>(g_value_get_pointer(value)));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
}
}
void GstQWidgetVideoSink::get_property(GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
{
GstQtVideoSinkBase *sinkBase = GST_QT_VIDEO_SINK_BASE(object);
QWidgetVideoSinkDelegate *delegate = static_cast<QWidgetVideoSinkDelegate*>(sinkBase->delegate);
switch (prop_id) {
case PROP_WIDGET:
g_value_set_pointer(value, delegate->widget());
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
}
}
/*
Copyright (C) 2010 George Kiagiadakis <kiagiadakis.george@gmail.com>
Copyright (C) 2012 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#ifndef GST_QWIDGET_VIDEO_SINK_H
#define GST_QWIDGET_VIDEO_SINK_H
#include "gstqtvideosinkbase.h"
#define GST_TYPE_QWIDGET_VIDEO_SINK \
(GstQWidgetVideoSink::get_type())
struct GstQWidgetVideoSink
{
public:
GstQtVideoSinkBase parent;
static GType get_type();
private:
enum {
PROP_0,
PROP_WIDGET
};
static void base_init(gpointer g_class);
static void class_init(gpointer g_class, gpointer class_data);
static void init(GTypeInstance *instance, gpointer g_class);
static void set_property(GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec);
static void get_property(GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec);
};
struct GstQWidgetVideoSinkClass
{
GstQtVideoSinkBaseClass parent_class;
};
#endif
VOID:POINTER,FLOAT,FLOAT,FLOAT,FLOAT
VOID:POINTER,DOUBLE,DOUBLE,DOUBLE,DOUBLE
POINTER:POINTER,FLOAT,FLOAT,FLOAT,FLOAT
POINTER:POINTER,DOUBLE,DOUBLE,DOUBLE,DOUBLE
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011-2012 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#ifndef ABSTRACTSURFACEPAINTER_H
#define ABSTRACTSURFACEPAINTER_H
#include "../utils/bufferformat.h"
#include <QRectF>
class QPainter;
/** Common interface for all the painters */
class AbstractSurfacePainter
{
public:
virtual ~AbstractSurfacePainter() {}
virtual bool supportsFormat(GstVideoFormat format) const = 0;
virtual void init(const BufferFormat & format) = 0;
virtual void cleanup() = 0;
virtual void paint(quint8 *data, const BufferFormat & frameFormat,
QPainter *painter, const PaintAreas & areas) = 0;
virtual void updateColors(int brightness, int contrast, int hue, int saturation) = 0;
};
#endif
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011-2012 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#include "genericsurfacepainter.h"
#include <QPainter>
GenericSurfacePainter::GenericSurfacePainter()
: m_imageFormat(QImage::Format_Invalid)
{
}
//static
QSet<GstVideoFormat> GenericSurfacePainter::supportedPixelFormats()
{
return QSet<GstVideoFormat>()
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
<< GST_VIDEO_FORMAT_ARGB
<< GST_VIDEO_FORMAT_xRGB
#else
<< GST_VIDEO_FORMAT_BGRA
<< GST_VIDEO_FORMAT_BGRx
#endif
<< GST_VIDEO_FORMAT_RGB
<< GST_VIDEO_FORMAT_RGB16
;
}
void GenericSurfacePainter::init(const BufferFormat &format)
{
switch (format.videoFormat()) {
// QImage is shitty and reads integers instead of bytes,
// thus it is affected by the host's endianness
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
case GST_VIDEO_FORMAT_ARGB:
#else
case GST_VIDEO_FORMAT_BGRA:
#endif
m_imageFormat = QImage::Format_ARGB32;
break;
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
case GST_VIDEO_FORMAT_xRGB:
#else
case GST_VIDEO_FORMAT_BGRx:
#endif
m_imageFormat = QImage::Format_RGB32;
break;
//16-bit RGB formats use host's endianness in GStreamer
//FIXME-0.11 do endianness checks like above if semantics have changed
case GST_VIDEO_FORMAT_RGB16:
m_imageFormat = QImage::Format_RGB16;
break;
//This is not affected by endianness
case GST_VIDEO_FORMAT_RGB:
m_imageFormat = QImage::Format_RGB888;
break;
default:
throw QString("Unsupported format");
}
}
void GenericSurfacePainter::cleanup()
{
m_imageFormat = QImage::Format_Invalid;
}
void GenericSurfacePainter::paint(quint8 *data,
const BufferFormat & frameFormat,
QPainter *painter,
const PaintAreas & areas)
{
Q_ASSERT(m_imageFormat != QImage::Format_Invalid);
QImage image(
data,
frameFormat.frameSize().width(),
frameFormat.frameSize().height(),
frameFormat.bytesPerLine(),
m_imageFormat);
QRectF sourceRect = areas.sourceRect;
sourceRect.setX(sourceRect.x() * frameFormat.frameSize().width());
sourceRect.setY(sourceRect.y() * frameFormat.frameSize().height());
sourceRect.setWidth(sourceRect.width() * frameFormat.frameSize().width());
sourceRect.setHeight(sourceRect.height() * frameFormat.frameSize().height());
painter->fillRect(areas.blackArea1, Qt::black);
painter->drawImage(areas.videoArea, image, sourceRect);
painter->fillRect(areas.blackArea2, Qt::black);
}
void GenericSurfacePainter::updateColors(int, int, int, int)
{
}
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#ifndef GENERICSURFACEPAINTER_H
#define GENERICSURFACEPAINTER_H
#include "abstractsurfacepainter.h"
#include <QSet>
#include <QImage>
/**
* Generic painter that paints using the QPainter API.
* No colorspace conversion is done and no colors adjustment either.
*/
class GenericSurfacePainter : public AbstractSurfacePainter
{
public:
GenericSurfacePainter();
static QSet<GstVideoFormat> supportedPixelFormats();
virtual bool supportsFormat(GstVideoFormat format) const {
return supportedPixelFormats().contains(format);
}
virtual void init(const BufferFormat &format);
virtual void cleanup();
virtual void paint(quint8 *data, const BufferFormat & frameFormat,
QPainter *painter, const PaintAreas & areas);
virtual void updateColors(int brightness, int contrast, int hue, int saturation);
private:
QImage::Format m_imageFormat;
};
#endif // GENERICSURFACEPAINTER_H
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011-2012 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#ifndef OPENGLSURFACEPAINTER_H
#define OPENGLSURFACEPAINTER_H
#ifndef GST_QT_VIDEO_SINK_NO_OPENGL
#include "abstractsurfacepainter.h"
#include <QGLShaderProgram>
#ifndef Q_WS_MAC
# ifndef APIENTRYP
# ifdef APIENTRY
# define APIENTRYP APIENTRY *
# else
# define APIENTRY
# define APIENTRYP *
# endif
# endif
#else
# define APIENTRY
# define APIENTRYP *
#endif
class OpenGLSurfacePainter : public AbstractSurfacePainter
{
public:
OpenGLSurfacePainter();
static QSet<GstVideoFormat> supportedPixelFormats();
virtual bool supportsFormat(GstVideoFormat format) const {
return supportedPixelFormats().contains(format);
}
virtual void updateColors(int brightness, int contrast, int hue, int saturation);
virtual void paint(quint8 *data, const BufferFormat & frameFormat,
QPainter *painter, const PaintAreas & areas);
protected:
void initRgbTextureInfo(GLenum internalFormat, GLuint format, GLenum type, const QSize &size);
void initYuv420PTextureInfo(const QSize &size);
void initYv12TextureInfo(const QSize &size);
virtual void paintImpl(const QPainter *painter,
const GLfloat *vertexCoordArray,
const GLfloat *textureCoordArray) = 0;
#ifndef QT_OPENGL_ES
typedef void (APIENTRY *_glActiveTexture) (GLenum);
_glActiveTexture glActiveTexture;
#endif
GLenum m_textureFormat;
GLuint m_textureInternalFormat;
GLenum m_textureType;
int m_textureCount;
GLuint m_textureIds[3];
int m_textureWidths[3];
int m_textureHeights[3];
int m_textureOffsets[3];
QMatrix4x4 m_colorMatrix;
GstVideoColorMatrix m_videoColorMatrix;
};
#ifndef QT_OPENGL_ES
class ArbFpSurfacePainter : public OpenGLSurfacePainter
{
public:
ArbFpSurfacePainter();
virtual void init(const BufferFormat & format);
virtual void cleanup();
protected:
virtual void paintImpl(const QPainter *painter,
const GLfloat *vertexCoordArray,
const GLfloat *textureCoordArray);
private:
typedef void (APIENTRY *_glProgramStringARB) (GLenum, GLenum, GLsizei, const GLvoid *);
typedef void (APIENTRY *_glBindProgramARB) (GLenum, GLuint);
typedef void (APIENTRY *_glDeleteProgramsARB) (GLsizei, const GLuint *);
typedef void (APIENTRY *_glGenProgramsARB) (GLsizei, GLuint *);
typedef void (APIENTRY *_glProgramLocalParameter4fARB) (
GLenum, GLuint, GLfloat, GLfloat, GLfloat, GLfloat);
typedef void (APIENTRY *_glActiveTexture) (GLenum);
_glProgramStringARB glProgramStringARB;
_glBindProgramARB glBindProgramARB;
_glDeleteProgramsARB glDeleteProgramsARB;
_glGenProgramsARB glGenProgramsARB;
_glProgramLocalParameter4fARB glProgramLocalParameter4fARB;
GLuint m_programId;
};
#endif
class GlslSurfacePainter : public OpenGLSurfacePainter
{
public:
GlslSurfacePainter();
virtual void init(const BufferFormat & format);
virtual void cleanup();
protected:
virtual void paintImpl(const QPainter *painter,
const GLfloat *vertexCoordArray,
const GLfloat *textureCoordArray);
private:
QGLShaderProgram m_program;
};
#endif // GST_QT_VIDEO_SINK_NO_OPENGL
#endif // OPENGLSURFACEPAINTER_H
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -64,6 +64,7 @@ Item {
Menu {
id: mapTypeMenu
title: "Map Type..."
enabled: root.visible
ExclusiveGroup { id: currMapType }
function setCurrentMap(mapID) {
for (var i = 0; i < map.supportedMapTypes.length; i++) {
......
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment