diff --git a/src/Settings/Video.SettingsGroup.json b/src/Settings/Video.SettingsGroup.json index 4b5a6cc..c9cd28a 100644 --- a/src/Settings/Video.SettingsGroup.json +++ b/src/Settings/Video.SettingsGroup.json @@ -117,5 +117,12 @@ "longDescription": "Disable Video Stream when disarmed.", "type": "bool", "defaultValue": false +}, +{ + "name": "lowLatencyMode", + "shortDescription": "Tweaks video for lower latency", + "longDescription": "If this option is enabled, the rtpjitterbuffer is removed and the video sink is set to assynchronous mode, reducing the latency by about 200 ms.", + "type": "bool", + "defaultValue": false } ] diff --git a/src/Settings/VideoSettings.cc b/src/Settings/VideoSettings.cc index 08fb41d..587d8e9 100644 --- a/src/Settings/VideoSettings.cc +++ b/src/Settings/VideoSettings.cc @@ -82,6 +82,7 @@ DECLARE_SETTINGSFACT(VideoSettings, enableStorageLimit) DECLARE_SETTINGSFACT(VideoSettings, rtspTimeout) DECLARE_SETTINGSFACT(VideoSettings, streamEnabled) DECLARE_SETTINGSFACT(VideoSettings, disableWhenDisarmed) +DECLARE_SETTINGSFACT(VideoSettings, lowLatencyMode) DECLARE_SETTINGSFACT_NO_FUNC(VideoSettings, videoSource) { diff --git a/src/Settings/VideoSettings.h b/src/Settings/VideoSettings.h index e8864f2..3cb6648 100644 --- a/src/Settings/VideoSettings.h +++ b/src/Settings/VideoSettings.h @@ -34,6 +34,7 @@ public: DEFINE_SETTINGFACT(rtspTimeout) DEFINE_SETTINGFACT(streamEnabled) DEFINE_SETTINGFACT(disableWhenDisarmed) + DEFINE_SETTINGFACT(lowLatencyMode) Q_PROPERTY(bool streamConfigured READ streamConfigured NOTIFY streamConfiguredChanged) Q_PROPERTY(QString rtspVideoSource READ rtspVideoSource CONSTANT) diff --git a/src/VideoStreaming/VideoManager.cc b/src/VideoStreaming/VideoManager.cc index 7fd2ef1..db49828 100644 --- a/src/VideoStreaming/VideoManager.cc +++ b/src/VideoStreaming/VideoManager.cc @@ -60,6 +60,7 @@ VideoManager::setToolbox(QGCToolbox *toolbox) connect(_videoSettings->rtspUrl(), &Fact::rawValueChanged, this, &VideoManager::_rtspUrlChanged); connect(_videoSettings->tcpUrl(), &Fact::rawValueChanged, this, &VideoManager::_tcpUrlChanged); connect(_videoSettings->aspectRatio(), &Fact::rawValueChanged, this, &VideoManager::_aspectRatioChanged); + connect(_videoSettings->lowLatencyMode(),&Fact::rawValueChanged, this, &VideoManager::_lowLatencyModeChanged); MultiVehicleManager *pVehicleMgr = qgcApp()->toolbox()->multiVehicleManager(); connect(pVehicleMgr, &MultiVehicleManager::activeVehicleChanged, this, &VideoManager::_setActiveVehicle); @@ -229,6 +230,13 @@ VideoManager::_tcpUrlChanged() } //----------------------------------------------------------------------------- +void +VideoManager::_lowLatencyModeChanged() +{ + restartVideo(); +} + +//----------------------------------------------------------------------------- bool VideoManager::hasVideo() { diff --git a/src/VideoStreaming/VideoManager.h b/src/VideoStreaming/VideoManager.h index f53f282..10111bd 100644 --- a/src/VideoStreaming/VideoManager.h +++ b/src/VideoStreaming/VideoManager.h @@ -97,6 +97,7 @@ protected slots: void _udpPortChanged (); void _rtspUrlChanged (); void _tcpUrlChanged (); + void _lowLatencyModeChanged (); void _updateUVC (); void _setActiveVehicle (Vehicle* vehicle); void _aspectRatioChanged (); diff --git a/src/VideoStreaming/VideoReceiver.cc b/src/VideoStreaming/VideoReceiver.cc index 038b1a7..a6a95d9 100644 --- a/src/VideoStreaming/VideoReceiver.cc +++ b/src/VideoStreaming/VideoReceiver.cc @@ -395,7 +395,7 @@ VideoReceiver::_makeSource(const QString& uri) gst_element_foreach_src_pad(source, _padProbe, &probeRes); if (probeRes & 1) { - if (probeRes & 2) { + if (probeRes & 2 && !_videoSettings->lowLatencyMode()->rawValue().toBool()) { if ((buffer = gst_element_factory_make("rtpjitterbuffer", nullptr)) == nullptr) { qCCritical(VideoReceiverLog) << "gst_element_factory_make('rtpjitterbuffer') failed"; break; @@ -414,7 +414,11 @@ VideoReceiver::_makeSource(const QString& uri) } } } else { - g_signal_connect(source, "pad-added", G_CALLBACK(_linkPadWithOptionalBuffer), parser); + if (_videoSettings->lowLatencyMode()->rawValue().toBool()) { + g_signal_connect(source, "pad-added", G_CALLBACK(newPadCB), parser); + } else { + g_signal_connect(source, "pad-added", G_CALLBACK(_linkPadWithOptionalBuffer), parser); + } } g_signal_connect(parser, "pad-added", G_CALLBACK(_wrapWithGhostPad), nullptr); @@ -568,6 +572,9 @@ VideoReceiver::start() qCWarning(VideoReceiverLog) << "Failed because video sink is not set"; return; } + + g_object_set(_videoSink, "sync", !_videoSettings->lowLatencyMode()->rawValue().toBool(), NULL); + if(_running) { qCDebug(VideoReceiverLog) << "Already running!"; return; diff --git a/src/ui/preferences/GeneralSettings.qml b/src/ui/preferences/GeneralSettings.qml index 125a09b..54e02a5 100644 --- a/src/ui/preferences/GeneralSettings.qml +++ b/src/ui/preferences/GeneralSettings.qml @@ -1028,6 +1028,16 @@ Rectangle { fact: QGroundControl.settingsManager.videoSettings.disableWhenDisarmed visible: _isGst && QGroundControl.settingsManager.videoSettings.disableWhenDisarmed.visible } + + QGCLabel { + text: qsTr("Low Latency Mode") + visible: _isGst && QGroundControl.settingsManager.videoSettings.lowLatencyMode.visible + } + FactCheckBox { + text: "" + fact: QGroundControl.settingsManager.videoSettings.lowLatencyMode + visible: _isGst && QGroundControl.settingsManager.videoSettings.lowLatencyMode.visible + } } }