Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Q
qgroundcontrol
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Valentin Platzgummer
qgroundcontrol
Commits
a8154e23
Commit
a8154e23
authored
Nov 27, 2017
by
Gus Grubba
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Video Stream Control Widget
parent
aeb0e8a7
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
176 additions
and
83 deletions
+176
-83
qgroundcontrol.qrc
qgroundcontrol.qrc
+1
-0
FlightDisplayView.qml
src/FlightDisplay/FlightDisplayView.qml
+0
-59
FlightDisplayViewVideo.qml
src/FlightDisplay/FlightDisplayViewVideo.qml
+1
-1
VideoPageWidget.qml
src/FlightMap/Widgets/VideoPageWidget.qml
+128
-0
PageView.qml
src/QmlControls/PageView.qml
+1
-1
VideoReceiver.cc
src/VideoStreaming/VideoReceiver.cc
+26
-16
VideoReceiver.h
src/VideoStreaming/VideoReceiver.h
+8
-3
QGCCorePlugin.cc
src/api/QGCCorePlugin.cc
+11
-3
No files found.
qgroundcontrol.qrc
View file @
a8154e23
...
...
@@ -179,6 +179,7 @@
<file alias="VehicleSummary.qml">src/VehicleSetup/VehicleSummary.qml</file>
<file alias="VirtualJoystick.qml">src/FlightDisplay/VirtualJoystick.qml</file>
<file alias="CameraPageWidget.qml">src/FlightMap/Widgets/CameraPageWidget.qml</file>
<file alias="VideoPageWidget.qml">src/FlightMap/Widgets/VideoPageWidget.qml</file>
<file alias="ValuePageWidget.qml">src/FlightMap/Widgets/ValuePageWidget.qml</file>
<file alias="HealthPageWidget.qml">src/FlightMap/Widgets/HealthPageWidget.qml</file>
<file alias="VibrationPageWidget.qml">src/FlightMap/Widgets/VibrationPageWidget.qml</file>
...
...
src/FlightDisplay/FlightDisplayView.qml
View file @
a8154e23
...
...
@@ -43,8 +43,6 @@ QGCView {
property
var
_geoFenceController
:
_planMasterController
.
geoFenceController
property
var
_rallyPointController
:
_planMasterController
.
rallyPointController
property
var
_activeVehicle
:
QGroundControl
.
multiVehicleManager
.
activeVehicle
property
var
_videoReceiver
:
QGroundControl
.
videoManager
.
videoReceiver
property
bool
_recordingVideo
:
_videoReceiver
&&
_videoReceiver
.
recording
property
bool
_mainIsMap
:
QGroundControl
.
videoManager
.
hasVideo
?
QGroundControl
.
loadBoolGlobalSetting
(
_mainIsMapKey
,
true
)
:
true
property
bool
_isPipVisible
:
QGroundControl
.
videoManager
.
hasVideo
?
QGroundControl
.
loadBoolGlobalSetting
(
_PIPVisibleKey
,
true
)
:
false
property
real
_savedZoomLevel
:
0
...
...
@@ -346,63 +344,6 @@ QGCView {
property
var
qgcView
:
root
}
// Button to start/stop video recording
Item
{
z
:
_flightVideoPipControl
.
z
+
1
anchors.margins
:
ScreenTools
.
defaultFontPixelHeight
/
2
anchors.bottom
:
_flightVideo
.
bottom
anchors.right
:
_flightVideo
.
right
height
:
ScreenTools
.
defaultFontPixelHeight
*
2
width
:
height
visible
:
_videoReceiver
&&
_videoReceiver
.
videoRunning
&&
QGroundControl
.
settingsManager
.
videoSettings
.
showRecControl
.
rawValue
&&
_flightVideo
.
visible
&&
!
_isCamera
&&
!
QGroundControl
.
videoManager
.
fullScreen
opacity
:
0.75
readonly
property
string
recordBtnBackground
:
"
BackgroundName
"
Rectangle
{
id
:
recordBtnBackground
anchors.top
:
parent
.
top
anchors.bottom
:
parent
.
bottom
width
:
height
radius
:
_recordingVideo
?
0
:
height
color
:
"
red
"
SequentialAnimation
on
visible
{
running
:
_recordingVideo
loops
:
Animation
.
Infinite
PropertyAnimation
{
to
:
false
;
duration
:
1000
}
PropertyAnimation
{
to
:
true
;
duration
:
1000
}
}
}
QGCColoredImage
{
anchors.top
:
parent
.
top
anchors.bottom
:
parent
.
bottom
anchors.horizontalCenter
:
parent
.
horizontalCenter
width
:
height
*
0.625
sourceSize.width
:
width
source
:
"
/qmlimages/CameraIcon.svg
"
visible
:
recordBtnBackground
.
visible
fillMode
:
Image
.
PreserveAspectFit
color
:
"
white
"
}
MouseArea
{
anchors.fill
:
parent
onClicked
:
{
if
(
_videoReceiver
)
{
if
(
_recordingVideo
)
{
_videoReceiver
.
stopRecording
()
// reset blinking animation
recordBtnBackground
.
visible
=
true
}
else
{
_videoReceiver
.
startRecording
()
}
}
}
}
}
MultiVehicleList
{
anchors.margins
:
_margins
anchors.top
:
singleMultiSelector
.
bottom
...
...
src/FlightDisplay/FlightDisplayViewVideo.qml
View file @
a8154e23
...
...
@@ -34,7 +34,7 @@ Item {
color
:
Qt
.
rgba
(
0
,
0
,
0
,
0.75
)
visible
:
!
(
_videoReceiver
&&
_videoReceiver
.
videoRunning
)
QGCLabel
{
text
:
qsTr
(
"
WAITING FOR VIDEO
"
)
text
:
_videoReceiver
&&
_videoReceiver
.
enabled
?
qsTr
(
"
WAITING FOR VIDEO
"
)
:
qsTr
(
"
VIDEO DISABLED
"
)
font.family
:
ScreenTools
.
demiboldFontFamily
color
:
"
white
"
font.pointSize
:
_mainIsMap
?
ScreenTools
.
smallFontPointSize
:
ScreenTools
.
largeFontPointSize
...
...
src/FlightMap/Widgets/VideoPageWidget.qml
0 → 100644
View file @
a8154e23
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
import
QtQuick
2.4
import
QtPositioning
5.2
import
QtQuick
.
Layouts
1.2
import
QtQuick
.
Controls
1.4
import
QtQuick
.
Dialogs
1.2
import
QtQuick
.
Controls
.
Styles
1.4
import
QtGraphicalEffects
1.0
import
QGroundControl
1.0
import
QGroundControl
.
ScreenTools
1.0
import
QGroundControl
.
Controls
1.0
import
QGroundControl
.
Palette
1.0
import
QGroundControl
.
Vehicle
1.0
import
QGroundControl
.
Controllers
1.0
import
QGroundControl
.
FactSystem
1.0
import
QGroundControl
.
FactControls
1.0
/// Video streaming page for Instrument Panel PageView
Item
{
width
:
pageWidth
height
:
videoGrid
.
height
+
(
ScreenTools
.
defaultFontPixelHeight
*
2
)
anchors.margins
:
ScreenTools
.
defaultFontPixelWidth
*
2
anchors.centerIn
:
parent
property
var
_activeVehicle
:
QGroundControl
.
multiVehicleManager
.
activeVehicle
property
bool
_communicationLost
:
_activeVehicle
?
_activeVehicle
.
connectionLost
:
false
property
var
_videoReceiver
:
QGroundControl
.
videoManager
.
videoReceiver
property
bool
_recordingVideo
:
_videoReceiver
&&
_videoReceiver
.
recording
property
bool
_videoRunning
:
_videoReceiver
&&
_videoReceiver
.
videoRunning
QGCPalette
{
id
:
qgcPal
;
colorGroupEnabled
:
parent
.
enabled
}
GridLayout
{
id
:
videoGrid
columns
:
2
columnSpacing
:
ScreenTools
.
defaultFontPixelWidth
*
2
rowSpacing
:
ScreenTools
.
defaultFontPixelHeight
anchors.centerIn
:
parent
QGCLabel
{
text
:
qsTr
(
"
Enable Stream
"
)
font.pointSize
:
ScreenTools
.
smallFontPointSize
}
Switch
{
checked
:
_videoRunning
enabled
:
_activeVehicle
onClicked
:
{
if
(
checked
)
{
_videoReceiver
.
start
()
}
else
{
_videoReceiver
.
stop
()
}
}
style
:
SwitchStyle
{
groove
:
Rectangle
{
implicitWidth
:
ScreenTools
.
defaultFontPixelWidth
*
6
implicitHeight
:
ScreenTools
.
defaultFontPixelHeight
color
:
control
.
checked
?
qgcPal
.
colorGreen
:
qgcPal
.
colorGrey
radius
:
3
border.color
:
qgcPal
.
button
border.width
:
1
}
}
}
QGCLabel
{
text
:
qsTr
(
"
Stream Recording
"
)
font.pointSize
:
ScreenTools
.
smallFontPointSize
visible
:
QGroundControl
.
settingsManager
.
videoSettings
.
showRecControl
.
rawValue
}
// Button to start/stop video recording
Item
{
anchors.margins
:
ScreenTools
.
defaultFontPixelHeight
/
2
height
:
ScreenTools
.
defaultFontPixelHeight
*
2
width
:
height
Layout.alignment
:
Qt
.
AlignHCenter
visible
:
QGroundControl
.
settingsManager
.
videoSettings
.
showRecControl
.
rawValue
Rectangle
{
id
:
recordBtnBackground
anchors.top
:
parent
.
top
anchors.bottom
:
parent
.
bottom
width
:
height
radius
:
_recordingVideo
?
0
:
height
color
:
_videoRunning
?
"
red
"
:
"
gray
"
SequentialAnimation
on
opacity
{
running
:
_recordingVideo
loops
:
Animation
.
Infinite
PropertyAnimation
{
to
:
0.5
;
duration
:
500
}
PropertyAnimation
{
to
:
1.0
;
duration
:
500
}
}
}
QGCColoredImage
{
anchors.top
:
parent
.
top
anchors.bottom
:
parent
.
bottom
anchors.horizontalCenter
:
parent
.
horizontalCenter
width
:
height
*
0.625
sourceSize.width
:
width
source
:
"
/qmlimages/CameraIcon.svg
"
visible
:
recordBtnBackground
.
visible
fillMode
:
Image
.
PreserveAspectFit
color
:
"
white
"
}
MouseArea
{
anchors.fill
:
parent
enabled
:
_videoRunning
onClicked
:
{
if
(
_recordingVideo
)
{
_videoReceiver
.
stopRecording
()
// reset blinking animation
recordBtnBackground
.
opacity
=
1
}
else
{
_videoReceiver
.
startRecording
()
}
}
}
}
}
}
src/QmlControls/PageView.qml
View file @
a8154e23
...
...
@@ -38,7 +38,7 @@ Rectangle {
width
:
parent
.
height
-
(
_margins
*
2
)
sourceSize.width
:
width
fillMode
:
Image
.
PreserveAspectFit
visible
:
pageWidgetLoader
.
item
.
showSettingsIcon
visible
:
pageWidgetLoader
.
item
?
(
pageWidgetLoader
.
item
.
showSettingsIcon
?
pageWidgetLoader
.
item
.
showSettingsIcon
:
false
)
:
false
QGCMouseArea
{
fillItem
:
parent
...
...
src/VideoStreaming/VideoReceiver.cc
View file @
a8154e23
...
...
@@ -67,6 +67,7 @@ VideoReceiver::VideoReceiver(QObject* parent)
,
_videoSurface
(
NULL
)
,
_videoRunning
(
false
)
,
_showFullScreen
(
false
)
,
_enabled
(
true
)
{
_videoSurface
=
new
VideoSurface
;
#if defined(QGC_GST_STREAMING)
...
...
@@ -147,8 +148,10 @@ VideoReceiver::_connected()
_timer
.
stop
();
_socket
->
deleteLater
();
_socket
=
NULL
;
_serverPresent
=
true
;
start
();
if
(
_enabled
)
{
_serverPresent
=
true
;
start
();
}
}
#endif
...
...
@@ -161,7 +164,9 @@ VideoReceiver::_socketError(QAbstractSocket::SocketError socketError)
_socket
->
deleteLater
();
_socket
=
NULL
;
//-- Try again in 5 seconds
_timer
.
start
(
5000
);
if
(
_enabled
)
{
_timer
.
start
(
5000
);
}
}
#endif
...
...
@@ -175,18 +180,19 @@ VideoReceiver::_timeout()
delete
_socket
;
_socket
=
NULL
;
}
//-- RTSP will try to connect to the server. If it cannot connect,
// it will simply give up and never try again. Instead, we keep
// attempting a connection on this timer. Once a connection is
// found to be working, only then we actually start the stream.
QUrl
url
(
_uri
);
_socket
=
new
QTcpSocket
;
_socket
->
setProxy
(
QNetworkProxy
::
NoProxy
);
connect
(
_socket
,
static_cast
<
void
(
QTcpSocket
::*
)(
QAbstractSocket
::
SocketError
)
>
(
&
QTcpSocket
::
error
),
this
,
&
VideoReceiver
::
_socketError
);
connect
(
_socket
,
&
QTcpSocket
::
connected
,
this
,
&
VideoReceiver
::
_connected
);
//qCDebug(VideoReceiverLog) << "Trying to connect to:" << url.host() << url.port();
_socket
->
connectToHost
(
url
.
host
(),
url
.
port
());
_timer
.
start
(
5000
);
if
(
_enabled
)
{
//-- RTSP will try to connect to the server. If it cannot connect,
// it will simply give up and never try again. Instead, we keep
// attempting a connection on this timer. Once a connection is
// found to be working, only then we actually start the stream.
QUrl
url
(
_uri
);
_socket
=
new
QTcpSocket
;
_socket
->
setProxy
(
QNetworkProxy
::
NoProxy
);
connect
(
_socket
,
static_cast
<
void
(
QTcpSocket
::*
)(
QAbstractSocket
::
SocketError
)
>
(
&
QTcpSocket
::
error
),
this
,
&
VideoReceiver
::
_socketError
);
connect
(
_socket
,
&
QTcpSocket
::
connected
,
this
,
&
VideoReceiver
::
_connected
);
_socket
->
connectToHost
(
url
.
host
(),
url
.
port
());
_timer
.
start
(
5000
);
}
}
#endif
...
...
@@ -203,6 +209,8 @@ VideoReceiver::_timeout()
void
VideoReceiver
::
start
()
{
_enabled
=
true
;
emit
enabledChanged
();
#if defined(QGC_GST_STREAMING)
qCDebug
(
VideoReceiverLog
)
<<
"start()"
;
...
...
@@ -416,6 +424,8 @@ VideoReceiver::start()
void
VideoReceiver
::
stop
()
{
_enabled
=
false
;
emit
enabledChanged
();
#if defined(QGC_GST_STREAMING)
qCDebug
(
VideoReceiverLog
)
<<
"stop()"
;
if
(
!
_streaming
)
{
...
...
@@ -814,7 +824,7 @@ VideoReceiver::_updateTimer()
stop
();
}
}
else
{
if
(
!
running
()
&&
!
_uri
.
isEmpty
())
{
if
(
!
running
()
&&
!
_uri
.
isEmpty
()
&&
_enabled
)
{
start
();
}
}
...
...
src/VideoStreaming/VideoReceiver.h
View file @
a8154e23
...
...
@@ -38,9 +38,10 @@ public:
Q_PROPERTY
(
bool
recording
READ
recording
NOTIFY
recordingChanged
)
#endif
Q_PROPERTY
(
VideoSurface
*
videoSurface
READ
videoSurface
CONSTANT
)
Q_PROPERTY
(
bool
videoRunning
READ
videoRunning
NOTIFY
videoRunningChanged
)
Q_PROPERTY
(
QString
imageFile
READ
imageFile
NOTIFY
imageFileChanged
)
Q_PROPERTY
(
bool
showFullScreen
READ
showFullScreen
WRITE
setShowFullScreen
NOTIFY
showFullScreenChanged
)
Q_PROPERTY
(
bool
videoRunning
READ
videoRunning
NOTIFY
videoRunningChanged
)
Q_PROPERTY
(
QString
imageFile
READ
imageFile
NOTIFY
imageFileChanged
)
Q_PROPERTY
(
bool
showFullScreen
READ
showFullScreen
WRITE
setShowFullScreen
NOTIFY
showFullScreenChanged
)
Q_PROPERTY
(
bool
enabled
READ
enabled
NOTIFY
enabledChanged
)
explicit
VideoReceiver
(
QObject
*
parent
=
0
);
~
VideoReceiver
();
...
...
@@ -57,6 +58,8 @@ public:
bool
videoRunning
()
{
return
_videoRunning
;
}
QString
imageFile
()
{
return
_imageFile
;
}
bool
showFullScreen
()
{
return
_showFullScreen
;
}
bool
enabled
()
{
return
_enabled
;
}
void
grabImage
(
QString
imageFile
);
void
setShowFullScreen
(
bool
show
)
{
_showFullScreen
=
show
;
emit
showFullScreenChanged
();
}
...
...
@@ -65,6 +68,7 @@ signals:
void
videoRunningChanged
();
void
imageFileChanged
();
void
showFullScreenChanged
();
void
enabledChanged
();
#if defined(QGC_GST_STREAMING)
void
recordingChanged
();
void
msgErrorReceived
();
...
...
@@ -136,6 +140,7 @@ private:
VideoSurface
*
_videoSurface
;
bool
_videoRunning
;
bool
_showFullScreen
;
bool
_enabled
;
};
...
...
src/api/QGCCorePlugin.cc
View file @
a8154e23
...
...
@@ -39,6 +39,7 @@ public:
,
defaultOptions
(
NULL
)
,
valuesPageWidgetInfo
(
NULL
)
,
cameraPageWidgetInfo
(
NULL
)
,
videoPageWidgetInfo
(
NULL
)
,
healthPageWidgetInfo
(
NULL
)
,
vibrationPageWidgetInfo
(
NULL
)
{
...
...
@@ -80,6 +81,7 @@ public:
QmlComponentInfo
*
valuesPageWidgetInfo
;
QmlComponentInfo
*
cameraPageWidgetInfo
;
QmlComponentInfo
*
videoPageWidgetInfo
;
QmlComponentInfo
*
healthPageWidgetInfo
;
QmlComponentInfo
*
vibrationPageWidgetInfo
;
QVariantList
instrumentPageWidgetList
;
...
...
@@ -148,13 +150,19 @@ QVariantList &QGCCorePlugin::settingsPages()
QVariantList
&
QGCCorePlugin
::
instrumentPages
(
void
)
{
if
(
!
_p
->
valuesPageWidgetInfo
)
{
_p
->
valuesPageWidgetInfo
=
new
QmlComponentInfo
(
tr
(
"Values"
),
QUrl
::
fromUserInput
(
"qrc:/qml/ValuePageWidget.qml"
));
_p
->
cameraPageWidgetInfo
=
new
QmlComponentInfo
(
tr
(
"Camera"
),
QUrl
::
fromUserInput
(
"qrc:/qml/CameraPageWidget.qml"
));
_p
->
healthPageWidgetInfo
=
new
QmlComponentInfo
(
tr
(
"Health"
),
QUrl
::
fromUserInput
(
"qrc:/qml/HealthPageWidget.qml"
));
_p
->
valuesPageWidgetInfo
=
new
QmlComponentInfo
(
tr
(
"Values"
),
QUrl
::
fromUserInput
(
"qrc:/qml/ValuePageWidget.qml"
));
_p
->
cameraPageWidgetInfo
=
new
QmlComponentInfo
(
tr
(
"Camera"
),
QUrl
::
fromUserInput
(
"qrc:/qml/CameraPageWidget.qml"
));
#if defined(QGC_GST_STREAMING)
_p
->
videoPageWidgetInfo
=
new
QmlComponentInfo
(
tr
(
"Video"
),
QUrl
::
fromUserInput
(
"qrc:/qml/VideoPageWidget.qml"
));
#endif
_p
->
healthPageWidgetInfo
=
new
QmlComponentInfo
(
tr
(
"Health"
),
QUrl
::
fromUserInput
(
"qrc:/qml/HealthPageWidget.qml"
));
_p
->
vibrationPageWidgetInfo
=
new
QmlComponentInfo
(
tr
(
"Vibration"
),
QUrl
::
fromUserInput
(
"qrc:/qml/VibrationPageWidget.qml"
));
_p
->
instrumentPageWidgetList
.
append
(
QVariant
::
fromValue
(
_p
->
valuesPageWidgetInfo
));
_p
->
instrumentPageWidgetList
.
append
(
QVariant
::
fromValue
(
_p
->
cameraPageWidgetInfo
));
#if defined(QGC_GST_STREAMING)
_p
->
instrumentPageWidgetList
.
append
(
QVariant
::
fromValue
(
_p
->
videoPageWidgetInfo
));
#endif
_p
->
instrumentPageWidgetList
.
append
(
QVariant
::
fromValue
(
_p
->
healthPageWidgetInfo
));
_p
->
instrumentPageWidgetList
.
append
(
QVariant
::
fromValue
(
_p
->
vibrationPageWidgetInfo
));
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment