VideoItem.cc 3.67 KB
Newer Older
1 2 3 4 5 6 7 8
/****************************************************************************
 *
 *   (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
 *
 * QGroundControl is licensed according to the terms in the file
 * COPYING.md in the root of the source code directory.
 *
 ****************************************************************************/
Gus Grubba's avatar
Gus Grubba committed
9 10 11 12 13 14 15 16 17 18 19 20


/**
 * @file
 *   @brief QGC Video Item
 *   @author Gus Grubba <mavlink@grubba.com>
 */

#include <QtCore/QPointer>
#include <QtQuick/QSGNode>
#include <QtQuick/QSGFlatColorMaterial>

Gus Grubba's avatar
Gus Grubba committed
21
#include "VideoItem.h"
22
#if defined(QGC_GST_STREAMING)
Gus Grubba's avatar
Gus Grubba committed
23
#include "VideoSurface_p.h"
24
#endif
Gus Grubba's avatar
Gus Grubba committed
25

26
#if defined(QGC_GST_STREAMING)
Gus Grubba's avatar
Gus Grubba committed
27 28 29 30 31 32
struct VideoItem::Private
{
    QPointer<VideoSurface> surface;
    bool surfaceDirty;
    QRectF targetArea;
};
33
#endif
Gus Grubba's avatar
Gus Grubba committed
34 35

VideoItem::VideoItem(QQuickItem *parent)
36 37 38 39
    : QQuickItem(parent)
#if defined(QGC_GST_STREAMING)
    , _data(new Private)
#endif
Gus Grubba's avatar
Gus Grubba committed
40
{
41
#if defined(QGC_GST_STREAMING)
Gus Grubba's avatar
Gus Grubba committed
42 43
    _data->surfaceDirty = true;
    setFlag(QQuickItem::ItemHasContents, true);
44
#endif
Gus Grubba's avatar
Gus Grubba committed
45 46 47 48
}

VideoItem::~VideoItem()
{
49
#if defined(QGC_GST_STREAMING)
Gus Grubba's avatar
Gus Grubba committed
50 51
    setSurface(0);
    delete _data;
52
#endif
Gus Grubba's avatar
Gus Grubba committed
53 54 55 56
}

VideoSurface *VideoItem::surface() const
{
57
#if defined(QGC_GST_STREAMING)
Gus Grubba's avatar
Gus Grubba committed
58
    return _data->surface.data();
59
#else
60
    return nullptr;
61
#endif
Gus Grubba's avatar
Gus Grubba committed
62 63 64 65
}

void VideoItem::setSurface(VideoSurface *surface)
{
66
#if defined(QGC_GST_STREAMING)
Gus Grubba's avatar
Gus Grubba committed
67 68 69 70 71 72 73 74
    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);
    }
dogmaphobic's avatar
dogmaphobic committed
75 76
#else
    Q_UNUSED(surface)
77
#endif
Gus Grubba's avatar
Gus Grubba committed
78 79
}

80
#if defined(QGC_GST_STREAMING)
81 82 83 84 85 86 87 88 89 90 91
QSGGeometry* VideoItem::_createDefaultGeometry(QRectF& rectBound)
{
	QSGGeometry *geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 4);
	geometry->vertexDataAsPoint2D()[0].set(rectBound.x(), rectBound.y());
	geometry->vertexDataAsPoint2D()[1].set(rectBound.x(), rectBound.height());
	geometry->vertexDataAsPoint2D()[2].set(rectBound.width(), rectBound.y());
	geometry->vertexDataAsPoint2D()[3].set(rectBound.width(), rectBound.height());

	return geometry;
}

Gus Grubba's avatar
Gus Grubba committed
92 93 94
QSGNode* VideoItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData*)
{
    QRectF r = boundingRect();
95
    QSGNode* newNode = nullptr;
Gus Grubba's avatar
Gus Grubba committed
96 97 98

    if (_data->surfaceDirty) {
        delete oldNode;
99
        oldNode = nullptr;
Gus Grubba's avatar
Gus Grubba committed
100 101 102
        _data->surfaceDirty = false;
    }

103
    if (!_data->surface || _data->surface.data()->_data->videoSink == nullptr) {
Gus Grubba's avatar
Gus Grubba committed
104 105 106 107 108 109 110 111 112 113 114 115 116 117
        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) {
            QSGGeometryNode *node = static_cast<QSGGeometryNode*>(newNode);
118
			node->setGeometry(_createDefaultGeometry(r));
Gus Grubba's avatar
Gus Grubba committed
119 120 121 122 123 124
            _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);
    }

125 126 127 128 129 130 131 132
	// Sometimes we can still end up here with no geometry when gstreamer fails to create it for whatever reason. If that happens it can
	// cause crashes.
	QSGGeometryNode *node = static_cast<QSGGeometryNode*>(newNode);
	if (node->geometry() == nullptr) {
		qDebug() << "Creating default geom";
		node->setGeometry(_createDefaultGeometry(r));
	}

Gus Grubba's avatar
Gus Grubba committed
133 134
    return newNode;
}
135
#endif