From 7de745a8fbd9197fed3355691910ec6a48e4a906 Mon Sep 17 00:00:00 2001 From: Willian Galvani Date: Wed, 11 Mar 2020 20:12:59 -0300 Subject: [PATCH] Create lowLatencyMode setting --- src/VideoManager/VideoManager.cc | 50 ++++++++++++++++----------- src/VideoManager/VideoManager.h | 1 + src/VideoReceiver/GstVideoReceiver.cc | 16 +++++---- src/VideoReceiver/GstVideoReceiver.h | 3 +- src/VideoReceiver/VideoReceiver.h | 6 +++- 5 files changed, 47 insertions(+), 29 deletions(-) diff --git a/src/VideoManager/VideoManager.cc b/src/VideoManager/VideoManager.cc index b38188b00..5c11624b0 100644 --- a/src/VideoManager/VideoManager.cc +++ b/src/VideoManager/VideoManager.cc @@ -509,7 +509,7 @@ VideoManager::_tcpUrlChanged() void VideoManager::_lowLatencyModeChanged() { - //restartVideo(); + _restartAllVideos(); } //----------------------------------------------------------------------------- @@ -614,36 +614,43 @@ VideoManager::_updateSettings(unsigned id) { if(!_videoSettings) return false; + + const bool lowLatencyStreaming =_videoSettings->lowLatencyMode()->rawValue().toBool(); + + bool settingsChanged = _lowLatencyStreaming[id] != lowLatencyStreaming; + + _lowLatencyStreaming[id] = lowLatencyStreaming; + //-- Auto discovery + if(_activeVehicle && _activeVehicle->dynamicCameras()) { QGCVideoStreamInfo* pInfo = _activeVehicle->dynamicCameras()->currentStreamInstance(); if(pInfo) { - bool status = false; if (id == 0) { qCDebug(VideoManagerLog) << "Configure primary stream:" << pInfo->uri(); switch(pInfo->type()) { case VIDEO_STREAM_TYPE_RTSP: - if ((status = _updateVideoUri(id, pInfo->uri()))) { + if ((settingsChanged |= _updateVideoUri(id, pInfo->uri()))) { _toolbox->settingsManager()->videoSettings()->videoSource()->setRawValue(VideoSettings::videoSourceRTSP); } break; case VIDEO_STREAM_TYPE_TCP_MPEG: - if ((status = _updateVideoUri(id, pInfo->uri()))) { + if ((settingsChanged |= _updateVideoUri(id, pInfo->uri()))) { _toolbox->settingsManager()->videoSettings()->videoSource()->setRawValue(VideoSettings::videoSourceTCP); } break; case VIDEO_STREAM_TYPE_RTPUDP: - if ((status = _updateVideoUri(id, QStringLiteral("udp://0.0.0.0:%1").arg(pInfo->uri())))) { + if ((settingsChanged |= _updateVideoUri(id, QStringLiteral("udp://0.0.0.0:%1").arg(pInfo->uri())))) { _toolbox->settingsManager()->videoSettings()->videoSource()->setRawValue(VideoSettings::videoSourceUDPH264); } break; case VIDEO_STREAM_TYPE_MPEG_TS_H264: - if ((status = _updateVideoUri(id, QStringLiteral("mpegts://0.0.0.0:%1").arg(pInfo->uri())))) { + if ((settingsChanged |= _updateVideoUri(id, QStringLiteral("mpegts://0.0.0.0:%1").arg(pInfo->uri())))) { _toolbox->settingsManager()->videoSettings()->videoSource()->setRawValue(VideoSettings::videoSourceMPEGTS); } break; default: - status = _updateVideoUri(id, pInfo->uri()); + settingsChanged |= _updateVideoUri(id, pInfo->uri()); break; } } @@ -654,36 +661,36 @@ VideoManager::_updateSettings(unsigned id) switch(pTinfo->type()) { case VIDEO_STREAM_TYPE_RTSP: case VIDEO_STREAM_TYPE_TCP_MPEG: - status |= _updateVideoUri(id, pTinfo->uri()); + settingsChanged |= _updateVideoUri(id, pTinfo->uri()); break; case VIDEO_STREAM_TYPE_RTPUDP: - status |= _updateVideoUri(id, QStringLiteral("udp://0.0.0.0:%1").arg(pTinfo->uri())); + settingsChanged |= _updateVideoUri(id, QStringLiteral("udp://0.0.0.0:%1").arg(pTinfo->uri())); break; case VIDEO_STREAM_TYPE_MPEG_TS_H264: - status |= _updateVideoUri(id, QStringLiteral("mpegts://0.0.0.0:%1").arg(pTinfo->uri())); + settingsChanged |= _updateVideoUri(id, QStringLiteral("mpegts://0.0.0.0:%1").arg(pTinfo->uri())); break; default: - status |= _updateVideoUri(id, pTinfo->uri()); + settingsChanged |= _updateVideoUri(id, pTinfo->uri()); break; } } } - return status; + return settingsChanged; } } QString source = _videoSettings->videoSource()->rawValue().toString(); if (source == VideoSettings::videoSourceUDPH264) - return _updateVideoUri(0, QStringLiteral("udp://0.0.0.0:%1").arg(_videoSettings->udpPort()->rawValue().toInt())); + settingsChanged |= _updateVideoUri(0, QStringLiteral("udp://0.0.0.0:%1").arg(_videoSettings->udpPort()->rawValue().toInt())); else if (source == VideoSettings::videoSourceUDPH265) - return _updateVideoUri(0, QStringLiteral("udp265://0.0.0.0:%1").arg(_videoSettings->udpPort()->rawValue().toInt())); + settingsChanged |= _updateVideoUri(0, QStringLiteral("udp265://0.0.0.0:%1").arg(_videoSettings->udpPort()->rawValue().toInt())); else if (source == VideoSettings::videoSourceMPEGTS) - return _updateVideoUri(0, QStringLiteral("mpegts://0.0.0.0:%1").arg(_videoSettings->udpPort()->rawValue().toInt())); + settingsChanged |= _updateVideoUri(0, QStringLiteral("mpegts://0.0.0.0:%1").arg(_videoSettings->udpPort()->rawValue().toInt())); else if (source == VideoSettings::videoSourceRTSP) - return _updateVideoUri(0, _videoSettings->rtspUrl()->rawValue().toString()); + settingsChanged |= _updateVideoUri(0, _videoSettings->rtspUrl()->rawValue().toString()); else if (source == VideoSettings::videoSourceTCP) - return _updateVideoUri(0, QStringLiteral("tcp://%1").arg(_videoSettings->tcpUrl()->rawValue().toString())); + settingsChanged |= _updateVideoUri(0, QStringLiteral("tcp://%1").arg(_videoSettings->tcpUrl()->rawValue().toString())); - return false; + return settingsChanged; } //----------------------------------------------------------------------------- @@ -720,11 +727,14 @@ void VideoManager::_restartVideo(unsigned id) { #if defined(QGC_GST_STREAMING) + bool oldLowLatencyStreaming = _lowLatencyStreaming[id]; QString oldUri = _videoUri[id]; _updateSettings(id); + bool newLowLatencyStreaming = _lowLatencyStreaming[id]; QString newUri = _videoUri[id]; - if (oldUri == newUri && _videoStarted[id]) { + // FIXME: AV: use _updateSettings() result to check if settings were changed + if (oldUri == newUri && oldLowLatencyStreaming == newLowLatencyStreaming && _videoStarted[id]) { qCDebug(VideoManagerLog) << "No sense to restart video streaming, skipped" << id; return; } @@ -758,7 +768,7 @@ VideoManager::_startReceiver(unsigned id) qCDebug(VideoManagerLog) << "Unsupported receiver id" << id; } else if (_videoReceiver[id] != nullptr/* && _videoSink[id] != nullptr*/) { if (!_videoUri[id].isEmpty()) { - _videoReceiver[id]->start(_videoUri[id], timeout); + _videoReceiver[id]->start(_videoUri[id], timeout, _lowLatencyStreaming[id] ? -1 : 0); } } #endif diff --git a/src/VideoManager/VideoManager.h b/src/VideoManager/VideoManager.h index 3eadcbab3..285aad96d 100644 --- a/src/VideoManager/VideoManager.h +++ b/src/VideoManager/VideoManager.h @@ -164,6 +164,7 @@ protected: // 3) Qt rendering thread (during video sink creation process which should happen in this thread) // It works for now but... bool _videoStarted[2] = { false, false }; + bool _lowLatencyStreaming[2] = { false, false }; QAtomicInteger _streaming = false; QAtomicInteger _decoding = false; QAtomicInteger _recording = false; diff --git a/src/VideoReceiver/GstVideoReceiver.cc b/src/VideoReceiver/GstVideoReceiver.cc index 28c7e855e..2dfb78e16 100644 --- a/src/VideoReceiver/GstVideoReceiver.cc +++ b/src/VideoReceiver/GstVideoReceiver.cc @@ -68,12 +68,12 @@ GstVideoReceiver::~GstVideoReceiver(void) } void -GstVideoReceiver::start(const QString& uri, unsigned timeout) +GstVideoReceiver::start(const QString& uri, unsigned timeout, int buffer) { if (_needDispatch()) { QString cachedUri = uri; - _slotHandler.dispatch([this, cachedUri, timeout]() { - start(cachedUri, timeout); + _slotHandler.dispatch([this, cachedUri, timeout, buffer]() { + start(cachedUri, timeout, buffer); }); return; } @@ -95,13 +95,13 @@ GstVideoReceiver::start(const QString& uri, unsigned timeout) } _uri = uri; + _timeout = timeout; + _buffer = buffer; - qCDebug(VideoReceiverLog) << "Starting" << _uri; + qCDebug(VideoReceiverLog) << "Starting" << _uri << ", buffer" << _buffer; _endOfStream = false; - _timeout = timeout; - bool running = false; bool pipelineUp = false; @@ -791,7 +791,7 @@ GstVideoReceiver::_makeSource(const QString& uri) gst_element_foreach_src_pad(source, _padProbe, &probeRes); if (probeRes & 1) { - if (probeRes & 2) { + if (probeRes & 2 && _buffer >= 0) { if ((buffer = gst_element_factory_make("rtpjitterbuffer", nullptr)) == nullptr) { qCCritical(VideoReceiverLog) << "gst_element_factory_make('rtpjitterbuffer') failed"; break; @@ -1096,6 +1096,8 @@ GstVideoReceiver::_addVideoSink(GstPad* pad) gst_element_sync_state_with_parent(_videoSink); + g_object_set(_videoSink, "sync", _buffer >= 0, NULL); + GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(_pipeline), GST_DEBUG_GRAPH_SHOW_ALL, "pipeline-with-videosink"); if (caps != nullptr) { diff --git a/src/VideoReceiver/GstVideoReceiver.h b/src/VideoReceiver/GstVideoReceiver.h index 024a722b7..e9b00b7a4 100644 --- a/src/VideoReceiver/GstVideoReceiver.h +++ b/src/VideoReceiver/GstVideoReceiver.h @@ -89,7 +89,7 @@ public: ~GstVideoReceiver(void); public slots: - virtual void start(const QString& uri, unsigned timeout); + virtual void start(const QString& uri, unsigned timeout, int buffer = 0); virtual void stop(void); virtual void startDecoding(void* sink); virtual void stopDecoding(void); @@ -160,6 +160,7 @@ protected: QString _uri; unsigned _timeout; + int _buffer; Worker _slotHandler; uint32_t _signalDepth; diff --git a/src/VideoReceiver/VideoReceiver.h b/src/VideoReceiver/VideoReceiver.h index 4ec114fa9..7e2a272d3 100644 --- a/src/VideoReceiver/VideoReceiver.h +++ b/src/VideoReceiver/VideoReceiver.h @@ -64,7 +64,11 @@ signals: void onTakeScreenshotComplete(STATUS status); public slots: - virtual void start(const QString& uri, unsigned timeout) = 0; + // buffer: + // -1 - disable buffer and video sync + // 0 - default buffer length + // N - buffer length, ms + virtual void start(const QString& uri, unsigned timeout, int buffer = 0) = 0; virtual void stop(void) = 0; virtual void startDecoding(void* sink) = 0; virtual void stopDecoding(void) = 0; -- 2.22.0