diff --git a/ChangeLog.md b/ChangeLog.md index aeccabe..cdb34db 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -9,6 +9,7 @@ Note: This file only contains high level features or important fixes. * Major rewrite and bug fix pass through Structure Scan. Previous version had such bad problems that it can no longer be supported. Plans with Structure Scan will need to be recreated. New QGC will not load old Structure Scan plans. ### 3.5.4 - Not yet released +* Guard against null geometry coming from gstreamer which can cause crashes * Add .apj file selection support to custom firmware flash ### 3.5.3 - Stable diff --git a/src/VideoStreaming/VideoItem.cc b/src/VideoStreaming/VideoItem.cc index 2a138cf..8a872c6 100644 --- a/src/VideoStreaming/VideoItem.cc +++ b/src/VideoStreaming/VideoItem.cc @@ -78,6 +78,17 @@ void VideoItem::setSurface(VideoSurface *surface) } #if defined(QGC_GST_STREAMING) +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; +} + QSGNode* VideoItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData*) { QRectF r = boundingRect(); @@ -103,19 +114,22 @@ QSGNode* VideoItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData*) 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(newNode); - node->setGeometry(geometry); + node->setGeometry(_createDefaultGeometry(r)); _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); } + // 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(newNode); + if (node->geometry() == nullptr) { + qDebug() << "Creating default geom"; + node->setGeometry(_createDefaultGeometry(r)); + } + return newNode; } #endif diff --git a/src/VideoStreaming/VideoItem.h b/src/VideoStreaming/VideoItem.h index eeb1caa..5044604 100644 --- a/src/VideoStreaming/VideoItem.h +++ b/src/VideoStreaming/VideoItem.h @@ -19,6 +19,8 @@ #include #include "VideoSurface.h" +class QSGGeometry; + class VideoItem : public QQuickItem { Q_OBJECT @@ -40,6 +42,8 @@ protected: private: #if defined(QGC_GST_STREAMING) + QSGGeometry* _createDefaultGeometry(QRectF& rectBound); + struct Private; Private* const _data; #endif