Commit f7be8bff authored by DoinLakeFlyer's avatar DoinLakeFlyer
Browse files

Merge remote-tracking branch 'origin/TerrainProfile' into TerrainProfile

parents ecb051f3 aa8a9ac6
......@@ -23,6 +23,7 @@ Item {
property var map ///< Map control to place item in
property var vehicle ///< Vehicle associated with this item
property var interactive: true ///< Vehicle associated with this item
signal clicked(int sequenceNumber)
......@@ -34,7 +35,7 @@ Item {
if (component.status === Component.Error) {
console.log("Error loading Qml: ", object.mapVisualQML, component.errorString())
}
_visualItem = component.createObject(map, { "map": _root.map, vehicle: _root.vehicle })
_visualItem = component.createObject(map, { "map": _root.map, vehicle: _root.vehicle, 'opacity': Qt.binding(function() { return _root.opacity }), 'interactive': Qt.binding(function() { return _root.interactive }) })
_visualItem.clicked.connect(_root.clicked)
}
}
......
......@@ -388,8 +388,9 @@ Item {
// This is the center rectangle of the map which is not obscured by tools
property rect centerViewport: Qt.rect(_leftToolWidth + _margin, _margin, editorMap.width - _leftToolWidth - _rightToolWidth - (_margin * 2), (terrainStatus.visible ? terrainStatus.y : height - _margin) - _margin)
property real _leftToolWidth: toolStrip.x + toolStrip.width
property real _rightToolWidth: rightPanel.width + rightPanel.anchors.rightMargin
property real _leftToolWidth: toolStrip.x + toolStrip.width
property real _rightToolWidth: rightPanel.width + rightPanel.anchors.rightMargin
property real _nonInteractiveOpacity: 0.5
// Initial map position duplicates Fly view position
Component.onCompleted: editorMap.center = QGroundControl.flightMapPosition
......@@ -436,18 +437,20 @@ Item {
// Add the mission item visuals to the map
Repeater {
model: _editingLayer == _layerMission ? _missionController.visualItems : undefined
model: _missionController.visualItems
delegate: MissionItemMapVisual {
map: editorMap
onClicked: _missionController.setCurrentPlanViewSeqNum(sequenceNumber, false)
visible: _editingLayer == _layerMission
opacity: _editingLayer == _layerMission ? 1 : editorMap._nonInteractiveOpacity
interactive: _editingLayer == _layerMission
}
}
// Add lines between waypoints
MissionLineView {
showSpecialVisual: _missionController.isROIBeginCurrentItem
model: _editingLayer == _layerMission ? _missionController.simpleFlightPathSegments : undefined
model: _missionController.simpleFlightPathSegments
opacity: _editingLayer == _layerMission ? 1 : editorMap._nonInteractiveOpacity
}
// Direction arrows in waypoint lines
......@@ -464,13 +467,14 @@ Item {
// Incomplete segment lines
MapItemView {
model: _editingLayer == _layerMission ? _missionController.incompleteComplexItemLines : undefined
model: _missionController.incompleteComplexItemLines
delegate: MapPolyline {
path: [ object.coordinate1, object.coordinate2 ]
line.width: 1
line.color: "red"
z: QGroundControl.zOrderWaypointLines
opacity: _editingLayer == _layerMission ? 1 : editorMap._nonInteractiveOpacity
}
}
......@@ -513,8 +517,7 @@ Item {
// Add the vehicles to the map
MapItemView {
model: QGroundControl.multiVehicleManager.vehicles
delegate:
VehicleMapItem {
delegate: VehicleMapItem {
vehicle: object
coordinate: object.coordinate
map: editorMap
......@@ -529,6 +532,7 @@ Item {
interactive: _editingLayer == _layerGeoFence
homePosition: _missionController.plannedHomePosition
planView: true
opacity: _editingLayer != _layerGeoFence ? editorMap._nonInteractiveOpacity : 1
}
RallyPointMapVisuals {
......@@ -536,6 +540,7 @@ Item {
myRallyPointController: _rallyPointController
interactive: _editingLayer == _layerRallyPoints
planView: true
opacity: _editingLayer != _layerRallyPoints ? editorMap._nonInteractiveOpacity : 1
}
// Airspace overlap support
......@@ -851,6 +856,7 @@ Item {
flightMap: editorMap
visible: _editingLayer == _layerGeoFence
}
// Rally Point Editor
RallyPointEditorHeader {
id: rallyPointHeader
......
......@@ -47,7 +47,7 @@ Item {
MissionItemIndicatorDrag {
mapControl: _root.map
itemCoordinate: rallyPointObject.coordinate
visible: rallyPointObject === myRallyPointController.currentRallyPoint
visible: rallyPointObject === myRallyPointController.currentRallyPoint && _root.interactive
property var rallyPointObject
......@@ -63,6 +63,7 @@ Item {
anchorPoint.x: sourceItem.anchorPointX
anchorPoint.y: sourceItem.anchorPointY
z: QGroundControl.zOrderMapItems
opacity: _root.opacity
property var rallyPointObject
......@@ -84,6 +85,7 @@ Item {
model: _rallyPoints
delegate: Item {
opacity: _root.opacity
property var _visuals: [ ]
Component.onCompleted: {
......
......@@ -24,6 +24,7 @@ Item {
property var map ///< Map control to place item in
property var vehicle ///< Vehicle associated with this item
property bool interactive: true
property var _missionItem: object
property var _itemVisual
......@@ -95,6 +96,7 @@ Item {
mapControl: _root.map
itemIndicator: _itemVisual
itemCoordinate: _missionItem.coordinate
visible: _root.interactive
onItemCoordinateChanged: _missionItem.coordinate = itemCoordinate
}
......@@ -109,7 +111,8 @@ Item {
z: QGroundControl.zOrderMapItems
missionItem: _missionItem
sequenceNumber: _missionItem.sequenceNumber
onClicked: _root.clicked(_missionItem.sequenceNumber)
onClicked: if(_root.interactive) _root.clicked(_missionItem.sequenceNumber)
opacity: _root.opacity
}
}
}
......@@ -27,6 +27,7 @@ Item {
property var _missionItem: object
property var _structurePolygon: object.structurePolygon
property var _flightPolygon: object.flightPolygon
property bool interactive: parent.interactive
signal clicked(int sequenceNumber)
......@@ -43,12 +44,12 @@ Item {
QGCMapPolygonVisuals {
mapControl: map
mapPolygon: _structurePolygon
interactive: _missionItem.isCurrentItem
interactive: _missionItem.isCurrentItem && _root.interactive
borderWidth: 1
borderColor: "black"
interiorColor: "green"
altColor: "red"
interiorOpacity: 0.25
interiorOpacity: 0.5 * _root.opacity
}
QGCMapPolygonVisuals {
......@@ -57,6 +58,7 @@ Item {
interactive: false
borderWidth: 2
borderColor: "white"
interiorOpacity: _root.opacity
}
// Entry point
......@@ -68,7 +70,7 @@ Item {
anchorPoint.y: sourceItem.anchorPointY
z: QGroundControl.zOrderMapItems
coordinate: _missionItem.coordinate
visible: _missionItem.exitCoordinate.isValid
visible: _missionItem.exitCoordinate.isValid && _root.interactive
sourceItem: MissionItemIndexLabel {
index: _missionItem.sequenceNumber
......@@ -88,7 +90,7 @@ Item {
anchorPoint.y: sourceItem.anchorPointY
z: QGroundControl.zOrderMapItems
coordinate: _missionItem.exitCoordinate
visible: _missionItem.exitCoordinate.isValid
visible: _missionItem.exitCoordinate.isValid && _root.interactive
sourceItem: MissionItemIndexLabel {
index: _missionItem.lastSequenceNumber
......
......@@ -24,6 +24,7 @@ Item {
property var map ///< Map control to place item in
property var vehicle ///< Vehicle associated with this item
property bool interactive: true
property var _missionItem: object
property var _takeoffIndicatorItem
......@@ -78,6 +79,7 @@ Item {
mapControl: _root.map
itemIndicator: _takeoffIndicatorItem
itemCoordinate: _missionItem.specifiesCoordinate ? _missionItem.coordinate : _missionItem.launchCoordinate
visible: _root.interactive
onItemCoordinateChanged: {
if (_missionItem.specifiesCoordinate) {
......@@ -96,7 +98,7 @@ Item {
mapControl: _root.map
itemIndicator: _launchIndicatorItem
itemCoordinate: _missionItem.launchCoordinate
visible: !_missionItem.launchTakeoffAtSameLocation
visible: !_missionItem.launchTakeoffAtSameLocation && _root.interactive
onItemCoordinateChanged: _missionItem.launchCoordinate = itemCoordinate
}
......@@ -111,6 +113,7 @@ Item {
missionItem: _missionItem
sequenceNumber: _missionItem.sequenceNumber
onClicked: _root.clicked(_missionItem.sequenceNumber)
opacity: _root.opacity
}
}
......@@ -121,7 +124,7 @@ Item {
coordinate: _missionItem.launchCoordinate
anchorPoint.x: sourceItem.anchorPointX
anchorPoint.y: sourceItem.anchorPointY
visible: !_missionItem.launchTakeoffAtSameLocation
visible: !_missionItem.launchTakeoffAtSameLocation && _root.interactive
sourceItem:
MissionItemIndexLabel {
......@@ -129,6 +132,7 @@ Item {
label: qsTr("Launch")
highlightSelected: true
onClicked: _root.clicked(_missionItem.sequenceNumber)
visible: _root.interactive
}
}
}
......@@ -140,7 +144,7 @@ Item {
MouseArea {
anchors.fill: map
z: QGroundControl.zOrderMapItems + 1 // Over item indicators
visible: !_missionItem.launchCoordinate.isValid
visible: !_missionItem.launchCoordinate.isValid && _root.interactive
readonly property int _decimalPlaces: 8
......
......@@ -24,6 +24,7 @@ Item {
property var map ///< Map control to place item in
property bool polygonInteractive: true
property bool interactive: true
property var _missionItem: object
property var _mapPolygon: object.surveyAreaPolygon
......@@ -70,12 +71,12 @@ Item {
id: mapPolygonVisuals
mapControl: map
mapPolygon: _mapPolygon
interactive: polygonInteractive && _missionItem.isCurrentItem
interactive: polygonInteractive && _missionItem.isCurrentItem && _root.interactive
borderWidth: 1
borderColor: "black"
interiorColor: QGroundControl.globalPalette.surveyPolygonInterior
altColor: QGroundControl.globalPalette.surveyPolygonTerrainCollision
interiorOpacity: 0.5
interiorOpacity: 0.5 * _root.opacity
}
// Full set of transects lines. Shown when item is selected.
......@@ -87,6 +88,7 @@ Item {
line.width: 2
path: _transectPoints
visible: _currentItem
opacity: _root.opacity
}
}
......@@ -99,6 +101,7 @@ Item {
line.width: 2
path: _showPartialEntryExit ? [ _transectPoints[0], _transectPoints[1] ] : []
visible: _showPartialEntryExit
opacity: _root.opacity
}
}
Component {
......@@ -109,6 +112,7 @@ Item {
line.width: 2
path: _showPartialEntryExit ? [ _transectPoints[_lastPointIndex - 1], _transectPoints[_lastPointIndex] ] : []
visible: _showPartialEntryExit
opacity: _root.opacity
}
}
......@@ -122,11 +126,12 @@ Item {
z: QGroundControl.zOrderMapItems
coordinate: _missionItem.coordinate
visible: _missionItem.exitCoordinate.isValid
opacity: _root.opacity
sourceItem: MissionItemIndexLabel {
index: _missionItem.sequenceNumber
checked: _missionItem.isCurrentItem
onClicked: _root.clicked(_missionItem.sequenceNumber)
onClicked: if(_root.interactive) _root.clicked(_missionItem.sequenceNumber)
}
}
}
......@@ -139,6 +144,7 @@ Item {
toCoord: _transectPoints[_firstTrueTransectIndex + 1]
arrowPosition: 1
visible: _currentItem
opacity: _root.opacity
}
}
......@@ -150,6 +156,7 @@ Item {
toCoord: _transectPoints[nextTrueTransectIndex + 1]
arrowPosition: 1
visible: _currentItem && _transectCount > 3
opacity: _root.opacity
property int nextTrueTransectIndex: _firstTrueTransectIndex + (_hasTurnaround ? 4 : 2)
}
......@@ -163,6 +170,7 @@ Item {
toCoord: _transectPoints[_lastTrueTransectIndex]
arrowPosition: 3
visible: _currentItem
opacity: _root.opacity
}
}
......@@ -174,6 +182,7 @@ Item {
toCoord: _transectPoints[prevTrueTransectIndex]
arrowPosition: 13
visible: _currentItem && _transectCount > 3
opacity: _root.opacity
property int prevTrueTransectIndex: _lastTrueTransectIndex - (_hasTurnaround ? 4 : 2)
}
......@@ -189,11 +198,12 @@ Item {
z: QGroundControl.zOrderMapItems
coordinate: _missionItem.exitCoordinate
visible: _missionItem.exitCoordinate.isValid
opacity: _root.opacity
sourceItem: MissionItemIndexLabel {
index: _missionItem.lastSequenceNumber
checked: _missionItem.isCurrentItem
onClicked: _root.clicked(_missionItem.sequenceNumber)
onClicked: if(_root.interactive) _root.clicked(_missionItem.sequenceNumber)
}
}
}
......
......@@ -11,7 +11,6 @@
#include <QApplication>
#include <QTimer>
#include <QQmlApplicationEngine>
#include <QElapsedTimer>
#include <QMap>
#include <QSet>
......@@ -38,6 +37,7 @@
#endif
// Work around circular header includes
class QQmlApplicationEngine;
class QGCSingleton;
class QGCToolbox;
class QGCFileDownload;
......
......@@ -11,6 +11,7 @@ import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.4
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.12
import QGroundControl 1.0
import QGroundControl.Palette 1.0
......@@ -29,35 +30,71 @@ Item {
id: filtersDialogComponent
QGCViewDialog {
QGCFlickable {
anchors.fill: parent
anchors.fill: parent
contentHeight: categoryColumn.height
clip: true
Column {
id: categoryColumn
spacing: ScreenTools.defaultFontPixelHeight / 2
QGCButton {
text: qsTr("Clear All")
onClicked: {
var logCats = QGroundControl.loggingCategories()
for (var i=0; i<logCats.length; i++) {
QGroundControl.setCategoryLoggingOn(logCats[i], false)
}
QGroundControl.updateLoggingFilterRules()
categoryRepeater.model = undefined
categoryRepeater.model = QGroundControl.loggingCategories()
ColumnLayout {
anchors.fill: parent
RowLayout {
spacing: ScreenTools.defaultFontPixelHeight / 2
Layout.alignment: Qt.AlignVCenter
Layout.fillHeight: true
Layout.fillWidth: true
QGCLabel {
text: qsTr("Search:")
}
QGCTextField {
id: searchText
text: ""
Layout.fillWidth: true
enabled: true
}
QGCButton {
text: qsTr("Clear")
onClicked: searchText.text = ""
}
}
Repeater {
id: categoryRepeater
model: QGroundControl.loggingCategories()
QGCCheckBox {
text: modelData
checked: QGroundControl.categoryLoggingOn(modelData)
onClicked: {
QGroundControl.setCategoryLoggingOn(modelData, checked)
Row {
spacing: ScreenTools.defaultFontPixelHeight / 2
QGCButton {
text: qsTr("Clear All")
onClicked: categoryRepeater.setAllLogs(false)
}
}
Column {
id: categoryColumn
spacing: ScreenTools.defaultFontPixelHeight / 2
Repeater {
id: categoryRepeater
model: QGroundControl.loggingCategories()
function setAllLogs(value) {
var logCategories = QGroundControl.loggingCategories()
for (var category of logCategories) {
QGroundControl.setCategoryLoggingOn(category, value)
}
QGroundControl.updateLoggingFilterRules()
// Update model for repeater
categoryRepeater.model = undefined
categoryRepeater.model = QGroundControl.loggingCategories()
}
QGCCheckBox {
text: modelData
visible: searchText.text ? text.match(`(${searchText.text})`, "i") : true
checked: QGroundControl.categoryLoggingOn(modelData)
onClicked: {
QGroundControl.setCategoryLoggingOn(modelData, checked)
QGroundControl.updateLoggingFilterRules()
}
}
}
}
......
This diff is collapsed.
......@@ -49,8 +49,12 @@ public:
Q_PROPERTY(double hfov READ hfov NOTIFY aspectRatioChanged)
Q_PROPERTY(double thermalHfov READ thermalHfov NOTIFY aspectRatioChanged)
Q_PROPERTY(bool autoStreamConfigured READ autoStreamConfigured NOTIFY autoStreamConfiguredChanged)
Q_PROPERTY(bool hasThermal READ hasThermal NOTIFY aspectRatioChanged)
Q_PROPERTY(bool hasThermal READ hasThermal NOTIFY decodingChanged)
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,9 +69,27 @@ public:
virtual bool hasThermal ();
virtual QString imageFile ();
bool streaming(void) {
return _streaming;
}
virtual VideoReceiver* videoReceiver () { return _videoReceiver; }
virtual VideoReceiver* thermalVideoReceiver () { return _thermalVideoReceiver; }
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[0]; }
virtual VideoReceiver* thermalVideoReceiver () { return _videoReceiver[1]; }
#if defined(QGC_DISABLE_UVC)
virtual bool uvcEnabled () { return false; }
......@@ -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 ();
......@@ -115,31 +142,37 @@ protected:
friend class FinishVideoInitialization;
void _initVideo ();
void _updateSettings ();
void _setVideoUri (const QString& uri);
void _setThermalVideoUri (const QString& uri);
bool _updateSettings (unsigned id);
bool _updateVideoUri (unsigned id, const QString& uri);
void _cleanupOldVideos ();
void _restartVideo ();
void _streamingChanged ();
void _recordingStarted ();
void _recordingChanged ();
void _screenshotComplete ();
void _restartAllVideos ();
void _restartVideo (unsigned id);
void _startReceiver (unsigned id);
void _stopReceiver (unsigned id);
protected:
QString _videoFile;
QString _imageFile;
SubtitleWriter _subtitleWriter;
bool _isTaisync = false;
VideoReceiver* _videoReceiver = nullptr;
VideoReceiver* _thermalVideoReceiver = nullptr;
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[2] = { nullptr, nullptr };
void* _videoSink[2] = { nullptr, nullptr };
QString _videoUri[2];
// FIXME: AV: _videoStarted seems to be access from 3 different threads, from time to time
// 1) Video Receiver thread
// 2) Video Manager/main app thread
// 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<bool> _streaming = false;
QAtomicInteger<bool> _decoding = false;
QAtomicInteger<bool> _recording = false;
QAtomicInteger<quint32> _videoSize = 0;
VideoSettings* _videoSettings = nullptr;
QString _videoSourceID;
bool _fullScreen = false;
Vehicle* _activeVehicle = nullptr;
};
#endif
......@@ -105,9 +105,28 @@ static void qgcputenv(const QString& key, const QString& root, const QString& pa
}
#endif
static void
blacklist()
{
GstRegistry* reg;
if ((reg = gst_registry_get()) == nullptr) {
return;
}
GstPluginFeature* plugin;
if ((plugin = gst_registry_lookup_feature(reg, "bcmdec")) != nullptr) {
qCCritical(GStreamerLog) << "Disable bcmdec";
gst_plugin_feature_set_rank(plugin, GST_RANK_NONE);
}
}
void
GStreamer::initialize(int argc, char* argv[], int debuglevel)
{
qRegisterMetaType<VideoReceiver::STATUS>("STATUS");
#ifdef Q_OS_MAC
#ifdef QGC_INSTALL_RELEASE
QString currentDir = QCoreApplication::applicationDirPath();
......@@ -171,6 +190,8 @@ GStreamer::initialize(int argc, char* argv[], int debuglevel)
gst_ios_post_init();
#endif
blacklist();
/* the plugin must be loaded before loading the qml file to register the
* GstGLVideoItem qml item
* FIXME Add a QQmlExtensionPlugin into qmlglsink to register GstGLVideoItem
......
This diff is collapsed.
......@@ -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);
......@@ -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);
......@@ -118,16 +113,19 @@ protected:
virtual void _noteTeeFrame(void);
virtual void _noteVideoSinkFrame(void);
virtual void _noteEndOfStream(void);
virtual void _unlinkBranch(GstElement* from);
virtual bool _unlinkBranch(GstElement* from);
virtual void _shutdownDecodingBranch (void);
virtual void _shutdownRecordingBranch(void);
private:
bool _needDispatch(void);
void _dispatchSignal(std::function<void()> emitter);
static gboolean _onBusMessage(GstBus* bus, GstMessage* message, gpointer user_data);
static void _onNewPad(GstElement* element, GstPad* pad, gpointer data);
static void _wrapWithGhostPad(GstElement* element, GstPad* pad, gpointer data);
static void _linkPadWithOptionalBuffer(GstElement* element, GstPad* pad, gpointer data);
static void _linkPad(GstElement* element, GstPad* pad, gpointer data);
static gboolean _padProbe(GstElement* element, GstPad* pad, gpointer user_data);
static gboolean _filterParserCaps(GstElement* bin, GstPad* pad, GstElement* element, GstQuery* query, gpointer data);
static gboolean _autoplugQueryCaps(GstElement* bin, GstPad* pad, GstElement* element, GstQuery* query, gpointer data);
static gboolean _autoplugQueryContext(GstElement* bin, GstPad* pad, GstElement* element, GstQuery* query, gpointer data);
static gboolean _autoplugQuery(GstElement* bin, GstPad* pad, GstElement* element, GstQuery* query, gpointer data);
......@@ -136,6 +134,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;
......@@ -157,10 +158,12 @@ private:
//-- RTSP UDP reconnect timeout
uint64_t _udpReconnect_us;
QString _uri;
unsigned _timeout;
int _buffer;
Worker _apiHandler;
Worker _notificationHandler;
Worker _slotHandler;
uint32_t _signalDepth;
bool _endOfStream;
......
......@@ -39,7 +39,7 @@ gst-launch-1.0 videotestsrc ! video/x-raw,width=640,height=480 ! videoconvert !
On the receiving end, if you want to test it from the command line, you can use something like:
```
gst-launch-1.0 udpsrc port=5600 caps='application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264' ! rtph264depay ! h264parse ! avdec_h264 ! autovideosink fps-update-interval=1000 sync=false
gst-launch-1.0 udpsrc port=5600 caps='application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264' ! rtpjitterbuffer ! rtph264depay ! h264parse ! avdec_h264 ! autovideosink fps-update-interval=1000 sync=false
```
### Additional Protocols
......
......@@ -17,9 +17,6 @@
#include <QObject>
#include <QSize>
#include <QQuickItem>
#include <atomic>
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) {}
......@@ -44,50 +37,42 @@ public:
FILE_FORMAT_MAX
} FILE_FORMAT;
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;
}
typedef enum {
STATUS_OK = 0,
STATUS_FAIL,
STATUS_INVALID_STATE,
STATUS_INVALID_URL,
STATUS_NOT_IMPLEMENTED
} STATUS;
QSize videoSize(void) {
const quint32 size = _videoSize;
return QSize((size >> 16) & 0xFFFF, size & 0xFFFF);
}
Q_ENUM(STATUS)
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 screenshotComplete(void);
void videoSizeChanged(QSize size);
void onStartComplete(STATUS status);
void onStopComplete(STATUS status);
void onStartDecodingComplete(STATUS status);
void onStopDecodingComplete(STATUS status);
void onStartRecordingComplete(STATUS status);
void onStopRecordingComplete(STATUS status);
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;
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<bool> _streaming;
std::atomic<bool> _decoding;
std::atomic<bool> _recording;
std::atomic<quint32>_videoSize;
};
......@@ -485,6 +485,15 @@ void* QGCCorePlugin::createVideoSink(QObject* parent, QQuickItem* widget)
#endif
}
void QGCCorePlugin::releaseVideoSink(void* sink)
{
#if defined(QGC_GST_STREAMING)
GStreamer::releaseVideoSink(sink);
#else
Q_UNUSED(sink)
#endif
}
bool QGCCorePlugin::guidedActionsControllerLogging() const
{
return GuidedActionsControllerLog().isDebugEnabled();
......
......@@ -119,6 +119,8 @@ public:
virtual VideoReceiver* createVideoReceiver(QObject* parent);
/// Allows the plugin to override the creation of VideoSink.
virtual void* createVideoSink(QObject* parent, QQuickItem* widget);
/// Allows the plugin to override the release of VideoSink.
virtual void releaseVideoSink(void* sink);
/// Allows the plugin to see all mavlink traffic to a vehicle
/// @return true: Allow vehicle to continue processing, false: Vehicle should not process message
......
Supports Markdown
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