diff --git a/QGCApplication.pro b/QGCApplication.pro index 6f9795607809cec4f583d484089d1c8045775a47..61d8f15d3f3ea04bd1ee289b19a60753e4c1ee48 100644 --- a/QGCApplication.pro +++ b/QGCApplication.pro @@ -652,7 +652,23 @@ SOURCES += \ src/FactSystem/ParameterLoader.cc \ src/FactSystem/FactControls/FactPanelController.cc \ +#------------------------------------------------------------------------------------- # Video Streaming + +INCLUDEPATH += \ + src/VideoStreaming + +HEADERS += \ + src/VideoStreaming/VideoItem.h \ + src/VideoStreaming/VideoReceiver.h \ + src/VideoStreaming/VideoSurface.h \ + src/VideoStreaming/VideoSurface_p.h \ + +SOURCES += \ + src/VideoStreaming/VideoItem.cc \ + src/VideoStreaming/VideoReceiver.cc \ + src/VideoStreaming/VideoSurface.cc \ + contains (DEFINES, DISABLE_VIDEOSTREAMING) { message("Skipping support for video streaming (manual override from command line)") DEFINES -= DISABLE_VIDEOSTREAMING @@ -663,6 +679,7 @@ contains (DEFINES, DISABLE_VIDEOSTREAMING) { include(src/VideoStreaming/VideoStreaming.pri) } +#------------------------------------------------------------------------------------- # Android AndroidBuild { diff --git a/src/QGCApplication.cc b/src/QGCApplication.cc index 00cbf094aeb60a65ebf7072075d4236b4b0a9f87..f6da705d3072fafc77e9d9810925ca330c9ad550 100644 --- a/src/QGCApplication.cc +++ b/src/QGCApplication.cc @@ -40,9 +40,9 @@ #include -#if defined(QGC_GST_STREAMING) #include #include +#if defined(QGC_GST_STREAMING) G_BEGIN_DECLS GST_PLUGIN_STATIC_DECLARE(QTVIDEOSINK_NAME); G_END_DECLS @@ -264,11 +264,11 @@ QGCApplication::QGCApplication(int &argc, char* argv[], bool unitTesting) settings.setValue(_settingsVersionKey, QGC_SETTINGS_VERSION); } -#if defined(QGC_GST_STREAMING) //---------------------------------------------------------------- //-- Video Streaming qmlRegisterType("QGroundControl.QgcQtGStreamer", 1, 0, "VideoItem"); qmlRegisterUncreatableType("QGroundControl.QgcQtGStreamer", 1, 0, "VideoSurface", QLatin1String("VideoSurface from QML is not supported")); +#if defined(QGC_GST_STREAMING) GError* error = NULL; if (!gst_init_check(&argc, &argv, &error)) { qCritical() << "gst_init_check() failed: " << error->message; diff --git a/src/QmlControls/ScreenToolsController.h b/src/QmlControls/ScreenToolsController.h index d118c8a76fb190fe9a97b7f3a04edfe7d8fec084..46e43fa04b10fd7f8e2b1819baaf2919e29a4b49 100644 --- a/src/QmlControls/ScreenToolsController.h +++ b/src/QmlControls/ScreenToolsController.h @@ -50,7 +50,6 @@ 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. /*! @@ -111,12 +110,6 @@ 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); diff --git a/src/VideoStreaming/VideoItem.cc b/src/VideoStreaming/VideoItem.cc index b02ff504fd0dd56735dd38b5b8b22498b9a30ade..3943a326bea8c355c5dfdb90ff35d307c699617a 100644 --- a/src/VideoStreaming/VideoItem.cc +++ b/src/VideoStreaming/VideoItem.cc @@ -32,35 +32,51 @@ This file is part of the QGROUNDCONTROL project #include #include "VideoItem.h" +#if defined(QGC_GST_STREAMING) #include "VideoSurface_p.h" +#endif +#if defined(QGC_GST_STREAMING) struct VideoItem::Private { QPointer surface; bool surfaceDirty; QRectF targetArea; }; +#endif VideoItem::VideoItem(QQuickItem *parent) - : QQuickItem(parent), _data(new Private) + : QQuickItem(parent) +#if defined(QGC_GST_STREAMING) + , _data(new Private) +#endif { +#if defined(QGC_GST_STREAMING) _data->surfaceDirty = true; setFlag(QQuickItem::ItemHasContents, true); +#endif } VideoItem::~VideoItem() { +#if defined(QGC_GST_STREAMING) setSurface(0); delete _data; +#endif } VideoSurface *VideoItem::surface() const { +#if defined(QGC_GST_STREAMING) return _data->surface.data(); +#else + return NULL; +#endif } void VideoItem::setSurface(VideoSurface *surface) { +#if defined(QGC_GST_STREAMING) if (_data->surface) { _data->surface.data()->_data->items.remove(this); } @@ -69,8 +85,10 @@ void VideoItem::setSurface(VideoSurface *surface) if (_data->surface) { _data->surface.data()->_data->items.insert(this); } +#endif } +#if defined(QGC_GST_STREAMING) QSGNode* VideoItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData*) { QRectF r = boundingRect(); @@ -111,3 +129,4 @@ QSGNode* VideoItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData*) return newNode; } +#endif diff --git a/src/VideoStreaming/VideoItem.h b/src/VideoStreaming/VideoItem.h index 65c38c83a95d9e8687e25a676916ac36990b0357..ef7399a9268d7f1d98498797408d54302940b447 100644 --- a/src/VideoStreaming/VideoItem.h +++ b/src/VideoStreaming/VideoItem.h @@ -47,12 +47,16 @@ public: void setSurface(VideoSurface *surface); protected: +#if defined(QGC_GST_STREAMING) /*! Reimplemented from QQuickItem. */ virtual QSGNode* updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *updatePaintNodeData); +#endif private: +#if defined(QGC_GST_STREAMING) struct Private; Private* const _data; +#endif }; #endif // VIDEO_ITEM_H diff --git a/src/VideoStreaming/VideoReceiver.cc b/src/VideoStreaming/VideoReceiver.cc index 7c60446a411b9b89aab0668440761747b78e9d44..10aa0f5bb598798d1104641d4220caeb93e36994 100644 --- a/src/VideoStreaming/VideoReceiver.cc +++ b/src/VideoStreaming/VideoReceiver.cc @@ -32,18 +32,23 @@ This file is part of the QGROUNDCONTROL project VideoReceiver::VideoReceiver(QObject* parent) : QObject(parent) +#if defined(QGC_GST_STREAMING) , _pipeline(NULL) , _videoSink(NULL) +#endif { } VideoReceiver::~VideoReceiver() { +#if defined(QGC_GST_STREAMING) stop(); setVideoSink(NULL); +#endif } +#if defined(QGC_GST_STREAMING) void VideoReceiver::setVideoSink(GstElement* sink) { if (_videoSink) { @@ -55,9 +60,11 @@ void VideoReceiver::setVideoSink(GstElement* sink) gst_object_ref_sink(_videoSink); } } +#endif void VideoReceiver::start() { +#if defined(QGC_GST_STREAMING) if (_uri.isEmpty()) { qCritical() << "VideoReceiver::start() failed because URI is not specified"; return; @@ -158,15 +165,18 @@ void VideoReceiver::start() _pipeline = NULL; } } +#endif } void VideoReceiver::stop() { +#if defined(QGC_GST_STREAMING) if (_pipeline != NULL) { gst_element_set_state(_pipeline, GST_STATE_NULL); gst_object_unref(_pipeline); _pipeline = NULL; } +#endif } void VideoReceiver::setUri(const QString & uri) @@ -175,6 +185,7 @@ void VideoReceiver::setUri(const QString & uri) _uri = uri; } +#if defined(QGC_GST_STREAMING) void VideoReceiver::_onBusMessage(GstMessage* msg) { switch (GST_MESSAGE_TYPE(msg)) { @@ -196,7 +207,9 @@ void VideoReceiver::_onBusMessage(GstMessage* msg) break; } } +#endif +#if defined(QGC_GST_STREAMING) gboolean VideoReceiver::_onBusMessage(GstBus* bus, GstMessage* msg, gpointer data) { Q_UNUSED(bus) @@ -205,3 +218,4 @@ gboolean VideoReceiver::_onBusMessage(GstBus* bus, GstMessage* msg, gpointer dat pThis->_onBusMessage(msg); return TRUE; } +#endif diff --git a/src/VideoStreaming/VideoReceiver.h b/src/VideoStreaming/VideoReceiver.h index 1a7917f1210ad00919bd8ad533ce69b063b27e8c..c2fd35fc3d08250d011b61d3aa330317df08c978 100644 --- a/src/VideoStreaming/VideoReceiver.h +++ b/src/VideoStreaming/VideoReceiver.h @@ -31,7 +31,9 @@ This file is part of the QGROUNDCONTROL project #define VIDEORECEIVER_H #include +#if defined(QGC_GST_STREAMING) #include +#endif class VideoReceiver : public QObject { @@ -40,7 +42,9 @@ public: explicit VideoReceiver(QObject* parent = 0); ~VideoReceiver(); +#if defined(QGC_GST_STREAMING) void setVideoSink(GstElement* sink); +#endif public Q_SLOTS: void start (); @@ -48,12 +52,19 @@ public Q_SLOTS: void setUri (const QString& uri); private: + +#if defined(QGC_GST_STREAMING) void _onBusMessage(GstMessage* message); static gboolean _onBusMessage(GstBus* bus, GstMessage* msg, gpointer data); +#endif QString _uri; + +#if defined(QGC_GST_STREAMING) GstElement* _pipeline; GstElement* _videoSink; +#endif + }; #endif // VIDEORECEIVER_H diff --git a/src/VideoStreaming/VideoStreaming.pri b/src/VideoStreaming/VideoStreaming.pri index 4d4f2a5413a15a325a5ca2b80f20693e79961c47..323fe1d6b5df95e6dd4b8f6189a4cfc69d33d47c 100644 --- a/src/VideoStreaming/VideoStreaming.pri +++ b/src/VideoStreaming/VideoStreaming.pri @@ -50,26 +50,13 @@ VideoEnabled { 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 += \ diff --git a/src/VideoStreaming/VideoSurface.cc b/src/VideoStreaming/VideoSurface.cc index cb067527aacfcca699b91ca2138bbb9c48972fdd..9202f198421d101200cd413c37cb613704f38658 100644 --- a/src/VideoStreaming/VideoSurface.cc +++ b/src/VideoStreaming/VideoSurface.cc @@ -27,25 +27,33 @@ This file is part of the QGROUNDCONTROL project * @author Gus Grubba */ +#if defined(QGC_GST_STREAMING) #include "VideoSurface_p.h" +#endif +#include "VideoSurface.h" #include #include VideoSurface::VideoSurface(QObject *parent) : QObject(parent) +#if defined(QGC_GST_STREAMING) , _data(new VideoSurfacePrivate) +#endif { } VideoSurface::~VideoSurface() { +#if defined(QGC_GST_STREAMING) if (_data->videoSink != NULL) { gst_element_set_state(_data->videoSink, GST_STATE_NULL); } delete _data; +#endif } +#if defined(QGC_GST_STREAMING) GstElement* VideoSurface::videoSink() const { if (_data->videoSink == NULL) { @@ -71,4 +79,5 @@ void VideoSurface::onUpdateThunk(GstElement* sink, gpointer data) VideoSurface* pThis = (VideoSurface* )data; pThis->onUpdate(); } +#endif diff --git a/src/VideoStreaming/VideoSurface.h b/src/VideoStreaming/VideoSurface.h index 428a59af21268e72a1aec03bc8bbbccc3ad664b4..deb140ad7b5489b2be177fc2eb786355159ba10b 100644 --- a/src/VideoStreaming/VideoSurface.h +++ b/src/VideoStreaming/VideoSurface.h @@ -32,9 +32,13 @@ This file is part of the QGROUNDCONTROL project #include +#if defined(QGC_GST_STREAMING) #include +#endif +#if defined(QGC_GST_STREAMING) class VideoSurfacePrivate; +#endif class VideoSurface : public QObject { @@ -48,15 +52,21 @@ public: * The element will be constructed the first time that this function * is called. The surface will always keep a reference to this element. */ +#if defined(QGC_GST_STREAMING) GstElement* videoSink() const; +#endif protected: +#if defined(QGC_GST_STREAMING) void onUpdate(); static void onUpdateThunk(GstElement* sink, gpointer data); +#endif private: friend class VideoItem; +#if defined(QGC_GST_STREAMING) VideoSurfacePrivate * const _data; +#endif }; Q_DECLARE_METATYPE(VideoSurface*) diff --git a/src/ui/flightdisplay/FlightDisplay.cc b/src/ui/flightdisplay/FlightDisplay.cc index f3b8938d6c42ab114e38aade1ad9cf485d9a7f0d..a154823b76d532aab283f8b631b0d10b10ffa3ad 100644 --- a/src/ui/flightdisplay/FlightDisplay.cc +++ b/src/ui/flightdisplay/FlightDisplay.cc @@ -31,11 +31,9 @@ This file is part of the QGROUNDCONTROL project #include #include -#if defined(QGC_GST_STREAMING) #include #include #include "VideoReceiver.h" -#endif #include "ScreenToolsController.h" #include "FlightDisplay.h" @@ -59,7 +57,6 @@ FlightDisplay::FlightDisplay(QWidget *parent) #endif setContextPropertyObject("flightDisplay", this); -#if defined(QGC_GST_STREAMING) /* * This is the receiving end of an UDP RTP stream. The sender can be setup with this command: * @@ -89,9 +86,10 @@ FlightDisplay::FlightDisplay(QWidget *parent) setContextPropertyObject("videoDisplay", pSurface); VideoReceiver* pReceiver = new VideoReceiver(this); pReceiver->setUri(QLatin1Literal("udp://0.0.0.0:5000")); +#if defined(QGC_GST_STREAMING) pReceiver->setVideoSink(pSurface->videoSink()); - setContextPropertyObject("videoReceiver", pReceiver); #endif + setContextPropertyObject("videoReceiver", pReceiver); setSource(QUrl::fromUserInput("qrc:/qml/FlightDisplay.qml")); setVisible(true); diff --git a/src/ui/flightdisplay/FlightDisplay.h b/src/ui/flightdisplay/FlightDisplay.h index ba374c26a92af873861305171d76de4ba53b6805..cd3e63e72e6b877405127891ce9c0890043fcb89 100644 --- a/src/ui/flightdisplay/FlightDisplay.h +++ b/src/ui/flightdisplay/FlightDisplay.h @@ -44,9 +44,17 @@ public: /// @brief Invokes the Flight Display Options menu void showOptionsMenu() { emit showOptionsMenuChanged(); } + Q_PROPERTY(bool hasVideo READ hasVideo CONSTANT) + Q_INVOKABLE void saveSetting (const QString &key, const QString& value); Q_INVOKABLE QString loadSetting (const QString &key, const QString& defaultValue); +#if defined(QGC_GST_STREAMING) + bool hasVideo () { return true; } +#else + bool hasVideo () { return false; } +#endif + signals: void showOptionsMenuChanged (); diff --git a/src/ui/flightdisplay/FlightDisplay.qml b/src/ui/flightdisplay/FlightDisplay.qml index 043d4164a2ddfd47fab2138a32e5e0c185f9d20c..e075a524857b0dad2c672d9975c3135a57de35ad 100644 --- a/src/ui/flightdisplay/FlightDisplay.qml +++ b/src/ui/flightdisplay/FlightDisplay.qml @@ -91,6 +91,13 @@ Item { videoBackground.visible = false; flightDisplay.saveSetting("showVideoBackground", setBool(videoBackground.visible)); } + // Disable video if we don't have support for it + if(!flightDisplay.hasVideo) { + videoBackground.visible = false; + flightDisplay.saveSetting("showVideoBackground", setBool(videoBackground.visible)); + } + // Enable/Disable menu accordingly + videoMenu.enabled = flightDisplay.hasVideo; } Menu { @@ -141,6 +148,7 @@ Item { MenuSeparator {} MenuItem { + id: videoMenu text: "Video Background" checkable: true checked: videoBackground.visible diff --git a/src/ui/qmlcommon/QGCVideoBackground.qml b/src/ui/qmlcommon/QGCVideoBackground.qml index 833222574d0614a1c46df40dde39eaafcc6c797e..639bba83ff785dfd7691b54d177f7e00e80f4e4f 100644 --- a/src/ui/qmlcommon/QGCVideoBackground.qml +++ b/src/ui/qmlcommon/QGCVideoBackground.qml @@ -35,17 +35,19 @@ VideoItem { id: videoBackground property var display property var receiver - surface: display + surface: display onVisibleChanged: { - if(videoBackground.visible) { - receiver.start(); - } else { - receiver.stop(); + if(videoBackground.receiver && videoBackground.display) { + if(videoBackground.visible) { + videoBackground.receiver.start(); + } else { + videoBackground.receiver.stop(); + } } } Component.onCompleted: { - if(videoBackground.visible) { - receiver.start(); + if(videoBackground.visible && videoBackground.receiver) { + videoBackground.receiver.start(); } } }