From c9885e2307278fef6a6864edbc260b879934a523 Mon Sep 17 00:00:00 2001 From: Jacob Walser Date: Fri, 13 Jan 2017 13:24:17 -0500 Subject: [PATCH] Pop messages off gstreamer bus manually And fix broken file path to save video on windows --- src/FlightDisplay/VideoManager.cc | 6 ++ src/FlightDisplay/VideoManager.h | 35 ++++++------ src/VideoStreaming/VideoReceiver.cc | 77 +++++++++++++++++++------- src/VideoStreaming/VideoReceiver.h | 2 + src/ui/preferences/GeneralSettings.qml | 6 +- 5 files changed, 85 insertions(+), 41 deletions(-) diff --git a/src/FlightDisplay/VideoManager.cc b/src/FlightDisplay/VideoManager.cc index 5dc6b63c8..e778dafeb 100644 --- a/src/FlightDisplay/VideoManager.cc +++ b/src/FlightDisplay/VideoManager.cc @@ -11,6 +11,7 @@ #include #include #include +#include #ifndef QGC_DISABLE_UVC #include @@ -188,6 +189,11 @@ VideoManager::setRtspURL(QString url) */ } +void +VideoManager::setVideoSavePathByUrl(QUrl url) { + setVideoSavePath(url.toLocalFile()); +} + void VideoManager::setVideoSavePath(QString path) { diff --git a/src/FlightDisplay/VideoManager.h b/src/FlightDisplay/VideoManager.h index 1e1cbbe7b..c9a5e6291 100644 --- a/src/FlightDisplay/VideoManager.h +++ b/src/FlightDisplay/VideoManager.h @@ -13,6 +13,7 @@ #include #include +#include #include "QGCLoggingCategory.h" #include "VideoSurface.h" @@ -29,18 +30,20 @@ public: VideoManager (QGCApplication* app); ~VideoManager (); - Q_PROPERTY(bool hasVideo READ hasVideo NOTIFY hasVideoChanged) - Q_PROPERTY(bool isGStreamer READ isGStreamer NOTIFY isGStreamerChanged) - Q_PROPERTY(QString videoSourceID READ videoSourceID NOTIFY videoSourceIDChanged) - Q_PROPERTY(QString videoSource READ videoSource WRITE setVideoSource NOTIFY videoSourceChanged) - Q_PROPERTY(QStringList videoSourceList READ videoSourceList NOTIFY videoSourceListChanged) - Q_PROPERTY(bool videoRunning READ videoRunning NOTIFY videoRunningChanged) - Q_PROPERTY(quint16 udpPort READ udpPort WRITE setUdpPort NOTIFY udpPortChanged) - Q_PROPERTY(QString rtspURL READ rtspURL WRITE setRtspURL NOTIFY rtspURLChanged) - Q_PROPERTY(QString videoSavePath READ videoSavePath WRITE setVideoSavePath NOTIFY videoSavePathChanged) - Q_PROPERTY(bool uvcEnabled READ uvcEnabled CONSTANT) - Q_PROPERTY(VideoSurface* videoSurface MEMBER _videoSurface CONSTANT) - Q_PROPERTY(VideoReceiver* videoReceiver MEMBER _videoReceiver CONSTANT) + Q_PROPERTY(bool hasVideo READ hasVideo NOTIFY hasVideoChanged) + Q_PROPERTY(bool isGStreamer READ isGStreamer NOTIFY isGStreamerChanged) + Q_PROPERTY(QString videoSourceID READ videoSourceID NOTIFY videoSourceIDChanged) + Q_PROPERTY(QString videoSource READ videoSource WRITE setVideoSource NOTIFY videoSourceChanged) + Q_PROPERTY(QStringList videoSourceList READ videoSourceList NOTIFY videoSourceListChanged) + Q_PROPERTY(bool videoRunning READ videoRunning NOTIFY videoRunningChanged) + Q_PROPERTY(quint16 udpPort READ udpPort WRITE setUdpPort NOTIFY udpPortChanged) + Q_PROPERTY(QString rtspURL READ rtspURL WRITE setRtspURL NOTIFY rtspURLChanged) + Q_PROPERTY(QString videoSavePath READ videoSavePath NOTIFY videoSavePathChanged) + Q_PROPERTY(bool uvcEnabled READ uvcEnabled CONSTANT) + Q_PROPERTY(VideoSurface* videoSurface MEMBER _videoSurface CONSTANT) + Q_PROPERTY(VideoReceiver* videoReceiver MEMBER _videoReceiver CONSTANT) + + Q_INVOKABLE void setVideoSavePathByUrl (QUrl url); bool hasVideo (); bool isGStreamer (); @@ -58,10 +61,10 @@ public: bool uvcEnabled (); #endif - void setVideoSource (QString vSource); - void setUdpPort (quint16 port); - void setRtspURL (QString url); - void setVideoSavePath (QString path); + void setVideoSource (QString vSource); + void setUdpPort (quint16 port); + void setRtspURL (QString url); + void setVideoSavePath (QString path); // Override from QGCTool void setToolbox (QGCToolbox *toolbox); diff --git a/src/VideoStreaming/VideoReceiver.cc b/src/VideoStreaming/VideoReceiver.cc index d05164350..e3e31cdf0 100644 --- a/src/VideoStreaming/VideoReceiver.cc +++ b/src/VideoStreaming/VideoReceiver.cc @@ -43,6 +43,7 @@ VideoReceiver::VideoReceiver(QObject* parent) #if defined(QGC_GST_STREAMING) _timer.setSingleShot(true); connect(&_timer, &QTimer::timeout, this, &VideoReceiver::_timeout); + connect(&_busCheckTimer, &QTimer::timeout, this, &VideoReceiver::_busCheck); #endif } @@ -132,6 +133,33 @@ void VideoReceiver::_timeout() } #endif +#if defined(QGC_GST_STREAMING) +void VideoReceiver::_busCheck() { + GstBus* bus = gst_pipeline_get_bus(GST_PIPELINE(_pipeline)); + + GstMessage* message; + + while((message = gst_bus_pop(bus)) != NULL) { + _onBusMessage(message); + gst_message_unref(message); + } + + gst_object_unref(bus); + + if(_pipelineStopRec == NULL) { + return; + } + + bus = gst_pipeline_get_bus(GST_PIPELINE(_pipelineStopRec)); + if((message = gst_bus_pop_filtered(bus, GST_MESSAGE_EOS)) != NULL) { + _eosCB(message); + gst_message_unref(message); + } + + gst_object_unref(bus); +} +#endif + // When we finish our pipeline will look like this: // // +-->queue-->decoder-->_videosink @@ -251,13 +279,15 @@ void VideoReceiver::start() dataSource = demux = parser = queue = decoder = NULL; - GstBus* bus = 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; - } +// if ((bus = gst_pipeline_get_bus(GST_PIPELINE(_pipeline))) != NULL) { +// gst_bus_add_watch(bus, _onBusMessage, this); +// gst_object_unref(bus); +// bus = NULL; +// } + // Workaround for above watch on Windows + _busCheckTimer.start(0); running = gst_element_set_state(_pipeline, GST_STATE_PLAYING) != GST_STATE_CHANGE_FAILURE; @@ -317,6 +347,7 @@ void VideoReceiver::stop() #if defined(QGC_GST_STREAMING) qCDebug(VideoReceiverLog) << "stop()"; if (_pipeline != NULL && !_stopping) { + _busCheckTimer.stop(); qCDebug(VideoReceiverLog) << "Stopping _pipeline"; gst_element_send_event(_pipeline, gst_event_new_eos()); _stopping = true; @@ -324,6 +355,7 @@ void VideoReceiver::stop() GstMessage* message = gst_bus_timed_pop_filtered(bus, GST_CLOCK_TIME_NONE, (GstMessageType)(GST_MESSAGE_EOS|GST_MESSAGE_ERROR)); gst_object_unref(bus); _onBusMessage(message); + gst_message_unref(message); } #endif } @@ -369,6 +401,7 @@ void VideoReceiver::_onBusMessage(GstMessage* msg) break; case GST_MESSAGE_STATE_CHANGED: _streaming = GST_STATE(_pipeline) == GST_STATE_PLAYING; + qCDebug(VideoReceiverLog) << "State changed, _streaming:" << _streaming; break; default: break; @@ -408,7 +441,12 @@ void VideoReceiver::startRecording(void) return; } - _sink = g_new0(Sink, 1); + if(_path.isEmpty()) { + qWarning() << "VideoReceiver::startRecording Empty Path!"; + return; + } + + _sink = new Sink(); _sink->teepad = gst_element_get_request_pad(_tee, "src_%u"); _sink->queue = gst_element_factory_make("queue", NULL); _sink->mux = gst_element_factory_make("matroskamux", NULL); @@ -420,15 +458,11 @@ void VideoReceiver::startRecording(void) return; } - QString fileName; - if(QSysInfo::WindowsVersion != QSysInfo::WV_None) { - fileName = _path + "\\QGC-" + QDateTime::currentDateTime().toString("yyyy-MM-dd-hh:mm:ss") + ".mkv"; - } else { - fileName = _path + "/QGC-" + QDateTime::currentDateTime().toString("yyyy-MM-dd-hh:mm:ss") + ".mkv"; - } + QString videoFile; + videoFile = _path + "/QGC-" + QDateTime::currentDateTime().toString("yyyy-MM-dd_hh.mm.ss") + ".mkv"; - g_object_set(G_OBJECT(_sink->filesink), "location", qPrintable(fileName), NULL); - qCDebug(VideoReceiverLog) << "New video file:" << fileName; + g_object_set(G_OBJECT(_sink->filesink), "location", qPrintable(videoFile), NULL); + qCDebug(VideoReceiverLog) << "New video file:" << videoFile; gst_object_ref(_sink->queue); gst_object_ref(_sink->mux); @@ -481,6 +515,7 @@ void VideoReceiver::_eosCB(GstMessage* message) gst_element_set_state(_pipelineStopRec, GST_STATE_NULL); gst_object_unref(_pipelineStopRec); + _pipelineStopRec = NULL; gst_element_set_state(_sink->filesink, GST_STATE_NULL); gst_element_set_state(_sink->mux, GST_STATE_NULL); @@ -492,8 +527,8 @@ void VideoReceiver::_eosCB(GstMessage* message) delete _sink; _sink = NULL; - _recording = false; + emit recordingChanged(); qCDebug(VideoReceiverLog) << "Recording Stopped"; } @@ -523,10 +558,12 @@ void VideoReceiver::_unlinkCB(GstPadProbeInfo* info) gst_element_link_many(_sink->queue, _sink->mux, _sink->filesink, NULL); // Add watch for EOS event - GstBus* bus = gst_pipeline_get_bus(GST_PIPELINE(_pipelineStopRec)); - gst_bus_add_signal_watch(bus); - g_signal_connect(bus, "message::eos", G_CALLBACK(_eosCallBack), this); - gst_object_unref(bus); +// GstBus* bus = gst_pipeline_get_bus(GST_PIPELINE(_pipelineStopRec)); +// gst_bus_add_signal_watch(bus); +// g_signal_connect(bus, "message::eos", G_CALLBACK(_eosCallBack), this); +// gst_object_unref(bus); + + // Above watch is handled by _busCheck now if(gst_element_set_state(_pipelineStopRec, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) { qCDebug(VideoReceiverLog) << "problem starting _pipelineStopRec"; diff --git a/src/VideoStreaming/VideoReceiver.h b/src/VideoStreaming/VideoReceiver.h index 8de7bb873..ad4437256 100644 --- a/src/VideoStreaming/VideoReceiver.h +++ b/src/VideoStreaming/VideoReceiver.h @@ -62,6 +62,7 @@ public slots: private slots: #if defined(QGC_GST_STREAMING) + void _busCheck (); void _timeout (); void _connected (); void _socketError (QAbstractSocket::SocketError socketError); @@ -85,6 +86,7 @@ private: bool _stopping; Sink* _sink; GstElement* _tee; + QTimer _busCheckTimer; void _onBusMessage(GstMessage* message); void _eosCB(GstMessage* message); diff --git a/src/ui/preferences/GeneralSettings.qml b/src/ui/preferences/GeneralSettings.qml index ba381f8f7..1fe8d5377 100644 --- a/src/ui/preferences/GeneralSettings.qml +++ b/src/ui/preferences/GeneralSettings.qml @@ -46,11 +46,7 @@ QGCView { title: "Choose a location to save video files." folder: shortcuts.home selectFolder: true - onAccepted: { - var path = fileDialog.fileUrl.toString(); - path = path.replace(/^(file:\/{2})/,""); - QGroundControl.videoManager.videoSavePath = path - } + onAccepted: QGroundControl.videoManager.setVideoSavePathByUrl(fileDialog.fileUrl) } QGCViewPanel { -- 2.22.0