diff --git a/VideoReceiverApp/main.cpp b/VideoReceiverApp/main.cpp index a0b864afd418122cb5dcf66db160d4c0288e93db..81711133f3300ab13a5253c684e2d5fc85afa51d 100644 --- a/VideoReceiverApp/main.cpp +++ b/VideoReceiverApp/main.cpp @@ -155,6 +155,9 @@ private: unsigned int _fileFormat = VideoReceiver::FILE_FORMAT_MIN; unsigned _stopRecordingAfter = 15; bool _useFakeSink = false; + bool _streaming = false; + bool _decoding = false; + bool _recording = false; }; void @@ -303,7 +306,7 @@ VideoReceiverApp::exec() qCDebug(AppLog) << "Streaming timeout"; _dispatch([this](){ - if (_receiver->streaming()) { + if (_streaming) { _receiver->stop(); } else { if (--_connect > 0) { @@ -320,8 +323,9 @@ VideoReceiverApp::exec() }); }); - QObject::connect(_receiver, &VideoReceiver::streamingChanged, [this](){ - if (_receiver->streaming()) { + QObject::connect(_receiver, &VideoReceiver::streamingChanged, [this](bool active){ + _streaming = active; + if (_streaming) { qCDebug(AppLog) << "Streaming started"; } else { qCDebug(AppLog) << "Streaming stopped"; @@ -338,13 +342,14 @@ VideoReceiverApp::exec() } }); - QObject::connect(_receiver, &VideoReceiver::decodingChanged, [this](){ - if (_receiver->decoding()) { + QObject::connect(_receiver, &VideoReceiver::decodingChanged, [this](bool active){ + _decoding = active; + if (_decoding) { qCDebug(AppLog) << "Decoding started"; } else { qCDebug(AppLog) << "Decoding stopped"; - if (_receiver->streaming()) { - if (!_receiver->recording()) { + if (_streaming) { + if (!_recording) { _dispatch([this](){ _receiver->stop(); }); @@ -353,13 +358,14 @@ VideoReceiverApp::exec() } }); - QObject::connect(_receiver, &VideoReceiver::recordingChanged, [this](){ - if (_receiver->recording()) { + QObject::connect(_receiver, &VideoReceiver::recordingChanged, [this](bool active){ + _recording = active; + if (_recording) { qCDebug(AppLog) << "Recording started"; } else { qCDebug(AppLog) << "Recording stopped"; - if (_receiver->streaming()) { - if (!_receiver->decoding()) { + if (_streaming) { + if (!_decoding) { _dispatch([this](){ _receiver->stop(); }); diff --git a/custom-example/res/CustomCameraControl.qml b/custom-example/res/CustomCameraControl.qml index 64a2b66276dba19cef5fcb5737c4b9289738a7dd..d28d336c19fc8051bf3baa7802133406a247cb3f 100644 --- a/custom-example/res/CustomCameraControl.qml +++ b/custom-example/res/CustomCameraControl.qml @@ -44,8 +44,8 @@ Item { property real _labelFieldWidth: ScreenTools.defaultFontPixelWidth * 28 property real _editFieldWidth: ScreenTools.defaultFontPixelWidth * 30 property real _editFieldHeight: ScreenTools.defaultFontPixelHeight * 2 - property var _videoReceiver: QGroundControl.videoManager.videoReceiver - property bool _recordingLocalVideo: _videoReceiver && _videoReceiver.recording + property var _videoManager: QGroundControl.videoManager + property bool _recordingLocalVideo: QGroundControl.videoManager.recording property var _dynamicCameras: activeVehicle ? activeVehicle.dynamicCameras : null property bool _isCamera: _dynamicCameras ? _dynamicCameras.cameras.count > 0 : false @@ -305,15 +305,15 @@ Item { _camera.stopVideo() //-- Local video as well if (_recordingVideo) { - _videoReceiver.stopRecording() + _videoManager.stopRecording() } } else { if(!_fullSD) { _camera.startVideo() } //-- Local video as well - if(_videoReceiver) { - _videoReceiver.startRecording() + if(_videoManager) { + _videoManager.startRecording() } } } else { diff --git a/src/FlightDisplay/FlightDisplayViewVideo.qml b/src/FlightDisplay/FlightDisplayViewVideo.qml index b85c85dd778c4fa1e39738ab2a38ef7b97106df0..3e71ed2efc5bac7133925716bb8aa3e4c01edffd 100644 --- a/src/FlightDisplay/FlightDisplayViewVideo.qml +++ b/src/FlightDisplay/FlightDisplayViewVideo.qml @@ -25,7 +25,6 @@ Item { clip: true property double _ar: QGroundControl.videoManager.aspectRatio property bool _showGrid: QGroundControl.settingsManager.videoSettings.gridLines.rawValue > 0 - property var _videoReceiver: QGroundControl.videoManager.videoReceiver property var _dynamicCameras: activeVehicle ? activeVehicle.dynamicCameras : null property bool _connected: activeVehicle ? !activeVehicle.connectionLost : false property int _curCameraIndex: _dynamicCameras ? _dynamicCameras.currentCamera : 0 @@ -40,7 +39,7 @@ Item { id: noVideo anchors.fill: parent color: Qt.rgba(0,0,0,0.75) - visible: !(_videoReceiver && _videoReceiver.decoding) + visible: !(QGroundControl.videoManager.decoding) QGCLabel { text: QGroundControl.settingsManager.videoSettings.streamEnabled.rawValue ? qsTr("WAITING FOR VIDEO") : qsTr("VIDEO DISABLED") font.family: ScreenTools.demiboldFontFamily @@ -58,7 +57,7 @@ Item { Rectangle { anchors.fill: parent color: "black" - visible: _videoReceiver && _videoReceiver.decoding + visible: QGroundControl.videoManager.decoding function getWidth() { //-- Fit Width or Stretch if(_fitMode === 0 || _fitMode === 2) { @@ -129,7 +128,7 @@ Item { height: parent.getHeight() width: parent.getWidth() anchors.centerIn: parent - visible: _videoReceiver && _videoReceiver.decoding + visible: QGroundControl.videoManager.decoding sourceComponent: videoBackgroundComponent property bool videoDisabled: QGroundControl.settingsManager.videoSettings.videoSource.rawValue === QGroundControl.settingsManager.videoSettings.disabledVideoSource diff --git a/src/FlightMap/Widgets/VideoPageWidget.qml b/src/FlightMap/Widgets/VideoPageWidget.qml index 651b27a092602b896f8508d98fe64f096503598c..d6c1e01ba36869f4213ff77a8bc29ad17caacb14 100644 --- a/src/FlightMap/Widgets/VideoPageWidget.qml +++ b/src/FlightMap/Widgets/VideoPageWidget.qml @@ -31,9 +31,8 @@ Item { anchors.centerIn: parent property bool _communicationLost: activeVehicle ? activeVehicle.connectionLost : false - property var _videoReceiver: QGroundControl.videoManager.videoReceiver - property bool _recordingVideo: _videoReceiver && _videoReceiver.recording - property bool _decodingVideo: _videoReceiver && _videoReceiver.decoding + property bool _recordingVideo: QGroundControl.videoManager.recording + property bool _decodingVideo: QGroundControl.videoManager.decoding property bool _streamingEnabled: QGroundControl.settingsManager.videoSettings.streamConfigured property var _dynamicCameras: activeVehicle ? activeVehicle.dynamicCameras : null property int _curCameraIndex: _dynamicCameras ? _dynamicCameras.currentCamera : 0 @@ -70,10 +69,10 @@ Item { onClicked: { if(checked) { QGroundControl.settingsManager.videoSettings.streamEnabled.rawValue = 1 - _videoReceiver.start() + QGroundControl.videoManager.startVideo() } else { QGroundControl.settingsManager.videoSettings.streamEnabled.rawValue = 0 - _videoReceiver.stop() + QGroundControl.videoManager.stopVideo() } } } diff --git a/src/VideoManager/VideoManager.cc b/src/VideoManager/VideoManager.cc index b3cc9eaf93e7fcc38da5c6774145cf264892d4c1..250e36fa8125cb01429924ff00494bff0b09485b 100644 --- a/src/VideoManager/VideoManager.cc +++ b/src/VideoManager/VideoManager.cc @@ -114,14 +114,39 @@ VideoManager::setToolbox(QGCToolbox *toolbox) _startReceiver(0); }); - connect(_videoReceiver, &VideoReceiver::streamingChanged, this, [this](){ - if (!_enableVideoRestart || _videoReceiver->streaming()) return; + connect(_videoReceiver, &VideoReceiver::streamingChanged, this, [this](bool active){ + _streaming = active; + emit streamingChanged(); + if (!_enableVideoRestart || active) return; _startReceiver(0); }); - connect(_videoReceiver, &VideoReceiver::recordingStarted, this, &VideoManager::_recordingStarted); - connect(_videoReceiver, &VideoReceiver::recordingChanged, this, &VideoManager::_recordingChanged); - connect(_videoReceiver, &VideoReceiver::onTakeScreenshotComplete, this, &VideoManager::_onTakeScreenshotComplete); + connect(_videoReceiver, &VideoReceiver::decodingChanged, this, [this](bool active){ + _decoding = active; + emit decodingChanged(); + }); + + connect(_videoReceiver, &VideoReceiver::recordingChanged, this, [this](bool active){ + _recording = active; + if (!active) { + _subtitleWriter.stopCapturingTelemetry(); + } + emit recordingChanged(); + }); + + connect(_videoReceiver, &VideoReceiver::recordingStarted, this, [this](){ + _subtitleWriter.startCapturingTelemetry(_videoFile); + }); + + connect(_videoReceiver, &VideoReceiver::videoSizeChanged, this, [this](QSize size){ + _videoSize = ((quint32)size.width() << 16) | (quint32)size.height(); + emit videoSizeChanged(); + }); + + connect(_videoReceiver, &VideoReceiver::onTakeScreenshotComplete, this, [this](VideoReceiver::STATUS status){ + if (status == VideoReceiver::STATUS_OK) { + } + }); // FIXME: AV: I believe _thermalVideoReceiver should be handled just like _videoReceiver in terms of event // and I expect that it will be changed during multiple video stream activity @@ -131,8 +156,8 @@ VideoManager::setToolbox(QGCToolbox *toolbox) _startReceiver(1); }); - connect(_thermalVideoReceiver, &VideoReceiver::streamingChanged, this, [this](){ - if (!_enableVideoRestart) return; + connect(_thermalVideoReceiver, &VideoReceiver::streamingChanged, this, [this](bool active){ + if (!_enableVideoRestart || active) return; _startReceiver(1); }); } @@ -668,30 +693,6 @@ VideoManager::_restartVideo() #endif } -//----------------------------------------------------------------------------- -void -VideoManager::_recordingStarted() -{ - _subtitleWriter.startCapturingTelemetry(_videoFile); -} - -//----------------------------------------------------------------------------- -void -VideoManager::_recordingChanged() -{ -#if defined(QGC_GST_STREAMING) - if (_videoReceiver && !_videoReceiver->recording()) { - _subtitleWriter.stopCapturingTelemetry(); - } -#endif -} - -//---------------------------------------------------------------------------------------- -void -VideoManager::_onTakeScreenshotComplete(VideoReceiver::STATUS status) -{ -} - //---------------------------------------------------------------------------------------- void VideoManager::_startReceiver(unsigned id) diff --git a/src/VideoManager/VideoManager.h b/src/VideoManager/VideoManager.h index faf5535611c32a637f1a33100b882db45f49f746..baeb0585029a37d210135b200c48c5bbf98af004 100644 --- a/src/VideoManager/VideoManager.h +++ b/src/VideoManager/VideoManager.h @@ -51,6 +51,10 @@ public: Q_PROPERTY(bool autoStreamConfigured READ autoStreamConfigured NOTIFY autoStreamConfiguredChanged) Q_PROPERTY(bool hasThermal READ hasThermal NOTIFY aspectRatioChanged) Q_PROPERTY(QString imageFile READ imageFile NOTIFY imageFileChanged) + Q_PROPERTY(bool streaming READ streaming NOTIFY streamingChanged) + Q_PROPERTY(bool decoding READ decoding NOTIFY decodingChanged) + Q_PROPERTY(bool recording READ recording NOTIFY recordingChanged) + Q_PROPERTY(QSize videoSize READ videoSize NOTIFY videoSizeChanged) virtual bool hasVideo (); virtual bool isGStreamer (); @@ -65,7 +69,25 @@ public: virtual bool hasThermal (); virtual QString imageFile (); + bool streaming(void) { + return _streaming; + } + bool decoding(void) { + return _decoding; + } + + bool recording(void) { + return _recording; + } + + QSize videoSize(void) { + const quint32 size = _videoSize; + return QSize((size >> 16) & 0xFFFF, size & 0xFFFF); + } + +// FIXME: AV: they should be removed after finishing multiple video stream support +// new arcitecture does not assume direct access to video receiver from QML side, even if it works for now virtual VideoReceiver* videoReceiver () { return _videoReceiver; } virtual VideoReceiver* thermalVideoReceiver () { return _thermalVideoReceiver; } @@ -99,6 +121,11 @@ signals: void aspectRatioChanged (); void autoStreamConfiguredChanged(); void imageFileChanged (); + void streamingChanged (); + void decodingChanged (); + void recordingChanged (); + void recordingStarted (); + void videoSizeChanged (); protected slots: void _videoSourceChanged (); @@ -120,28 +147,29 @@ protected: bool _updateThermalVideoUri (const QString& uri); void _cleanupOldVideos (); void _restartVideo (); - void _recordingStarted (); - void _recordingChanged (); - void _onTakeScreenshotComplete (VideoReceiver::STATUS status); void _startReceiver (unsigned id); void _stopReceiver (unsigned id); protected: - QString _videoFile; - QString _imageFile; - SubtitleWriter _subtitleWriter; - bool _isTaisync = false; - VideoReceiver* _videoReceiver = nullptr; - VideoReceiver* _thermalVideoReceiver = nullptr; - bool _enableVideoRestart = false; - void* _videoSink = nullptr; - void* _thermalVideoSink = nullptr; - VideoSettings* _videoSettings = nullptr; - QString _videoUri; - QString _thermalVideoUri; - QString _videoSourceID; - bool _fullScreen = false; - Vehicle* _activeVehicle = nullptr; + QString _videoFile; + QString _imageFile; + SubtitleWriter _subtitleWriter; + bool _isTaisync = false; + VideoReceiver* _videoReceiver = nullptr; + QAtomicInteger _streaming = false; + QAtomicInteger _decoding = false; + QAtomicInteger _recording = false; + QAtomicInteger _videoSize = 0; + VideoReceiver* _thermalVideoReceiver = nullptr; + bool _enableVideoRestart = false; + void* _videoSink = nullptr; + void* _thermalVideoSink = nullptr; + VideoSettings* _videoSettings = nullptr; + QString _videoUri; + QString _thermalVideoUri; + QString _videoSourceID; + bool _fullScreen = false; + Vehicle* _activeVehicle = nullptr; }; #endif diff --git a/src/VideoReceiver/GstVideoReceiver.cc b/src/VideoReceiver/GstVideoReceiver.cc index 857c6fef48762af342592bed54a0cf19968af983..abed163165d1d32c86131fbf6e0e93205c80c635 100644 --- a/src/VideoReceiver/GstVideoReceiver.cc +++ b/src/VideoReceiver/GstVideoReceiver.cc @@ -35,6 +35,9 @@ QGC_LOGGING_CATEGORY(VideoReceiverLog, "VideoReceiverLog") GstVideoReceiver::GstVideoReceiver(QObject* parent) : VideoReceiver(parent) + , _streaming(false) + , _decoding(false) + , _recording(false) , _removingDecoder(false) , _removingRecorder(false) , _source(nullptr) @@ -319,7 +322,7 @@ GstVideoReceiver::stop(void) _streaming = false; qCDebug(VideoReceiverLog) << "Streaming stopped"; _dispatchSignal([this](){ - emit streamingChanged(); + emit streamingChanged(_streaming); }); } else { qCDebug(VideoReceiverLog) << "Streaming did not start"; @@ -533,7 +536,7 @@ GstVideoReceiver::startRecording(const QString& videoFile, FILE_FORMAT format) qCDebug(VideoReceiverLog) << "Recording started"; _dispatchSignal([this](){ emit onStartRecordingComplete(STATUS_OK); - emit recordingChanged(); + emit recordingChanged(_recording); }); } @@ -934,7 +937,7 @@ GstVideoReceiver::_onNewSourcePad(GstPad* pad) _streaming = true; qCDebug(VideoReceiverLog) << "Streaming started"; _dispatchSignal([this](){ - emit streamingChanged(); + emit streamingChanged(_streaming); }); } @@ -1049,19 +1052,23 @@ GstVideoReceiver::_addVideoSink(GstPad* pad) gint width, height; gst_structure_get_int(s, "width", &width); gst_structure_get_int(s, "height", &height); - _setVideoSize(QSize(width, height)); + _dispatchSignal([this, width, height](){ + emit videoSizeChanged(QSize(width, height)); + }); } gst_caps_unref(caps); caps = nullptr; } else { - _setVideoSize(QSize(0, 0)); + _dispatchSignal([this](){ + emit videoSizeChanged(QSize(0, 0)); + }); } _decoding = true; qCDebug(VideoReceiverLog) << "Decoding started"; _dispatchSignal([this](){ - emit decodingChanged(); + emit decodingChanged(_decoding); }); return true; @@ -1181,7 +1188,7 @@ GstVideoReceiver::_shutdownDecodingBranch(void) _decoding = false; qCDebug(VideoReceiverLog) << "Decoding stopped"; _dispatchSignal([this](){ - emit decodingChanged(); + emit decodingChanged(_decoding); }); } @@ -1202,7 +1209,7 @@ GstVideoReceiver::_shutdownRecordingBranch(void) _recording = false; qCDebug(VideoReceiverLog) << "Recording stopped"; _dispatchSignal([this](){ - emit recordingChanged(); + emit recordingChanged(_recording); }); } diff --git a/src/VideoReceiver/GstVideoReceiver.h b/src/VideoReceiver/GstVideoReceiver.h index c59dbdab09787ee64c55fb26cca43ff2753a25ee..13b38330f158a77c8c56bf47d481b5e5ffb63cc9 100644 --- a/src/VideoReceiver/GstVideoReceiver.h +++ b/src/VideoReceiver/GstVideoReceiver.h @@ -102,11 +102,6 @@ protected slots: virtual void _handleEOS(void); protected: - void _setVideoSize(const QSize& size) { - _videoSize = ((quint32)size.width() << 16) | (quint32)size.height(); - emit videoSizeChanged(); - } - virtual GstElement* _makeSource(const QString& uri); virtual GstElement* _makeDecoder(GstCaps* caps, GstElement* videoSink); virtual GstElement* _makeFileSink(const QString& videoFile, FILE_FORMAT format); @@ -140,6 +135,9 @@ private: static GstPadProbeReturn _eosProbe(GstPad* pad, GstPadProbeInfo* info, gpointer user_data); static GstPadProbeReturn _keyframeWatch(GstPad* pad, GstPadProbeInfo* info, gpointer user_data); + bool _streaming; + bool _decoding; + bool _recording; bool _removingDecoder; bool _removingRecorder; GstElement* _source; diff --git a/src/VideoReceiver/VideoReceiver.h b/src/VideoReceiver/VideoReceiver.h index 92015c3f71e5b76d35f217ecde6ee32282c9ce3e..4ec114fa9fa6d942957d9c215e4beb174003c99e 100644 --- a/src/VideoReceiver/VideoReceiver.h +++ b/src/VideoReceiver/VideoReceiver.h @@ -17,9 +17,6 @@ #include #include -#include - -#include class VideoReceiver : public QObject { @@ -28,10 +25,6 @@ class VideoReceiver : public QObject public: explicit VideoReceiver(QObject* parent = nullptr) : QObject(parent) - , _streaming(false) - , _decoding(false) - , _recording(false) - , _videoSize(0) {} virtual ~VideoReceiver(void) {} @@ -54,35 +47,13 @@ public: Q_ENUM(STATUS) - Q_PROPERTY(bool streaming READ streaming NOTIFY streamingChanged) - Q_PROPERTY(bool decoding READ decoding NOTIFY decodingChanged) - Q_PROPERTY(bool recording READ recording NOTIFY recordingChanged) - Q_PROPERTY(QSize videoSize READ videoSize NOTIFY videoSizeChanged) - - bool streaming(void) { - return _streaming; - } - - bool decoding(void) { - return _decoding; - } - - bool recording(void) { - return _recording; - } - - QSize videoSize(void) { - const quint32 size = _videoSize; - return QSize((size >> 16) & 0xFFFF, size & 0xFFFF); - } - signals: void timeout(void); - void streamingChanged(void); - void decodingChanged(void); - void recordingChanged(void); + void streamingChanged(bool active); + void decodingChanged(bool active); + void recordingChanged(bool active); void recordingStarted(void); - void videoSizeChanged(void); + void videoSizeChanged(QSize size); void onStartComplete(STATUS status); void onStopComplete(STATUS status); @@ -100,11 +71,4 @@ public slots: virtual void startRecording(const QString& videoFile, FILE_FORMAT format) = 0; virtual void stopRecording(void) = 0; virtual void takeScreenshot(const QString& imageFile) = 0; - -protected: - std::atomic _streaming; - std::atomic _decoding; - std::atomic _recording; - std::atomic_videoSize; }; -