Commit c9885e23 authored by Jacob Walser's avatar Jacob Walser

Pop messages off gstreamer bus manually

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