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
4b4f758b
Commit
4b4f758b
authored
Jul 03, 2015
by
Gus Grubba
Committed by
dogmaphobic
Jul 06, 2015
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Video Streaming
parent
bffd454c
Changes
55
Show whitespace changes
Inline
Side-by-side
Showing
55 changed files
with
6322 additions
and
227 deletions
+6322
-227
QGCApplication.pro
QGCApplication.pro
+11
-0
qgroundcontrol.qrc
qgroundcontrol.qrc
+1
-41
QGCApplication.cc
src/QGCApplication.cc
+25
-0
ScreenToolsController.h
src/QmlControls/ScreenToolsController.h
+7
-0
VideoItem.cc
src/VideoStreaming/VideoItem.cc
+113
-0
VideoItem.h
src/VideoStreaming/VideoItem.h
+58
-0
VideoReceiver.cc
src/VideoStreaming/VideoReceiver.cc
+207
-0
VideoReceiver.h
src/VideoStreaming/VideoReceiver.h
+59
-0
VideoStreaming.pri
src/VideoStreaming/VideoStreaming.pri
+119
-0
VideoSurface.cc
src/VideoStreaming/VideoSurface.cc
+74
-0
VideoSurface.h
src/VideoStreaming/VideoSurface.h
+64
-0
basedelegate.cpp
src/VideoStreaming/gstqtvideosink/delegates/basedelegate.cpp
+203
-0
basedelegate.h
src/VideoStreaming/gstqtvideosink/delegates/basedelegate.h
+155
-0
qtquick2videosinkdelegate.cpp
...ng/gstqtvideosink/delegates/qtquick2videosinkdelegate.cpp
+108
-0
qtquick2videosinkdelegate.h
...ming/gstqtvideosink/delegates/qtquick2videosinkdelegate.h
+38
-0
qtvideosinkdelegate.cpp
...treaming/gstqtvideosink/delegates/qtvideosinkdelegate.cpp
+245
-0
qtvideosinkdelegate.h
...oStreaming/gstqtvideosink/delegates/qtvideosinkdelegate.h
+75
-0
qwidgetvideosinkdelegate.cpp
...ing/gstqtvideosink/delegates/qwidgetvideosinkdelegate.cpp
+89
-0
qwidgetvideosinkdelegate.h
...aming/gstqtvideosink/delegates/qwidgetvideosinkdelegate.h
+56
-0
gstqtglvideosink.cpp
src/VideoStreaming/gstqtvideosink/gstqtglvideosink.cpp
+150
-0
gstqtglvideosink.h
src/VideoStreaming/gstqtvideosink/gstqtglvideosink.h
+78
-0
gstqtglvideosinkbase.cpp
src/VideoStreaming/gstqtvideosink/gstqtglvideosinkbase.cpp
+268
-0
gstqtglvideosinkbase.h
src/VideoStreaming/gstqtvideosink/gstqtglvideosinkbase.h
+100
-0
gstqtquick2videosink.cpp
src/VideoStreaming/gstqtvideosink/gstqtquick2videosink.cpp
+459
-0
gstqtquick2videosink.h
src/VideoStreaming/gstqtvideosink/gstqtquick2videosink.h
+63
-0
gstqtvideosink.cpp
src/VideoStreaming/gstqtvideosink/gstqtvideosink.cpp
+117
-0
gstqtvideosink.h
src/VideoStreaming/gstqtvideosink/gstqtvideosink.h
+67
-0
gstqtvideosinkbase.cpp
src/VideoStreaming/gstqtvideosink/gstqtvideosinkbase.cpp
+221
-0
gstqtvideosinkbase.h
src/VideoStreaming/gstqtvideosink/gstqtvideosinkbase.h
+84
-0
gstqtvideosinkmarshal.c
src/VideoStreaming/gstqtvideosink/gstqtvideosinkmarshal.c
+231
-0
gstqtvideosinkmarshal.h
src/VideoStreaming/gstqtvideosink/gstqtvideosinkmarshal.h
+44
-0
gstqtvideosinkplugin.cpp
src/VideoStreaming/gstqtvideosink/gstqtvideosinkplugin.cpp
+86
-0
gstqtvideosinkplugin.h
src/VideoStreaming/gstqtvideosink/gstqtvideosinkplugin.h
+77
-0
gstqwidgetvideosink.cpp
src/VideoStreaming/gstqtvideosink/gstqwidgetvideosink.cpp
+104
-0
gstqwidgetvideosink.h
src/VideoStreaming/gstqtvideosink/gstqwidgetvideosink.h
+61
-0
marshaller.src
src/VideoStreaming/gstqtvideosink/marshaller.src
+4
-0
abstractsurfacepainter.h
...treaming/gstqtvideosink/painters/abstractsurfacepainter.h
+49
-0
genericsurfacepainter.cpp
...reaming/gstqtvideosink/painters/genericsurfacepainter.cpp
+113
-0
genericsurfacepainter.h
...Streaming/gstqtvideosink/painters/genericsurfacepainter.h
+58
-0
openglsurfacepainter.cpp
...treaming/gstqtvideosink/painters/openglsurfacepainter.cpp
+806
-0
openglsurfacepainter.h
...oStreaming/gstqtvideosink/painters/openglsurfacepainter.h
+142
-0
videomaterial.cpp
src/VideoStreaming/gstqtvideosink/painters/videomaterial.cpp
+461
-0
videomaterial.h
src/VideoStreaming/gstqtvideosink/painters/videomaterial.h
+83
-0
videonode.cpp
src/VideoStreaming/gstqtvideosink/painters/videonode.cpp
+118
-0
videonode.h
src/VideoStreaming/gstqtvideosink/painters/videonode.h
+56
-0
bufferformat.cpp
src/VideoStreaming/gstqtvideosink/utils/bufferformat.cpp
+66
-0
bufferformat.h
src/VideoStreaming/gstqtvideosink/utils/bufferformat.h
+70
-0
utils.cpp
src/VideoStreaming/gstqtvideosink/utils/utils.cpp
+92
-0
utils.h
src/VideoStreaming/gstqtvideosink/utils/utils.h
+78
-0
videosurface_p.h
src/VideoStreaming/videosurface_p.h
+47
-0
FlightDisplay.cc
src/ui/flightdisplay/FlightDisplay.cc
+41
-0
FlightDisplay.qml
src/ui/flightdisplay/FlightDisplay.qml
+52
-170
QGCMapBackground.qml
src/ui/qmlcommon/QGCMapBackground.qml
+1
-0
QGCVideoBackground.qml
src/ui/qmlcommon/QGCVideoBackground.qml
+51
-0
qmldir
src/ui/qmlcommon/qmldir
+17
-16
No files found.
QGCApplication.pro
View file @
4b4f758b
...
...
@@ -652,6 +652,17 @@ SOURCES += \
src
/
FactSystem
/
ParameterLoader
.
cc
\
src
/
FactSystem
/
FactControls
/
FactPanelController
.
cc
\
#
Video
Streaming
contains
(
DEFINES
,
DISABLE_VIDEOSTREAMING
)
{
message
(
"Skipping support for video streaming (manual override from command line)"
)
DEFINES
-=
DISABLE_VIDEOSTREAMING
#
Otherwise
the
user
can
still
disable
this
feature
in
the
user_config
.
pri
file
.
}
else
:
exists
(
user_config
.
pri
)
:
infile
(
user_config
.
pri
,
DEFINES
,
DISABLE_VIDEOSTREAMING
)
{
message
(
"Skipping support for video streaming (manual override from user_config.pri)"
)
}
else
{
include
(
src
/
VideoStreaming
/
VideoStreaming
.
pri
)
}
#
Android
AndroidBuild
{
...
...
qgroundcontrol.qrc
View file @
4b4f758b
...
...
@@ -3,24 +3,20 @@
<file alias="MockLink.params">src/comm/MockLink.params</file>
<file alias="FactSystemTest.qml">src/FactSystem/FactSystemTest.qml</file>
</qresource>
<qresource prefix="/qmlimages">
<file alias="SafetyComponentTree.svg">src/AutoPilotPlugins/PX4/Images/SafetyComponentTree.svg</file>
<file alias="SafetyComponentHome.png">src/AutoPilotPlugins/PX4/Images/SafetyComponentHome.png</file>
<file alias="SafetyComponentArrowDown.png">src/AutoPilotPlugins/PX4/Images/SafetyComponentArrowDown.png</file>
<file alias="SafetyComponentPlane.png">src/AutoPilotPlugins/PX4/Images/SafetyComponentPlane.png</file>
<file alias="VehicleDown.png">src/AutoPilotPlugins/PX4/Images/VehicleDown.png</file>
<file alias="VehicleUpsideDown.png">src/AutoPilotPlugins/PX4/Images/VehicleUpsideDown.png</file>
<file alias="VehicleLeft.png">src/AutoPilotPlugins/PX4/Images/VehicleLeft.png</file>
<file alias="VehicleRight.png">src/AutoPilotPlugins/PX4/Images/VehicleRight.png</file>
<file alias="VehicleNoseDown.png">src/AutoPilotPlugins/PX4/Images/VehicleNoseDown.png</file>
<file alias="VehicleTailDown.png">src/AutoPilotPlugins/PX4/Images/VehicleTailDown.png</file>
<file alias="VehicleDownRotate.png">src/AutoPilotPlugins/PX4/Images/VehicleDownRotate.png</file>
<file alias="VehicleLeftRotate.png">src/AutoPilotPlugins/PX4/Images/VehicleLeftRotate.png</file>
<file alias="VehicleNoseDownRotate.png">src/AutoPilotPlugins/PX4/Images/VehicleNoseDownRotate.png</file>
<file alias="AirframeStandardPlane.png">src/AutoPilotPlugins/PX4/Images/AirframeStandardPlane.png</file>
<file alias="AirframeFlyingWing.png">src/AutoPilotPlugins/PX4/Images/AirframeFlyingWing.png</file>
<file alias="AirframeQuadRotorX.png">src/AutoPilotPlugins/PX4/Images/AirframeQuadRotorX.png</file>
...
...
@@ -31,7 +27,6 @@
<file alias="AirframeHexaRotorPlus.png">src/AutoPilotPlugins/PX4/Images/AirframeHexaRotorPlus.png</file>
<file alias="AirframeQuadRotorH.png">src/AutoPilotPlugins/PX4/Images/AirframeQuadRotorH.png</file>
<file alias="AirframeSimulation.png">src/AutoPilotPlugins/PX4/Images/AirframeSimulation.png</file>
<file alias="arrow-down.png">src/QmlControls/arrow-down.png</file>
<file alias="subMenuButtonImage.png">resources/CogWheels.png</file>
<file alias="SensorsComponentIcon.png">src/AutoPilotPlugins/PX4/Images/SensorsComponentIcon.png</file>
...
...
@@ -42,14 +37,12 @@
<file alias="PowerComponentIcon.png">src/AutoPilotPlugins/PX4/Images/PowerComponentIcon.png</file>
<file alias="FirmwareUpgradeIcon.png">src/VehicleSetup/FirmwareUpgradeIcon.png</file>
<file alias="VehicleSummaryIcon.png">src/VehicleSetup/VehicleSummaryIcon.png</file>
<file alias="PowerComponentBattery_01cell.svg">src/AutoPilotPlugins/PX4/Images/PowerComponentBattery_01cell.svg</file>
<file alias="PowerComponentBattery_02cell.svg">src/AutoPilotPlugins/PX4/Images/PowerComponentBattery_02cell.svg</file>
<file alias="PowerComponentBattery_03cell.svg">src/AutoPilotPlugins/PX4/Images/PowerComponentBattery_03cell.svg</file>
<file alias="PowerComponentBattery_04cell.svg">src/AutoPilotPlugins/PX4/Images/PowerComponentBattery_04cell.svg</file>
<file alias="PowerComponentBattery_05cell.svg">src/AutoPilotPlugins/PX4/Images/PowerComponentBattery_05cell.svg</file>
<file alias="PowerComponentBattery_06cell.svg">src/AutoPilotPlugins/PX4/Images/PowerComponentBattery_06cell.svg</file>
<file alias="attitudeDial.svg">src/ui/qmlcommon/attitudeDial.svg</file>
<file alias="attitudeInstrument.svg">src/ui/qmlcommon/attitudeInstrument.svg</file>
<file alias="attitudePointer.svg">src/ui/qmlcommon/attitudePointer.svg</file>
...
...
@@ -67,18 +60,15 @@
<file alias="scale.png">src/ui/qmlcommon/scale.png</file>
<file alias="scale_end.png">src/ui/qmlcommon/scale_end.png</file>
</qresource>
<qresource prefix="/qml">
<file alias="test.qml">src/test.qml</file>
<file alias="QmlTest.qml">src/QmlControls/QmlTest.qml</file>
<file alias="QGroundControl/FactControls/qmldir">src/FactSystem/FactControls/qmldir</file>
<file alias="QGroundControl/FactControls/FactPanel.qml">src/FactSystem/FactControls/FactPanel.qml</file>
<file alias="QGroundControl/FactControls/FactLabel.qml">src/FactSystem/FactControls/FactLabel.qml</file>
<file alias="QGroundControl/FactControls/FactTextField.qml">src/FactSystem/FactControls/FactTextField.qml</file>
<file alias="QGroundControl/FactControls/FactCheckBox.qml">src/FactSystem/FactControls/FactCheckBox.qml</file>
<file alias="QGroundControl/FactControls/FactComboBox.qml">src/FactSystem/FactControls/FactComboBox.qml</file>
<file alias="QGroundControl/Controls/qmldir">src/QmlControls/QGroundControl.Controls.qmldir</file>
<file alias="QGroundControl/Controls/QGCButton.qml">src/QmlControls/QGCButton.qml</file>
<file alias="QGroundControl/Controls/QGCRadioButton.qml">src/QmlControls/QGCRadioButton.qml</file>
...
...
@@ -89,32 +79,25 @@
<file alias="QGroundControl/Controls/QGCColoredImage.qml">src/QmlControls/QGCColoredImage.qml</file>
<file alias="QGroundControl/Controls/QGCToolBarButton.qml">src/QmlControls/QGCToolBarButton.qml</file>
<file alias="QGroundControl/Controls/QGCMovableItem.qml">src/QmlControls/QGCMovableItem.qml</file>
<file alias="QGroundControl/ScreenTools/qmldir">src/QmlControls/QGroundControl.ScreenTools.qmldir</file>
<file alias="QGroundControl/ScreenTools/ScreenTools.qml">src/QmlControls/ScreenTools.qml</file>
<file alias="ScreenToolsFontQuery.qml">src/QmlControls/ScreenToolsFontQuery.qml</file>
<file alias="QGroundControl/Controls/SubMenuButton.qml">src/QmlControls/SubMenuButton.qml</file>
<file alias="QGroundControl/Controls/IndicatorButton.qml">src/QmlControls/IndicatorButton.qml</file>
<file alias="QGroundControl/Controls/VehicleRotationCal.qml">src/QmlControls/VehicleRotationCal.qml</file>
<file alias="QGroundControl/Controls/VehicleSummaryRow.qml">src/QmlControls/VehicleSummaryRow.qml</file>
<file alias="QGroundControl/Controls/ViewWidget.qml">src/ViewWidgets/ViewWidget.qml</file>
<file alias="QGroundControl/Controls/QGCView.qml">src/QmlControls/QGCView.qml</file>
<file alias="QGroundControl/Controls/QGCViewPanel.qml">src/QmlControls/QGCViewPanel.qml</file>
<file alias="QGroundControl/Controls/QGCViewDialog.qml">src/QmlControls/QGCViewDialog.qml</file>
<file alias="QGroundControl/Controls/QGCViewMessage.qml">src/QmlControls/QGCViewMessage.qml</file>
<file alias="QGroundControl/Controls/ParameterEditor.qml">src/QmlControls/ParameterEditor.qml</file>
<file alias="QGroundControl/Controls/ParameterEditorDialog.qml">src/QmlControls/ParameterEditorDialog.qml</file>
<file alias="ParameterEditorWidget.qml">src/ViewWidgets/ParameterEditorWidget.qml</file>
<file alias="CustomCommandWidget.qml">src/ViewWidgets/CustomCommandWidget.qml</file>
<file alias="SetupView.qml">src/VehicleSetup/SetupView.qml</file>
<file alias="SetupViewButtonsConnected.qml">src/VehicleSetup/SetupViewButtonsConnected.qml</file>
<file alias="SetupViewButtonsDisconnected.qml">src/VehicleSetup/SetupViewButtonsDisconnected.qml</file>
<file alias="VehicleSummary.qml">src/VehicleSetup/VehicleSummary.qml</file>
<file alias="FirmwareUpgrade.qml">src/VehicleSetup/FirmwareUpgrade.qml</file>
<file alias="SetupParameterEditor.qml">src/VehicleSetup/SetupParameterEditor.qml</file>
...
...
@@ -130,14 +113,10 @@
<file alias="RadioComponentSummary.qml">src/AutoPilotPlugins/PX4/RadioComponentSummary.qml</file>
<file alias="FlightModesComponentSummary.qml">src/AutoPilotPlugins/PX4/FlightModesComponentSummary.qml</file>
<file alias="AirframeComponentSummary.qml">src/AutoPilotPlugins/PX4/AirframeComponentSummary.qml</file>
<!-- Airframe component resourecs -->
<file alias="AirframeComponent.qml">src/AutoPilotPlugins/PX4/AirframeComponent.qml</file>
<!-- QML Main UI -->
<file alias="MainToolBar.qml">src/ui/toolbar/MainToolBar.qml</file>
<file alias="FlightDisplay.qml">src/ui/flightdisplay/FlightDisplay.qml</file>
<file alias="MapDisplay.qml">src/ui/mapdisplay/MapDisplay.qml</file>
<!-- QML Main UI Components -->
<file alias="QGroundControl/FlightControls/QGCAltitudeWidget.qml">src/ui/qmlcommon/QGCAltitudeWidget.qml</file>
<file alias="QGroundControl/FlightControls/QGCArtificialHorizon.qml">src/ui/qmlcommon/QGCArtificialHorizon.qml</file>
<file alias="QGroundControl/FlightControls/QGCAttitudeInstrument.qml">src/ui/qmlcommon/QGCAttitudeInstrument.qml</file>
...
...
@@ -152,16 +131,14 @@
<file alias="QGroundControl/FlightControls/QGCPitchWidget.qml">src/ui/qmlcommon/QGCPitchWidget.qml</file>
<file alias="QGroundControl/FlightControls/QGCSlider.qml">src/ui/qmlcommon/QGCSlider.qml</file>
<file alias="QGroundControl/FlightControls/QGCSpeedWidget.qml">src/ui/qmlcommon/QGCSpeedWidget.qml</file>
<file alias="QGroundControl/FlightControls/QGCVideoBackground.qml">src/ui/qmlcommon/QGCVideoBackground.qml</file>
<file alias="QGroundControl/FlightControls/QGCWaypointEditor.qml">src/ui/qmlcommon/QGCWaypointEditor.qml</file>
<file alias="QGroundControl/FlightControls/qmldir">src/ui/qmlcommon/qmldir</file>
<!-- QML Map Resources -->
<file alias="QGroundControl/FlightControls/QGCWaypoint.qml">src/ui/qmlcommon/QGCWaypoint.qml</file>
</qresource>
<qresource prefix="/AutoPilotPlugins/PX4">
<file alias="ParameterFactMetaData.xml">src/AutoPilotPlugins/PX4/ParameterFactMetaData.xml</file>
</qresource>
<qresource prefix="/res">
<file alias="LeftArrow">resources/LeftArrow.svg</file>
<file alias="RightArrow">resources/RightArrow.svg</file>
...
...
@@ -169,45 +146,35 @@
<file alias="UpArrow">resources/UpArrow.svg</file>
<file alias="BottomArrow">resources/BottomArrow.svg</file>
<file alias="JumpArrow">resources/JumpArrow.svg</file>
<file alias="PlusSign">resources/PlusSign.svg</file>
<file alias="MinusSign">resources/MinusSign.svg</file>
<file alias="Play">resources/Play.svg</file>
<file alias="Pause">resources/Pause.svg</file>
<file alias="Stop">resources/Stop.svg</file>
<file alias="Launch">resources/Launch.svg</file>
<file alias="Land">resources/Land.svg</file>
<file alias="Kill">resources/Kill.svg</file>
<file alias="Shutdown">resources/Shutdown.svg</file>
<file alias="AntennaT">resources/Antenna_T.svg</file>
<file alias="AntennaRC">resources/Antenna_RC.svg</file>
<file alias="Gps">resources/Gps.svg</file>
<file alias="Megaphone">resources/Megaphone.png</file>
<file alias="Yield">resources/Yield.png</file>
<file alias="Battery_0">resources/Battery_0.svg</file>
<file alias="Battery_20">resources/Battery_20.svg</file>
<file alias="Battery_40">resources/Battery_40.svg</file>
<file alias="Battery_60">resources/Battery_60.svg</file>
<file alias="Battery_80">resources/Battery_80.svg</file>
<file alias="Battery_100">resources/Battery_100.svg</file>
<file alias="SystemLockScreen">resources/SystemLockScreen.svg</file>
<file alias="SplashScreen">resources/SplashScreen.png</file>
<file alias="QGroundControlConnect">resources/QGroundControlConnect.svg</file>
</qresource>
<qresource prefix="/res/firmware">
<file alias="px4.png">resources/firmware/px4.png</file>
<file alias="apm.png">resources/firmware/apm.png</file>
<file alias="3drradio.png">resources/firmware/3drradio.png</file>
</qresource>
<qresource prefix="/res/mavs">
<file alias="Helicopter">resources/mavs/helicopter.svg</file>
<file alias="Unknown">resources/mavs/unknown.svg</file>
...
...
@@ -229,14 +196,12 @@
<file alias="SurfaceBoat">resources/mavs/surface-boat.svg</file>
<file alias="TriCopter">resources/mavs/tricopter.svg</file>
</qresource>
<qresource prefix="/res/mapproviders">
<file alias="openstreetmap.png">resources/mapproviders/openstreetmap.png</file>
<file alias="google.png">resources/mapproviders/google.png</file>
<file alias="yahoo.png">resources/mapproviders/yahoo.png</file>
<file alias="googleearth.svg">resources/mapproviders/googleearth.svg</file>
</qresource>
<qresource prefix="/res/calibration">
<file alias="accel_back.png">resources/calibration/accel_back.png</file>
<file alias="accel_front.png">resources/calibration/accel_front.png</file>
...
...
@@ -245,7 +210,6 @@
<file alias="accel_up.png">resources/calibration/accel_up.png</file>
<file alias="accel_left.png">resources/calibration/accel_left.png</file>
</qresource>
<qresource prefix="/qml/calibration/mode1">
<file alias="radioCenter.png">resources/calibration/mode1/radioCenter.png</file>
<file alias="radioHome.png">resources/calibration/mode1/radioHome.png</file>
...
...
@@ -259,7 +223,6 @@
<file alias="radioThrottleDown.png">resources/calibration/mode1/radioThrottleDown.png</file>
<file alias="radioSwitchMinMax.png">resources/calibration/mode1/radioSwitchMinMax.png</file>
</qresource>
<qresource prefix="/qml/calibration/mode2">
<file alias="radioCenter.png">resources/calibration/mode2/radioCenter.png</file>
<file alias="radioHome.png">resources/calibration/mode2/radioHome.png</file>
...
...
@@ -273,16 +236,13 @@
<file alias="radioThrottleDown.png">resources/calibration/mode2/radioThrottleDown.png</file>
<file alias="radioSwitchMinMax.png">resources/calibration/mode2/radioSwitchMinMax.png</file>
</qresource>
<qresource prefix="/res/styles">
<file alias="style-dark.css">resources/styles/style-dark.css</file>
<file alias="style-light.css">resources/styles/style-light.css</file>
</qresource>
<qresource prefix="/res/fonts">
<file alias="vera.ttf">resources/styles/Vera.ttf</file>
</qresource>
<qresource prefix="/res/audio">
<file alias="Alert">resources/audio/alert.wav</file>
</qresource>
...
...
src/QGCApplication.cc
View file @
4b4f758b
...
...
@@ -40,6 +40,14 @@
#include <QDebug>
#if defined(QGC_GST_STREAMING)
#include <videoitem.h>
#include <videosurface.h>
G_BEGIN_DECLS
GST_PLUGIN_STATIC_DECLARE
(
QTVIDEOSINK_NAME
);
G_END_DECLS
#endif
#include "configuration.h"
#include "QGC.h"
#include "QGCApplication.h"
...
...
@@ -255,11 +263,28 @@ QGCApplication::QGCApplication(int &argc, char* argv[], bool unitTesting)
settings
.
clear
();
settings
.
setValue
(
_settingsVersionKey
,
QGC_SETTINGS_VERSION
);
}
#if defined(QGC_GST_STREAMING)
//----------------------------------------------------------------
//-- Video Streaming
qmlRegisterType
<
VideoItem
>
(
"QGroundControl.QgcQtGStreamer"
,
1
,
0
,
"VideoItem"
);
qmlRegisterUncreatableType
<
VideoSurface
>
(
"QGroundControl.QgcQtGStreamer"
,
1
,
0
,
"VideoSurface"
,
QLatin1String
(
"VideoSurface from QML is not supported"
));
GError
*
error
=
NULL
;
if
(
!
gst_init_check
(
&
argc
,
&
argv
,
&
error
))
{
qCritical
()
<<
"gst_init_check() failed: "
<<
error
->
message
;
g_error_free
(
error
);
}
GST_PLUGIN_STATIC_REGISTER
(
QTVIDEOSINK_NAME
);
#endif
}
QGCApplication
::~
QGCApplication
()
{
_destroySingletons
();
#if defined(QGC_GST_STREAMING)
gst_deinit
();
#endif
}
void
QGCApplication
::
_initCommon
(
void
)
...
...
src/QmlControls/ScreenToolsController.h
View file @
4b4f758b
...
...
@@ -50,6 +50,7 @@ public:
Q_PROPERTY
(
bool
isAndroid
READ
isAndroid
CONSTANT
)
Q_PROPERTY
(
bool
isiOS
READ
isiOS
CONSTANT
)
Q_PROPERTY
(
bool
isMobile
READ
isMobile
CONSTANT
)
Q_PROPERTY
(
bool
hasVideo
READ
hasVideo
CONSTANT
)
//! Used to trigger a \c Canvas element repaint.
/*!
...
...
@@ -110,6 +111,12 @@ public:
bool
isMobile
()
{
return
false
;
}
#endif
#if defined(QGC_GST_STREAMING)
bool
hasVideo
()
{
return
true
;
}
#else
bool
hasVideo
()
{
return
false
;
}
#endif
signals:
void
repaintRequested
(
void
);
...
...
src/VideoStreaming/VideoItem.cc
0 → 100644
View file @
4b4f758b
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009, 2015 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/**
* @file
* @brief QGC Video Item
* @author Gus Grubba <mavlink@grubba.com>
*/
#include <QtCore/QPointer>
#include <QtQuick/QSGNode>
#include <QtQuick/QSGFlatColorMaterial>
#include "videoitem.h"
#include "videosurface_p.h"
struct
VideoItem
::
Private
{
QPointer
<
VideoSurface
>
surface
;
bool
surfaceDirty
;
QRectF
targetArea
;
};
VideoItem
::
VideoItem
(
QQuickItem
*
parent
)
:
QQuickItem
(
parent
),
_data
(
new
Private
)
{
_data
->
surfaceDirty
=
true
;
setFlag
(
QQuickItem
::
ItemHasContents
,
true
);
}
VideoItem
::~
VideoItem
()
{
setSurface
(
0
);
delete
_data
;
}
VideoSurface
*
VideoItem
::
surface
()
const
{
return
_data
->
surface
.
data
();
}
void
VideoItem
::
setSurface
(
VideoSurface
*
surface
)
{
if
(
_data
->
surface
)
{
_data
->
surface
.
data
()
->
_data
->
items
.
remove
(
this
);
}
_data
->
surface
=
surface
;
_data
->
surfaceDirty
=
true
;
if
(
_data
->
surface
)
{
_data
->
surface
.
data
()
->
_data
->
items
.
insert
(
this
);
}
}
QSGNode
*
VideoItem
::
updatePaintNode
(
QSGNode
*
oldNode
,
UpdatePaintNodeData
*
)
{
QRectF
r
=
boundingRect
();
QSGNode
*
newNode
=
0
;
if
(
_data
->
surfaceDirty
)
{
delete
oldNode
;
oldNode
=
0
;
_data
->
surfaceDirty
=
false
;
}
if
(
!
_data
->
surface
||
_data
->
surface
.
data
()
->
_data
->
videoSink
==
NULL
)
{
if
(
!
oldNode
)
{
QSGFlatColorMaterial
*
material
=
new
QSGFlatColorMaterial
;
material
->
setColor
(
Qt
::
black
);
QSGGeometryNode
*
node
=
new
QSGGeometryNode
;
node
->
setMaterial
(
material
);
node
->
setFlag
(
QSGNode
::
OwnsMaterial
);
node
->
setFlag
(
QSGNode
::
OwnsGeometry
);
newNode
=
node
;
_data
->
targetArea
=
QRectF
();
//force geometry to be set
}
else
{
newNode
=
oldNode
;
}
if
(
r
!=
_data
->
targetArea
)
{
QSGGeometry
*
geometry
=
new
QSGGeometry
(
QSGGeometry
::
defaultAttributes_Point2D
(),
4
);
geometry
->
vertexDataAsPoint2D
()[
0
].
set
(
r
.
x
(),
r
.
y
());
geometry
->
vertexDataAsPoint2D
()[
1
].
set
(
r
.
x
(),
r
.
height
());
geometry
->
vertexDataAsPoint2D
()[
2
].
set
(
r
.
width
(),
r
.
y
());
geometry
->
vertexDataAsPoint2D
()[
3
].
set
(
r
.
width
(),
r
.
height
());
QSGGeometryNode
*
node
=
static_cast
<
QSGGeometryNode
*>
(
newNode
);
node
->
setGeometry
(
geometry
);
_data
->
targetArea
=
r
;
}
}
else
{
g_signal_emit_by_name
(
_data
->
surface
.
data
()
->
_data
->
videoSink
,
"update-node"
,
(
void
*
)
oldNode
,
r
.
x
(),
r
.
y
(),
r
.
width
(),
r
.
height
(),
(
void
**
)
&
newNode
);
}
return
newNode
;
}
src/VideoStreaming/VideoItem.h
0 → 100644
View file @
4b4f758b
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009, 2015 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/**
* @file
* @brief QGC Video Item
* @author Gus Grubba <mavlink@grubba.com>
*/
#ifndef VIDEO_ITEM_H
#define VIDEO_ITEM_H
#include <QtQuick/QQuickItem>
#include "videosurface.h"
class
VideoItem
:
public
QQuickItem
{
Q_OBJECT
Q_DISABLE_COPY
(
VideoItem
)
Q_PROPERTY
(
VideoSurface
*
surface
READ
surface
WRITE
setSurface
)
public:
explicit
VideoItem
(
QQuickItem
*
parent
=
0
);
virtual
~
VideoItem
();
VideoSurface
*
surface
()
const
;
void
setSurface
(
VideoSurface
*
surface
);
protected:
/*! Reimplemented from QQuickItem. */
virtual
QSGNode
*
updatePaintNode
(
QSGNode
*
oldNode
,
UpdatePaintNodeData
*
updatePaintNodeData
);
private:
struct
Private
;
Private
*
const
_data
;
};
#endif // VIDEO_ITEM_H
src/VideoStreaming/VideoReceiver.cc
0 → 100644
View file @
4b4f758b
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009, 2015 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/**
* @file
* @brief QGC Video Receiver
* @author Gus Grubba <mavlink@grubba.com>
*/
#include "VideoReceiver.h"
#include <QDebug>
VideoReceiver
::
VideoReceiver
(
QObject
*
parent
)
:
QObject
(
parent
)
,
_pipeline
(
NULL
)
,
_videoSink
(
NULL
)
{
}
VideoReceiver
::~
VideoReceiver
()
{
stop
();
setVideoSink
(
NULL
);
}
void
VideoReceiver
::
setVideoSink
(
GstElement
*
sink
)
{
if
(
_videoSink
)
{
gst_object_unref
(
_videoSink
);
_videoSink
=
NULL
;
}
if
(
sink
)
{
_videoSink
=
sink
;
gst_object_ref_sink
(
_videoSink
);
}
}
void
VideoReceiver
::
start
()
{
if
(
_uri
.
isEmpty
())
{
qCritical
()
<<
"VideoReceiver::start() failed because URI is not specified"
;
return
;
}
if
(
_videoSink
==
NULL
)
{
qCritical
()
<<
"VideoReceiver::start() failed because video sink is not set"
;
return
;
}
stop
();
bool
running
=
false
;
GstElement
*
dataSource
=
NULL
;
GstCaps
*
caps
=
NULL
;
GstElement
*
demux
=
NULL
;
GstElement
*
parser
=
NULL
;
GstElement
*
decoder
=
NULL
;
do
{
if
((
_pipeline
=
gst_pipeline_new
(
"receiver"
))
==
NULL
)
{
break
;
}
if
((
dataSource
=
gst_element_factory_make
(
"udpsrc"
,
"udp-source"
))
==
NULL
)
{
break
;
}
if
((
caps
=
gst_caps_from_string
(
"application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264"
))
==
NULL
)
{
break
;
}
g_object_set
(
G_OBJECT
(
dataSource
),
"uri"
,
qPrintable
(
_uri
),
"caps"
,
caps
,
NULL
);
if
((
demux
=
gst_element_factory_make
(
"rtph264depay"
,
"rtp-h264-depacketizer"
))
==
NULL
)
{
break
;
}
if
((
parser
=
gst_element_factory_make
(
"h264parse"
,
"h264-parser"
))
==
NULL
)
{
break
;
}
if
((
decoder
=
gst_element_factory_make
(
"avdec_h264"
,
"h264-decoder"
))
==
NULL
)
{
break
;
}
gst_bin_add_many
(
GST_BIN
(
_pipeline
),
dataSource
,
demux
,
parser
,
decoder
,
_videoSink
,
NULL
);
if
(
gst_element_link_many
(
dataSource
,
demux
,
parser
,
decoder
,
_videoSink
,
NULL
)
!=
TRUE
)
{
break
;
}
dataSource
=
demux
=
parser
=
decoder
=
NULL
;
GstBus
*
bus
=
NULL
;
if
((
bus
=
gst_pipeline_get_bus
(
GST_PIPELINE
(
_pipeline
)))
!=
NULL
)
{
gst_bus_add_watch
(
bus
,
_onBusMessage
,
this
);
gst_object_unref
(
bus
);
bus
=
NULL
;
}
running
=
gst_element_set_state
(
_pipeline
,
GST_STATE_PLAYING
)
!=
GST_STATE_CHANGE_FAILURE
;
}
while
(
0
);
if
(
caps
!=
NULL
)
{
gst_caps_unref
(
caps
);
caps
=
NULL
;
}
if
(
!
running
)
{
qCritical
()
<<
"VideoReceiver::start() failed"
;
if
(
decoder
!=
NULL
)
{
gst_object_unref
(
decoder
);
decoder
=
NULL
;
}
if
(
parser
!=
NULL
)
{
gst_object_unref
(
parser
);
parser
=
NULL
;
}
if
(
demux
!=
NULL
)
{
gst_object_unref
(
demux
);
demux
=
NULL
;
}
if
(
dataSource
!=
NULL
)
{
gst_object_unref
(
dataSource
);
dataSource
=
NULL
;
}
if
(
_pipeline
!=
NULL
)
{
gst_object_unref
(
_pipeline
);
_pipeline
=
NULL
;
}
}
}
void
VideoReceiver
::
stop
()
{
if
(
_pipeline
!=
NULL
)
{
gst_element_set_state
(
_pipeline
,
GST_STATE_NULL
);
gst_object_unref
(
_pipeline
);
_pipeline
=
NULL
;
}
}
void
VideoReceiver
::
setUri
(
const
QString
&
uri
)
{
stop
();
_uri
=
uri
;
}
void
VideoReceiver
::
_onBusMessage
(
GstMessage
*
msg
)
{
switch
(
GST_MESSAGE_TYPE
(
msg
))
{
case
GST_MESSAGE_EOS
:
stop
();
break
;
case
GST_MESSAGE_ERROR
:
do
{
gchar
*
debug
;
GError
*
error
;
gst_message_parse_error
(
msg
,
&
error
,
&
debug
);
g_free
(
debug
);
qCritical
()
<<
error
->
message
;
g_error_free
(
error
);
}
while
(
0
);
stop
();
break
;
default:
break
;
}
}
gboolean
VideoReceiver
::
_onBusMessage
(
GstBus
*
bus
,
GstMessage
*
msg
,
gpointer
data
)
{
Q_UNUSED
(
bus
)
Q_ASSERT
(
msg
!=
NULL
&&
data
!=
NULL
);
VideoReceiver
*
pThis
=
(
VideoReceiver
*
)
data
;
pThis
->
_onBusMessage
(
msg
);
return
TRUE
;
}
src/VideoStreaming/VideoReceiver.h
0 → 100644
View file @
4b4f758b
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009, 2015 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/**
* @file
* @brief QGC Video Receiver
* @author Gus Grubba <mavlink@grubba.com>
*/
#ifndef VIDEORECEIVER_H
#define VIDEORECEIVER_H
#include <QObject>
#include <gst/gst.h>
class
VideoReceiver
:
public
QObject
{
Q_OBJECT
public:
explicit
VideoReceiver
(
QObject
*
parent
=
0
);
~
VideoReceiver
();
void
setVideoSink
(
GstElement
*
sink
);
public
Q_SLOTS
:
void
start
();
void
stop
();
void
setUri
(
const
QString
&
uri
);
private:
void
_onBusMessage
(
GstMessage
*
message
);
static
gboolean
_onBusMessage
(
GstBus
*
bus
,
GstMessage
*
msg
,
gpointer
data
);
QString
_uri
;
GstElement
*
_pipeline
;
GstElement
*
_videoSink
;
};
#endif // VIDEORECEIVER_H
src/VideoStreaming/VideoStreaming.pri
0 → 100644
View file @
4b4f758b
# -------------------------------------------------
# QGroundControl - Micro Air Vehicle Groundstation
# Please see our website at <http://qgroundcontrol.org>
# Maintainer:
# Lorenz Meier <lm@inf.ethz.ch>
# (c) 2009-2015 QGroundControl Developers
#
# This file is part of the open groundstation project
# QGroundControl is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# QGroundControl is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with QGroundControl. If not, see <http://www.gnu.org/licenses/>.
#
# Author: Gus Grubba <mavlink@grubba.com>
# -------------------------------------------------
#
#-- Depends on gstreamer, which can be found at: http://gstreamer.freedesktop.org/download/
#
LinuxBuild {
CONFIG += link_pkgconfig
packagesExist(gstreamer-1.0) {
message("Including support for video streaming")
DEFINES += QGC_GST_STREAMING
PKGCONFIG += gstreamer-1.0
CONFIG += VideoEnabled
}
} else:MacBuild {
#- gstreamer framework installed by the gstreamer devel installer
GST_ROOT = /Library/Frameworks/GStreamer.framework
exists($$GST_ROOT) {
message("Including support for video streaming")
DEFINES += QGC_GST_STREAMING
CONFIG += VideoEnabled
INCLUDEPATH += $$GST_ROOT/Headers
LIBS += -F/Library/Frameworks -framework GStreamer
}
}
VideoEnabled {
DEFINES += \
GST_PLUGIN_BUILD_STATIC \
QTGLVIDEOSINK_NAME=qt5glvideosink \
QTVIDEOSINK_NAME=qt5videosink
#QT_NO_KEYWORDS \
INCLUDEPATH += \
$$PWD \
$$PWD/gstqtvideosink \
$$PWD/gstqtvideosink/delegates \
$$PWD/gstqtvideosink/painters \
$$PWD/gstqtvideosink/utils \
HEADERS += \
$$PWD/VideoItem.h \
$$PWD/VideoReceiver.h \
$$PWD/VideoSurface.h \
$$PWD/VideoSurface_p.h \
SOURCES += \
$$PWD/VideoItem.cc \
$$PWD/VideoReceiver.cc \
$$PWD/VideoSurface.cc \
#-- QtGstreamer (gutted to our needs)
HEADERS += \
$$PWD/gstqtvideosink/delegates/basedelegate.h \
$$PWD/gstqtvideosink/delegates/qtquick2videosinkdelegate.h \
$$PWD/gstqtvideosink/delegates/qtvideosinkdelegate.h \
$$PWD/gstqtvideosink/delegates/qwidgetvideosinkdelegate.h \
$$PWD/gstqtvideosink/gstqtglvideosink.h \
$$PWD/gstqtvideosink/gstqtglvideosinkbase.h \
$$PWD/gstqtvideosink/gstqtquick2videosink.h \
$$PWD/gstqtvideosink/gstqtvideosink.h \
$$PWD/gstqtvideosink/gstqtvideosinkbase.h \
$$PWD/gstqtvideosink/gstqtvideosinkmarshal.h \
$$PWD/gstqtvideosink/gstqtvideosinkplugin.h \
$$PWD/gstqtvideosink/gstqwidgetvideosink.h \
$$PWD/gstqtvideosink/painters/abstractsurfacepainter.h \
$$PWD/gstqtvideosink/painters/genericsurfacepainter.h \
$$PWD/gstqtvideosink/painters/openglsurfacepainter.h \
$$PWD/gstqtvideosink/painters/videomaterial.h \
$$PWD/gstqtvideosink/painters/videonode.h \
$$PWD/gstqtvideosink/utils/bufferformat.h \
$$PWD/gstqtvideosink/utils/utils.h \
SOURCES += \
$$PWD/gstqtvideosink/delegates/basedelegate.cpp \
$$PWD/gstqtvideosink/delegates/qtquick2videosinkdelegate.cpp \
$$PWD/gstqtvideosink/delegates/qtvideosinkdelegate.cpp \
$$PWD/gstqtvideosink/delegates/qwidgetvideosinkdelegate.cpp \
$$PWD/gstqtvideosink/gstqtglvideosink.cpp \
$$PWD/gstqtvideosink/gstqtglvideosinkbase.cpp \
$$PWD/gstqtvideosink/gstqtvideosinkmarshal.c \
$$PWD/gstqtvideosink/gstqtquick2videosink.cpp \
$$PWD/gstqtvideosink/gstqtvideosink.cpp \
$$PWD/gstqtvideosink/gstqtvideosinkbase.cpp \
$$PWD/gstqtvideosink/gstqtvideosinkplugin.cpp \
$$PWD/gstqtvideosink/gstqwidgetvideosink.cpp \
$$PWD/gstqtvideosink/painters/genericsurfacepainter.cpp \
$$PWD/gstqtvideosink/painters/openglsurfacepainter.cpp \
$$PWD/gstqtvideosink/painters/videomaterial.cpp \
$$PWD/gstqtvideosink/painters/videonode.cpp \
$$PWD/gstqtvideosink/utils/bufferformat.cpp \
$$PWD/gstqtvideosink/utils/utils.cpp \
} else {
message("Skipping support for video streaming (Unsupported platform)")
}
src/VideoStreaming/VideoSurface.cc
0 → 100644
View file @
4b4f758b
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009, 2015 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/**
* @file
* @brief QGC Video Surface
* @author Gus Grubba <mavlink@grubba.com>
*/
#include "videosurface_p.h"
#include <QtCore/QDebug>
#include <QtQuick/QQuickItem>
VideoSurface
::
VideoSurface
(
QObject
*
parent
)
:
QObject
(
parent
)
,
_data
(
new
VideoSurfacePrivate
)
{
}
VideoSurface
::~
VideoSurface
()
{
if
(
_data
->
videoSink
!=
NULL
)
{
gst_element_set_state
(
_data
->
videoSink
,
GST_STATE_NULL
);
}
delete
_data
;
}
GstElement
*
VideoSurface
::
videoSink
()
const
{
if
(
_data
->
videoSink
==
NULL
)
{
if
((
_data
->
videoSink
=
gst_element_factory_make
(
"qtquick2videosink"
,
NULL
))
==
NULL
)
{
qCritical
(
"Failed to create qtquick2videosink. Make sure it is installed correctly"
);
return
NULL
;
}
g_signal_connect
(
_data
->
videoSink
,
"update"
,
G_CALLBACK
(
onUpdateThunk
),
(
void
*
)
this
);
}
return
_data
->
videoSink
;
}
void
VideoSurface
::
onUpdate
()
{
Q_FOREACH
(
QQuickItem
*
item
,
_data
->
items
)
{
item
->
update
();
}
}
void
VideoSurface
::
onUpdateThunk
(
GstElement
*
sink
,
gpointer
data
)
{
Q_UNUSED
(
sink
);
VideoSurface
*
pThis
=
(
VideoSurface
*
)
data
;
pThis
->
onUpdate
();
}
src/VideoStreaming/VideoSurface.h
0 → 100644
View file @
4b4f758b
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009, 2015 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/**
* @file
* @brief QGC Video Surface
* @author Gus Grubba <mavlink@grubba.com>
*/
#ifndef VIDEO_SURFACE_H
#define VIDEO_SURFACE_H
#include <QtCore/QObject>
#include <gst/gst.h>
class
VideoSurfacePrivate
;
class
VideoSurface
:
public
QObject
{
Q_OBJECT
Q_DISABLE_COPY
(
VideoSurface
)
public:
explicit
VideoSurface
(
QObject
*
parent
=
0
);
virtual
~
VideoSurface
();
/*! Returns the video sink element that provides this surface's image.
* The element will be constructed the first time that this function
* is called. The surface will always keep a reference to this element.
*/
GstElement
*
videoSink
()
const
;
protected:
void
onUpdate
();
static
void
onUpdateThunk
(
GstElement
*
sink
,
gpointer
data
);
private:
friend
class
VideoItem
;
VideoSurfacePrivate
*
const
_data
;
};
Q_DECLARE_METATYPE
(
VideoSurface
*
)
#endif // VIDEO_SURFACE_H
src/VideoStreaming/gstqtvideosink/delegates/basedelegate.cpp
0 → 100644
View file @
4b4f758b
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011-2013 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#include "basedelegate.h"
#include <QCoreApplication>
BaseDelegate
::
BaseDelegate
(
GstElement
*
sink
,
QObject
*
parent
)
:
QObject
(
parent
)
,
m_colorsDirty
(
true
)
,
m_brightness
(
0
)
,
m_contrast
(
0
)
,
m_hue
(
0
)
,
m_saturation
(
0
)
,
m_pixelAspectRatio
(
1
,
1
)
,
m_forceAspectRatioDirty
(
true
)
,
m_forceAspectRatio
(
false
)
,
m_formatDirty
(
true
)
,
m_isActive
(
false
)
,
m_buffer
(
NULL
)
,
m_sink
(
sink
)
{
}
BaseDelegate
::~
BaseDelegate
()
{
Q_ASSERT
(
!
isActive
());
}
//-------------------------------------
bool
BaseDelegate
::
isActive
()
const
{
QReadLocker
l
(
&
m_isActiveLock
);
return
m_isActive
;
}
void
BaseDelegate
::
setActive
(
bool
active
)
{
GST_INFO_OBJECT
(
m_sink
,
active
?
"Activating"
:
"Deactivating"
);
QWriteLocker
l
(
&
m_isActiveLock
);
m_isActive
=
active
;
if
(
!
active
)
{
QCoreApplication
::
postEvent
(
this
,
new
DeactivateEvent
());
}
}
//-------------------------------------
int
BaseDelegate
::
brightness
()
const
{
QReadLocker
l
(
&
m_colorsLock
);
return
m_brightness
;
}
void
BaseDelegate
::
setBrightness
(
int
brightness
)
{
QWriteLocker
l
(
&
m_colorsLock
);
m_brightness
=
qBound
(
-
100
,
brightness
,
100
);
m_colorsDirty
=
true
;
}
int
BaseDelegate
::
contrast
()
const
{
QReadLocker
l
(
&
m_colorsLock
);
return
m_contrast
;
}
void
BaseDelegate
::
setContrast
(
int
contrast
)
{
QWriteLocker
l
(
&
m_colorsLock
);
m_contrast
=
qBound
(
-
100
,
contrast
,
100
);
m_colorsDirty
=
true
;
}
int
BaseDelegate
::
hue
()
const
{
QReadLocker
l
(
&
m_colorsLock
);
return
m_hue
;
}
void
BaseDelegate
::
setHue
(
int
hue
)
{
QWriteLocker
l
(
&
m_colorsLock
);
m_hue
=
qBound
(
-
100
,
hue
,
100
);
m_colorsDirty
=
true
;
}
int
BaseDelegate
::
saturation
()
const
{
QReadLocker
l
(
&
m_colorsLock
);
return
m_saturation
;
}
void
BaseDelegate
::
setSaturation
(
int
saturation
)
{
QWriteLocker
l
(
&
m_colorsLock
);
m_saturation
=
qBound
(
-
100
,
saturation
,
100
);
m_colorsDirty
=
true
;
}
//-------------------------------------
Fraction
BaseDelegate
::
pixelAspectRatio
()
const
{
QReadLocker
l
(
&
m_pixelAspectRatioLock
);
return
m_pixelAspectRatio
;
}
void
BaseDelegate
::
setPixelAspectRatio
(
const
Fraction
&
f
)
{
QWriteLocker
l
(
&
m_pixelAspectRatioLock
);
m_pixelAspectRatio
=
f
;
}
//-------------------------------------
bool
BaseDelegate
::
forceAspectRatio
()
const
{
QReadLocker
l
(
&
m_forceAspectRatioLock
);
return
m_forceAspectRatio
;
}
void
BaseDelegate
::
setForceAspectRatio
(
bool
force
)
{
QWriteLocker
l
(
&
m_forceAspectRatioLock
);
if
(
m_forceAspectRatio
!=
force
)
{
m_forceAspectRatio
=
force
;
m_forceAspectRatioDirty
=
true
;
}
}
//-------------------------------------
bool
BaseDelegate
::
event
(
QEvent
*
event
)
{
switch
((
int
)
event
->
type
())
{
case
BufferEventType
:
{
BufferEvent
*
bufEvent
=
dynamic_cast
<
BufferEvent
*>
(
event
);
Q_ASSERT
(
bufEvent
);
GST_TRACE_OBJECT
(
m_sink
,
"Received buffer %"
GST_PTR_FORMAT
,
bufEvent
->
buffer
);
if
(
isActive
())
{
gst_buffer_replace
(
&
m_buffer
,
bufEvent
->
buffer
);
update
();
}
return
true
;
}
case
BufferFormatEventType
:
{
BufferFormatEvent
*
bufFmtEvent
=
dynamic_cast
<
BufferFormatEvent
*>
(
event
);
Q_ASSERT
(
bufFmtEvent
);
GST_TRACE_OBJECT
(
m_sink
,
"Received buffer format event. New format: %s"
,
gst_video_format_to_string
(
bufFmtEvent
->
format
.
videoFormat
()));
m_formatDirty
=
true
;
m_bufferFormat
=
bufFmtEvent
->
format
;
return
true
;
}
case
DeactivateEventType
:
{
GST_LOG_OBJECT
(
m_sink
,
"Received deactivate event"
);
gst_buffer_replace
(
&
m_buffer
,
NULL
);
update
();
return
true
;
}
default:
return
QObject
::
event
(
event
);
}
}
void
BaseDelegate
::
update
()
{
g_signal_emit_by_name
(
m_sink
,
"update"
);
}
src/VideoStreaming/gstqtvideosink/delegates/basedelegate.h
0 → 100644
View file @
4b4f758b
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011-2013 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#ifndef BASEDELEGATE_H
#define BASEDELEGATE_H
#include <gst/gst.h>
#include "../gstqtvideosinkplugin.h" //for debug category
#include "../utils/bufferformat.h"
#include "../utils/utils.h"
#include <QObject>
#include <QEvent>
#include <QReadWriteLock>
class
BaseDelegate
:
public
QObject
{
Q_OBJECT
public:
enum
EventType
{
BufferEventType
=
QEvent
::
User
,
BufferFormatEventType
,
DeactivateEventType
};
//-------------------------------------
class
BufferEvent
:
public
QEvent
{
public:
inline
BufferEvent
(
GstBuffer
*
buf
)
:
QEvent
(
static_cast
<
QEvent
::
Type
>
(
BufferEventType
)),
buffer
(
gst_buffer_ref
(
buf
))
{}
virtual
~
BufferEvent
()
{
gst_buffer_unref
(
buffer
);
}
GstBuffer
*
buffer
;
};
class
BufferFormatEvent
:
public
QEvent
{
public:
inline
BufferFormatEvent
(
const
BufferFormat
&
format
)
:
QEvent
(
static_cast
<
QEvent
::
Type
>
(
BufferFormatEventType
)),
format
(
format
)
{}
BufferFormat
format
;
};
class
DeactivateEvent
:
public
QEvent
{
public:
inline
DeactivateEvent
()
:
QEvent
(
static_cast
<
QEvent
::
Type
>
(
DeactivateEventType
))
{
}
};
//-------------------------------------
explicit
BaseDelegate
(
GstElement
*
sink
,
QObject
*
parent
=
0
);
virtual
~
BaseDelegate
();
bool
isActive
()
const
;
void
setActive
(
bool
playing
);
// GstColorBalance interface
int
brightness
()
const
;
void
setBrightness
(
int
brightness
);
int
contrast
()
const
;
void
setContrast
(
int
contrast
);
int
hue
()
const
;
void
setHue
(
int
hue
);
int
saturation
()
const
;
void
setSaturation
(
int
saturation
);
// pixel-aspect-ratio property
Fraction
pixelAspectRatio
()
const
;
void
setPixelAspectRatio
(
const
Fraction
&
f
);
// force-aspect-ratio property
bool
forceAspectRatio
()
const
;
void
setForceAspectRatio
(
bool
force
);
protected:
// internal event handling
virtual
bool
event
(
QEvent
*
event
);
// tells the surface to repaint itself
virtual
void
update
();
protected:
// colorbalance interface properties
mutable
QReadWriteLock
m_colorsLock
;
bool
m_colorsDirty
;
int
m_brightness
;
int
m_contrast
;
int
m_hue
;
int
m_saturation
;
// pixel-aspect-ratio property
mutable
QReadWriteLock
m_pixelAspectRatioLock
;
Fraction
m_pixelAspectRatio
;
// force-aspect-ratio property
mutable
QReadWriteLock
m_forceAspectRatioLock
;
bool
m_forceAspectRatioDirty
;
bool
m_forceAspectRatio
;
// format caching
bool
m_formatDirty
;
BufferFormat
m_bufferFormat
;
PaintAreas
m_areas
;
// whether the sink is active (PAUSED or PLAYING)
mutable
QReadWriteLock
m_isActiveLock
;
bool
m_isActive
;
// the buffer to be drawn next
GstBuffer
*
m_buffer
;
// the video sink element
GstElement
*
const
m_sink
;
};
#endif // BASEDELEGATE_H
src/VideoStreaming/gstqtvideosink/delegates/qtquick2videosinkdelegate.cpp
0 → 100644
View file @
4b4f758b
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011-2013 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#include "qtquick2videosinkdelegate.h"
#include "../painters/videonode.h"
QtQuick2VideoSinkDelegate
::
QtQuick2VideoSinkDelegate
(
GstElement
*
sink
,
QObject
*
parent
)
:
BaseDelegate
(
sink
,
parent
)
{
}
QSGNode
*
QtQuick2VideoSinkDelegate
::
updateNode
(
QSGNode
*
node
,
const
QRectF
&
targetArea
)
{
GST_TRACE_OBJECT
(
m_sink
,
"updateNode called"
);
bool
sgnodeFormatChanged
=
false
;
VideoNode
*
vnode
=
dynamic_cast
<
VideoNode
*>
(
node
);
if
(
!
vnode
)
{
GST_INFO_OBJECT
(
m_sink
,
"creating new VideoNode"
);
vnode
=
new
VideoNode
;
}
if
(
!
m_buffer
)
{
if
(
vnode
->
materialType
()
!=
VideoNode
::
MaterialTypeSolidBlack
)
{
vnode
->
setMaterialTypeSolidBlack
();
sgnodeFormatChanged
=
true
;
}
if
(
sgnodeFormatChanged
||
targetArea
!=
m_areas
.
targetArea
)
{
m_areas
.
targetArea
=
targetArea
;
vnode
->
updateGeometry
(
m_areas
);
}
}
else
{
//change format before geometry, so that we change QSGGeometry as well
if
(
m_formatDirty
)
{
vnode
->
changeFormat
(
m_bufferFormat
);
sgnodeFormatChanged
=
true
;
}
//recalculate the video area if needed
QReadLocker
forceAspectRatioLocker
(
&
m_forceAspectRatioLock
);
if
(
sgnodeFormatChanged
||
targetArea
!=
m_areas
.
targetArea
||
m_forceAspectRatioDirty
)
{
m_forceAspectRatioDirty
=
false
;
QReadLocker
pixelAspectRatioLocker
(
&
m_pixelAspectRatioLock
);
Qt
::
AspectRatioMode
aspectRatioMode
=
m_forceAspectRatio
?
Qt
::
KeepAspectRatio
:
Qt
::
IgnoreAspectRatio
;
m_areas
.
calculate
(
targetArea
,
m_bufferFormat
.
frameSize
(),
m_bufferFormat
.
pixelAspectRatio
(),
m_pixelAspectRatio
,
aspectRatioMode
);
pixelAspectRatioLocker
.
unlock
();
GST_LOG_OBJECT
(
m_sink
,
"Recalculated paint areas: "
"Frame size: "
QSIZE_FORMAT
", "
"target area: "
QRECTF_FORMAT
", "
"video area: "
QRECTF_FORMAT
", "
"black1: "
QRECTF_FORMAT
", "
"black2: "
QRECTF_FORMAT
,
QSIZE_FORMAT_ARGS
(
m_bufferFormat
.
frameSize
()),
QRECTF_FORMAT_ARGS
(
m_areas
.
targetArea
),
QRECTF_FORMAT_ARGS
(
m_areas
.
videoArea
),
QRECTF_FORMAT_ARGS
(
m_areas
.
blackArea1
),
QRECTF_FORMAT_ARGS
(
m_areas
.
blackArea2
)
);
vnode
->
updateGeometry
(
m_areas
);
}
forceAspectRatioLocker
.
unlock
();
if
(
m_formatDirty
)
{
m_formatDirty
=
false
;
//make sure to update the colors after changing material
m_colorsDirty
=
true
;
}
QReadLocker
colorsLocker
(
&
m_colorsLock
);
if
(
m_colorsDirty
)
{
vnode
->
updateColors
(
m_brightness
,
m_contrast
,
m_hue
,
m_saturation
);
m_colorsDirty
=
false
;
}
colorsLocker
.
unlock
();
vnode
->
setCurrentFrame
(
m_buffer
);
}
return
vnode
;
}
src/VideoStreaming/gstqtvideosink/delegates/qtquick2videosinkdelegate.h
0 → 100644
View file @
4b4f758b
/*
Copyright (C) 2013 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#ifndef QTQUICK2VIDEOSINKDELEGATE_H
#define QTQUICK2VIDEOSINKDELEGATE_H
#include "basedelegate.h"
#include <QtQuick/QSGNode>
class
QtQuick2VideoSinkDelegate
:
public
BaseDelegate
{
Q_OBJECT
public:
explicit
QtQuick2VideoSinkDelegate
(
GstElement
*
sink
,
QObject
*
parent
=
0
);
QSGNode
*
updateNode
(
QSGNode
*
node
,
const
QRectF
&
targetArea
);
};
#endif // QTQUICK2VIDEOSINKDELEGATE_H
src/VideoStreaming/gstqtvideosink/delegates/qtvideosinkdelegate.cpp
0 → 100644
View file @
4b4f758b
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#include "qtvideosinkdelegate.h"
#include "../painters/genericsurfacepainter.h"
#include "../painters/openglsurfacepainter.h"
#include <QStack>
#include <QPainter>
QtVideoSinkDelegate
::
QtVideoSinkDelegate
(
GstElement
*
sink
,
QObject
*
parent
)
:
BaseDelegate
(
sink
,
parent
)
,
m_painter
(
0
)
,
m_supportedPainters
(
Generic
)
#ifndef GST_QT_VIDEO_SINK_NO_OPENGL
,
m_glContext
(
0
)
#endif
{
}
QtVideoSinkDelegate
::~
QtVideoSinkDelegate
()
{
destroyPainter
();
}
void
QtVideoSinkDelegate
::
paint
(
QPainter
*
painter
,
const
QRectF
&
targetArea
)
{
GST_TRACE_OBJECT
(
m_sink
,
"paint called"
);
#ifndef GST_QT_VIDEO_SINK_NO_OPENGL
if
(
m_glContext
)
{
Q_ASSERT_X
(
m_glContext
==
QGLContext
::
currentContext
(),
"qtvideosink - paint"
,
"Please use a QPainter that is initialized to paint on the "
"GL surface that has the same context as the one given on the glcontext property"
);
}
#endif
if
(
!
m_buffer
)
{
painter
->
fillRect
(
targetArea
,
Qt
::
black
);
}
else
{
//recalculate the video area if needed
QReadLocker
forceAspectRatioLocker
(
&
m_forceAspectRatioLock
);
if
(
targetArea
!=
m_areas
.
targetArea
||
m_formatDirty
||
m_forceAspectRatioDirty
)
{
m_forceAspectRatioDirty
=
false
;
QReadLocker
pixelAspectRatioLocker
(
&
m_pixelAspectRatioLock
);
Qt
::
AspectRatioMode
aspectRatioMode
=
m_forceAspectRatio
?
Qt
::
KeepAspectRatio
:
Qt
::
IgnoreAspectRatio
;
m_areas
.
calculate
(
targetArea
,
m_bufferFormat
.
frameSize
(),
m_bufferFormat
.
pixelAspectRatio
(),
m_pixelAspectRatio
,
aspectRatioMode
);
pixelAspectRatioLocker
.
unlock
();
GST_LOG_OBJECT
(
m_sink
,
"Recalculated paint areas: "
"Frame size: "
QSIZE_FORMAT
", "
"target area: "
QRECTF_FORMAT
", "
"video area: "
QRECTF_FORMAT
", "
"black1: "
QRECTF_FORMAT
", "
"black2: "
QRECTF_FORMAT
,
QSIZE_FORMAT_ARGS
(
m_bufferFormat
.
frameSize
()),
QRECTF_FORMAT_ARGS
(
m_areas
.
targetArea
),
QRECTF_FORMAT_ARGS
(
m_areas
.
videoArea
),
QRECTF_FORMAT_ARGS
(
m_areas
.
blackArea1
),
QRECTF_FORMAT_ARGS
(
m_areas
.
blackArea2
)
);
}
forceAspectRatioLocker
.
unlock
();
//if either pixelFormat or frameSize have changed, we need to reset the painter
//and/or change painter, in case the current one does not handle the requested format
if
((
m_formatDirty
)
||
!
m_painter
)
{
changePainter
(
m_bufferFormat
);
m_formatDirty
=
false
;
//make sure to update the colors after changing painter
m_colorsDirty
=
true
;
}
if
(
G_LIKELY
(
m_painter
))
{
QReadLocker
colorsLocker
(
&
m_colorsLock
);
if
(
m_colorsDirty
)
{
m_painter
->
updateColors
(
m_brightness
,
m_contrast
,
m_hue
,
m_saturation
);
m_colorsDirty
=
false
;
}
colorsLocker
.
unlock
();
GstMapInfo
mem_info
;
if
(
gst_buffer_map
(
m_buffer
,
&
mem_info
,
GST_MAP_READ
))
{
m_painter
->
paint
(
mem_info
.
data
,
m_bufferFormat
,
painter
,
m_areas
);
gst_buffer_unmap
(
m_buffer
,
&
mem_info
);
}
}
}
}
#ifndef GST_QT_VIDEO_SINK_NO_OPENGL
QGLContext
*
QtVideoSinkDelegate
::
glContext
()
const
{
return
m_glContext
;
}
void
QtVideoSinkDelegate
::
setGLContext
(
QGLContext
*
context
)
{
if
(
m_glContext
==
context
)
return
;
m_glContext
=
context
;
m_supportedPainters
=
Generic
;
if
(
m_glContext
)
{
m_glContext
->
makeCurrent
();
const
QByteArray
extensions
(
reinterpret_cast
<
const
char
*>
(
glGetString
(
GL_EXTENSIONS
)));
GST_LOG_OBJECT
(
m_sink
,
"Available GL extensions: %s"
,
extensions
.
constData
());
#ifndef QT_OPENGL_ES
if
(
extensions
.
contains
(
"ARB_fragment_program"
))
m_supportedPainters
|=
ArbFp
;
#endif
#ifndef QT_OPENGL_ES_2
if
(
QGLShaderProgram
::
hasOpenGLShaderPrograms
(
m_glContext
)
&&
extensions
.
contains
(
"ARB_shader_objects"
))
#endif
m_supportedPainters
|=
Glsl
;
}
GST_LOG_OBJECT
(
m_sink
,
"Done setting GL context. m_supportedPainters=%x"
,
(
int
)
m_supportedPainters
);
}
#endif
void
QtVideoSinkDelegate
::
changePainter
(
const
BufferFormat
&
format
)
{
if
(
m_painter
)
{
m_painter
->
cleanup
();
if
(
G_UNLIKELY
(
!
m_painter
->
supportsFormat
(
format
.
videoFormat
())))
{
destroyPainter
();
}
}
QStack
<
PainterType
>
possiblePainters
;
if
(
GenericSurfacePainter
::
supportedPixelFormats
().
contains
(
format
.
videoFormat
()))
{
possiblePainters
.
push
(
Generic
);
}
#ifndef GST_QT_VIDEO_SINK_NO_OPENGL
if
(
OpenGLSurfacePainter
::
supportedPixelFormats
().
contains
(
format
.
videoFormat
()))
{
if
(
m_supportedPainters
&
ArbFp
)
{
possiblePainters
.
push
(
ArbFp
);
}
if
(
m_supportedPainters
&
Glsl
)
{
possiblePainters
.
push
(
Glsl
);
}
}
#endif
while
(
!
possiblePainters
.
isEmpty
())
{
if
(
!
m_painter
)
{
PainterType
type
=
possiblePainters
.
pop
();
switch
(
type
)
{
#ifndef GST_QT_VIDEO_SINK_NO_OPENGL
case
Glsl
:
GST_LOG_OBJECT
(
m_sink
,
"Creating GLSL painter"
);
m_painter
=
new
GlslSurfacePainter
;
break
;
# ifndef QT_OPENGL_ES
case
ArbFp
:
GST_LOG_OBJECT
(
m_sink
,
"Creating ARB Fragment Shader painter"
);
m_painter
=
new
ArbFpSurfacePainter
;
break
;
# endif
#endif
case
Generic
:
GST_LOG_OBJECT
(
m_sink
,
"Creating Generic painter"
);
m_painter
=
new
GenericSurfacePainter
;
break
;
default:
Q_ASSERT
(
false
);
}
}
try
{
m_painter
->
init
(
format
);
return
;
}
catch
(
const
QString
&
error
)
{
GST_ELEMENT_WARNING
(
m_sink
,
RESOURCE
,
FAILED
,
(
"Failed to start painter"
),
(
"%s"
,
error
.
toUtf8
().
constData
()));
delete
m_painter
;
m_painter
=
0
;
}
}
GST_ELEMENT_ERROR
(
m_sink
,
RESOURCE
,
FAILED
,
(
"Failed to create a painter for the given format"
),
(
NULL
));
}
void
QtVideoSinkDelegate
::
destroyPainter
()
{
GST_LOG_OBJECT
(
m_sink
,
"Destroying painter"
);
delete
m_painter
;
m_painter
=
0
;
}
bool
QtVideoSinkDelegate
::
event
(
QEvent
*
event
)
{
if
(
event
->
type
()
==
(
QEvent
::
Type
)
DeactivateEventType
)
{
if
(
m_painter
)
{
m_painter
->
cleanup
();
destroyPainter
();
}
}
return
BaseDelegate
::
event
(
event
);
}
src/VideoStreaming/gstqtvideosink/delegates/qtvideosinkdelegate.h
0 → 100644
View file @
4b4f758b
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#ifndef QT_VIDEO_SINK_DELEGATE_H
#define QT_VIDEO_SINK_DELEGATE_H
#include "basedelegate.h"
#include "../painters/abstractsurfacepainter.h"
class
QGLContext
;
class
QtVideoSinkDelegate
:
public
BaseDelegate
{
Q_OBJECT
public:
enum
PainterType
{
Generic
=
0x00
,
ArbFp
=
0x01
,
Glsl
=
0x02
};
Q_DECLARE_FLAGS
(
PainterTypes
,
PainterType
);
explicit
QtVideoSinkDelegate
(
GstElement
*
sink
,
QObject
*
parent
=
0
);
virtual
~
QtVideoSinkDelegate
();
PainterTypes
supportedPainterTypes
()
const
{
return
m_supportedPainters
;
}
#ifndef GST_QT_VIDEO_SINK_NO_OPENGL
// glcontext property
QGLContext
*
glContext
()
const
;
void
setGLContext
(
QGLContext
*
context
);
#endif
// paint action
void
paint
(
QPainter
*
painter
,
const
QRectF
&
targetArea
);
protected:
// internal event handling
virtual
bool
event
(
QEvent
*
event
);
private:
void
changePainter
(
const
BufferFormat
&
format
);
void
destroyPainter
();
AbstractSurfacePainter
*
m_painter
;
PainterTypes
m_supportedPainters
;
#ifndef GST_QT_VIDEO_SINK_NO_OPENGL
QGLContext
*
m_glContext
;
#endif
};
Q_DECLARE_OPERATORS_FOR_FLAGS
(
QtVideoSinkDelegate
::
PainterTypes
)
#endif // QT_VIDEO_SINK_DELEGATE_H
src/VideoStreaming/gstqtvideosink/delegates/qwidgetvideosinkdelegate.cpp
0 → 100644
View file @
4b4f758b
/*
Copyright (C) 2010 George Kiagiadakis <kiagiadakis.george@gmail.com>
Copyright (C) 2012 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#include "qwidgetvideosinkdelegate.h"
#include <QPainter>
QWidgetVideoSinkDelegate
::
QWidgetVideoSinkDelegate
(
GstElement
*
sink
,
QObject
*
parent
)
:
QtVideoSinkDelegate
(
sink
,
parent
)
{
}
QWidgetVideoSinkDelegate
::~
QWidgetVideoSinkDelegate
()
{
setWidget
(
NULL
);
}
QWidget
*
QWidgetVideoSinkDelegate
::
widget
()
const
{
return
m_widget
.
data
();
}
void
QWidgetVideoSinkDelegate
::
setWidget
(
QWidget
*
widget
)
{
GST_LOG_OBJECT
(
m_sink
,
"Setting
\"
widget
\"
property to %"
GST_PTR_FORMAT
,
widget
);
if
(
m_widget
)
{
m_widget
.
data
()
->
removeEventFilter
(
this
);
m_widget
.
data
()
->
setAttribute
(
Qt
::
WA_OpaquePaintEvent
,
m_opaquePaintEventAttribute
);
m_widget
.
data
()
->
update
();
m_widget
=
NULL
;
}
if
(
widget
)
{
widget
->
installEventFilter
(
this
);
m_opaquePaintEventAttribute
=
widget
->
testAttribute
(
Qt
::
WA_OpaquePaintEvent
);
widget
->
setAttribute
(
Qt
::
WA_OpaquePaintEvent
,
true
);
widget
->
update
();
m_widget
=
widget
;
}
}
bool
QWidgetVideoSinkDelegate
::
eventFilter
(
QObject
*
filteredObject
,
QEvent
*
event
)
{
if
(
filteredObject
==
m_widget
.
data
())
{
switch
(
event
->
type
())
{
case
QEvent
:
:
Paint
:
{
QPainter
painter
(
m_widget
.
data
());
paint
(
&
painter
,
m_widget
.
data
()
->
rect
());
return
true
;
}
default:
return
false
;
}
}
else
{
return
QtVideoSinkDelegate
::
eventFilter
(
filteredObject
,
event
);
}
}
void
QWidgetVideoSinkDelegate
::
update
()
{
if
(
m_widget
)
{
m_widget
.
data
()
->
update
();
}
}
src/VideoStreaming/gstqtvideosink/delegates/qwidgetvideosinkdelegate.h
0 → 100644
View file @
4b4f758b
/*
Copyright (C) 2010 George Kiagiadakis <kiagiadakis.george@gmail.com>
Copyright (C) 2012 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#ifndef QWIDGET_VIDEO_SINK_DELEGATE_H
#define QWIDGET_VIDEO_SINK_DELEGATE_H
#include "qtvideosinkdelegate.h"
#include <QEvent>
#include <QPointer>
#include <QWidget>
class
QWidgetVideoSinkDelegate
:
public
QtVideoSinkDelegate
{
Q_OBJECT
public:
explicit
QWidgetVideoSinkDelegate
(
GstElement
*
sink
,
QObject
*
parent
=
0
);
virtual
~
QWidgetVideoSinkDelegate
();
// "widget" property
QWidget
*
widget
()
const
;
void
setWidget
(
QWidget
*
widget
);
protected:
virtual
bool
eventFilter
(
QObject
*
filteredObject
,
QEvent
*
event
);
virtual
void
update
();
private:
// "widget" property
QPointer
<
QWidget
>
m_widget
;
// original value of the Qt::WA_OpaquePaintEvent attribute
bool
m_opaquePaintEventAttribute
;
};
#endif // QWIDGET_VIDEO_SINK_DELEGATE_H
src/VideoStreaming/gstqtvideosink/gstqtglvideosink.cpp
0 → 100644
View file @
4b4f758b
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011-2012 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#include "gstqtglvideosink.h"
#include "gstqtvideosinkmarshal.h"
#include "delegates/qtvideosinkdelegate.h"
guint
GstQtGLVideoSink
::
s_signals
[];
DEFINE_TYPE
(
GstQtGLVideoSink
,
GST_TYPE_QT_GL_VIDEO_SINK_BASE
)
//------------------------------
void
GstQtGLVideoSink
::
emit_update
(
gpointer
sink
)
{
g_signal_emit
(
sink
,
GstQtGLVideoSink
::
s_signals
[
UPDATE_SIGNAL
],
0
,
NULL
);
}
//------------------------------
void
GstQtGLVideoSink
::
base_init
(
gpointer
g_class
)
{
GstElementClass
*
element_class
=
GST_ELEMENT_CLASS
(
g_class
);
gst_element_class_set_details_simple
(
element_class
,
"Qt GL video sink"
,
"Sink/Video"
,
"A video sink that can draw on any Qt GL surface"
,
"George Kiagiadakis <george.kiagiadakis@collabora.com>"
);
}
void
GstQtGLVideoSink
::
class_init
(
gpointer
g_class
,
gpointer
class_data
)
{
Q_UNUSED
(
class_data
);
GObjectClass
*
object_class
=
G_OBJECT_CLASS
(
g_class
);
object_class
->
set_property
=
GstQtGLVideoSink
::
set_property
;
GstQtGLVideoSinkClass
*
qt_video_sink_class
=
reinterpret_cast
<
GstQtGLVideoSinkClass
*>
(
g_class
);
qt_video_sink_class
->
paint
=
GstQtGLVideoSink
::
paint
;
/**
* GstQtGLVideoSink::paint
* @painter: A valid QPainter pointer that will be used to paint the video
* @x: The x coordinate of the target area rectangle
* @y: The y coordinate of the target area rectangle
* @width: The width of the target area rectangle
* @height: The height of the target area rectangle
*
* This is an action signal that you can call from your Qt surface class inside
* its paint function to render the video. It takes a QPainter* and the target
* area rectangle as arguments. You should schedule to call this function to
* repaint the surface whenever the ::update signal is emited.
*
* Note that the x,y,width and height arguments are actually qreal. This means
* that on architectures like arm they will be float instead of double. You should
* cast the arguments to qreal if they are not already when emitting this signal.
*/
s_signals
[
PAINT_SIGNAL
]
=
g_signal_new
(
"paint"
,
G_TYPE_FROM_CLASS
(
g_class
),
static_cast
<
GSignalFlags
>
(
G_SIGNAL_RUN_LAST
|
G_SIGNAL_ACTION
),
G_STRUCT_OFFSET
(
GstQtGLVideoSinkClass
,
paint
),
NULL
,
NULL
,
qRealIsDouble
()
?
g_cclosure_user_marshal_VOID__POINTER_DOUBLE_DOUBLE_DOUBLE_DOUBLE
:
g_cclosure_user_marshal_VOID__POINTER_FLOAT_FLOAT_FLOAT_FLOAT
,
G_TYPE_NONE
,
5
,
G_TYPE_POINTER
,
G_TYPE_QREAL
,
G_TYPE_QREAL
,
G_TYPE_QREAL
,
G_TYPE_QREAL
);
/**
* GstQtGLVideoSink::update
*
* This signal is emited when the surface should be repainted. It should
* be connected to QWidget::update() or QGraphicsItem::update() or any
* other similar function in your surface.
*/
s_signals
[
UPDATE_SIGNAL
]
=
g_signal_new
(
"update"
,
G_TYPE_FROM_CLASS
(
g_class
),
G_SIGNAL_RUN_LAST
,
0
,
NULL
,
NULL
,
g_cclosure_marshal_VOID__VOID
,
G_TYPE_NONE
,
0
);
/**
* GstQtGLVideoSink::glcontext
*
* This property holds a pointer to the QGLContext that will be used to render
* the video using OpenGL acceleration. You must set this to a valid QGLContext
* pointer before the element changes state to READY, or else the state change will fail.
**/
g_object_class_install_property
(
object_class
,
PROP_GLCONTEXT
,
g_param_spec_pointer
(
"glcontext"
,
"GL context"
,
"The QGLContext that will be used to do OpenGL-accelerated rendering"
,
static_cast
<
GParamFlags
>
(
G_PARAM_WRITABLE
)));
}
void
GstQtGLVideoSink
::
init
(
GTypeInstance
*
instance
,
gpointer
g_class
)
{
Q_UNUSED
(
g_class
);
GstQtVideoSinkBase
*
sinkBase
=
GST_QT_VIDEO_SINK_BASE
(
instance
);
sinkBase
->
delegate
=
new
QtVideoSinkDelegate
(
GST_ELEMENT
(
sinkBase
));
}
//------------------------------
void
GstQtGLVideoSink
::
set_property
(
GObject
*
object
,
guint
prop_id
,
const
GValue
*
value
,
GParamSpec
*
pspec
)
{
GstQtVideoSinkBase
*
sinkBase
=
GST_QT_VIDEO_SINK_BASE
(
object
);
switch
(
prop_id
)
{
case
PROP_GLCONTEXT
:
sinkBase
->
delegate
->
setGLContext
(
static_cast
<
QGLContext
*>
(
g_value_get_pointer
(
value
)));
break
;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID
(
object
,
prop_id
,
pspec
);
break
;
}
}
//------------------------------
void
GstQtGLVideoSink
::
paint
(
GstQtGLVideoSink
*
sink
,
gpointer
painter
,
qreal
x
,
qreal
y
,
qreal
width
,
qreal
height
)
{
GST_QT_VIDEO_SINK_BASE
(
sink
)
->
delegate
->
paint
(
static_cast
<
QPainter
*>
(
painter
),
QRectF
(
x
,
y
,
width
,
height
));
}
src/VideoStreaming/gstqtvideosink/gstqtglvideosink.h
0 → 100644
View file @
4b4f758b
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011-2012 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#ifndef GST_QT_GL_VIDEO_SINK_H
#define GST_QT_GL_VIDEO_SINK_H
#include "gstqtglvideosinkbase.h"
#ifndef GST_QT_VIDEO_SINK_NO_OPENGL
#define GST_TYPE_QT_GL_VIDEO_SINK \
(GstQtGLVideoSink::get_type())
struct
GstQtGLVideoSink
{
public:
GstQtGLVideoSinkBase
parent
;
static
GType
get_type
();
static
void
emit_update
(
gpointer
sink
);
private:
enum
{
PROP_0
,
PROP_GLCONTEXT
};
enum
{
PAINT_SIGNAL
,
UPDATE_SIGNAL
,
LAST_SIGNAL
};
static
void
base_init
(
gpointer
g_class
);
static
void
class_init
(
gpointer
g_class
,
gpointer
class_data
);
static
void
init
(
GTypeInstance
*
instance
,
gpointer
g_class
);
static
void
set_property
(
GObject
*
object
,
guint
prop_id
,
const
GValue
*
value
,
GParamSpec
*
pspec
);
static
void
paint
(
GstQtGLVideoSink
*
sink
,
gpointer
painter
,
qreal
x
,
qreal
y
,
qreal
width
,
qreal
height
);
static
guint
s_signals
[
LAST_SIGNAL
];
};
struct
GstQtGLVideoSinkClass
{
GstQtGLVideoSinkBaseClass
parent_class
;
/* paint action signal */
void
(
*
paint
)
(
GstQtGLVideoSink
*
sink
,
gpointer
painter
,
qreal
x
,
qreal
y
,
qreal
width
,
qreal
height
);
};
#endif // GST_QT_VIDEO_SINK_NO_OPENGL
#endif // GST_QT_GL_VIDEO_SINK_H
src/VideoStreaming/gstqtvideosink/gstqtglvideosinkbase.cpp
0 → 100644
View file @
4b4f758b
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011-2012 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#include "gstqtglvideosinkbase.h"
#include "painters/openglsurfacepainter.h"
#include "delegates/qtvideosinkdelegate.h"
#include <QCoreApplication>
#define CAPS_FORMATS "{ BGRA, BGRx, ARGB, xRGB, RGB, RGB16, BGR, v308, AYUV, YV12, I420 }"
const
char
*
const
GstQtGLVideoSinkBase
::
s_colorbalance_labels
[]
=
{
"contrast"
,
"brightness"
,
"hue"
,
"saturation"
};
GstQtVideoSinkBaseClass
*
GstQtGLVideoSinkBase
::
s_parent_class
=
0
;
//------------------------------
DEFINE_TYPE_WITH_CODE
(
GstQtGLVideoSinkBase
,
GST_TYPE_QT_VIDEO_SINK_BASE
,
init_interfaces
)
void
GstQtGLVideoSinkBase
::
init_interfaces
(
GType
type
)
{
static
const
GInterfaceInfo
colorbalance_info
=
{
(
GInterfaceInitFunc
)
&
GstQtGLVideoSinkBase
::
colorbalance_init
,
NULL
,
NULL
};
g_type_add_interface_static
(
type
,
GST_TYPE_COLOR_BALANCE
,
&
colorbalance_info
);
}
//------------------------------
void
GstQtGLVideoSinkBase
::
base_init
(
gpointer
g_class
)
{
GstElementClass
*
element_class
=
GST_ELEMENT_CLASS
(
g_class
);
element_class
->
padtemplates
=
NULL
;
//get rid of the pad template of the base class
static
GstStaticPadTemplate
sink_pad_template
=
GST_STATIC_PAD_TEMPLATE
(
"sink"
,
GST_PAD_SINK
,
GST_PAD_ALWAYS
,
GST_STATIC_CAPS
(
GST_VIDEO_CAPS_MAKE
(
CAPS_FORMATS
))
);
gst_element_class_add_pad_template
(
element_class
,
gst_static_pad_template_get
(
&
sink_pad_template
));
}
void
GstQtGLVideoSinkBase
::
class_init
(
gpointer
g_class
,
gpointer
class_data
)
{
Q_UNUSED
(
class_data
);
s_parent_class
=
reinterpret_cast
<
GstQtVideoSinkBaseClass
*>
(
g_type_class_peek_parent
(
g_class
));
GObjectClass
*
object_class
=
G_OBJECT_CLASS
(
g_class
);
object_class
->
finalize
=
GstQtGLVideoSinkBase
::
finalize
;
object_class
->
set_property
=
GstQtGLVideoSinkBase
::
set_property
;
object_class
->
get_property
=
GstQtGLVideoSinkBase
::
get_property
;
GstBaseSinkClass
*
base_sink_class
=
GST_BASE_SINK_CLASS
(
g_class
);
base_sink_class
->
start
=
GstQtGLVideoSinkBase
::
start
;
base_sink_class
->
set_caps
=
GstQtGLVideoSinkBase
::
set_caps
;
g_object_class_install_property
(
object_class
,
PROP_CONTRAST
,
g_param_spec_int
(
"contrast"
,
"Contrast"
,
"The contrast of the video"
,
-
100
,
100
,
0
,
static_cast
<
GParamFlags
>
(
G_PARAM_READWRITE
)));
g_object_class_install_property
(
object_class
,
PROP_BRIGHTNESS
,
g_param_spec_int
(
"brightness"
,
"Brightness"
,
"The brightness of the video"
,
-
100
,
100
,
0
,
static_cast
<
GParamFlags
>
(
G_PARAM_READWRITE
)));
g_object_class_install_property
(
object_class
,
PROP_HUE
,
g_param_spec_int
(
"hue"
,
"Hue"
,
"The hue of the video"
,
-
100
,
100
,
0
,
static_cast
<
GParamFlags
>
(
G_PARAM_READWRITE
)));
g_object_class_install_property
(
object_class
,
PROP_SATURATION
,
g_param_spec_int
(
"saturation"
,
"Saturation"
,
"The saturation of the video"
,
-
100
,
100
,
0
,
static_cast
<
GParamFlags
>
(
G_PARAM_READWRITE
)));
}
void
GstQtGLVideoSinkBase
::
init
(
GTypeInstance
*
instance
,
gpointer
g_class
)
{
Q_UNUSED
(
g_class
);
GstQtGLVideoSinkBase
*
self
=
GST_QT_GL_VIDEO_SINK_BASE
(
instance
);
GstColorBalanceChannel
*
channel
;
self
->
m_channels_list
=
NULL
;
for
(
int
i
=
0
;
i
<
LABEL_LAST
;
i
++
)
{
channel
=
GST_COLOR_BALANCE_CHANNEL
(
g_object_new
(
GST_TYPE_COLOR_BALANCE_CHANNEL
,
NULL
));
channel
->
label
=
g_strdup
(
s_colorbalance_labels
[
i
]);
channel
->
min_value
=
-
100
;
channel
->
max_value
=
100
;
self
->
m_channels_list
=
g_list_append
(
self
->
m_channels_list
,
channel
);
}
}
void
GstQtGLVideoSinkBase
::
finalize
(
GObject
*
object
)
{
GstQtGLVideoSinkBase
*
self
=
GST_QT_GL_VIDEO_SINK_BASE
(
object
);
while
(
self
->
m_channels_list
)
{
GstColorBalanceChannel
*
channel
=
GST_COLOR_BALANCE_CHANNEL
(
self
->
m_channels_list
->
data
);
g_object_unref
(
channel
);
self
->
m_channels_list
=
g_list_next
(
self
->
m_channels_list
);
}
g_list_free
(
self
->
m_channels_list
);
G_OBJECT_CLASS
(
s_parent_class
)
->
finalize
(
object
);
}
//------------------------------
void
GstQtGLVideoSinkBase
::
colorbalance_init
(
GstColorBalanceInterface
*
balance_interface
,
gpointer
data
)
{
Q_UNUSED
(
data
);
balance_interface
->
list_channels
=
GstQtGLVideoSinkBase
::
colorbalance_list_channels
;
balance_interface
->
set_value
=
GstQtGLVideoSinkBase
::
colorbalance_set_value
;
balance_interface
->
get_value
=
GstQtGLVideoSinkBase
::
colorbalance_get_value
;
balance_interface
->
get_balance_type
=
GstQtGLVideoSinkBase
::
colorbalance_get_balance_type
;
}
const
GList
*
GstQtGLVideoSinkBase
::
colorbalance_list_channels
(
GstColorBalance
*
balance
)
{
return
GST_QT_GL_VIDEO_SINK_BASE
(
balance
)
->
m_channels_list
;
}
void
GstQtGLVideoSinkBase
::
colorbalance_set_value
(
GstColorBalance
*
balance
,
GstColorBalanceChannel
*
channel
,
gint
value
)
{
GstQtVideoSinkBase
*
sink
=
GST_QT_VIDEO_SINK_BASE
(
balance
);
if
(
!
qstrcmp
(
channel
->
label
,
s_colorbalance_labels
[
LABEL_CONTRAST
]))
{
sink
->
delegate
->
setContrast
(
value
);
}
else
if
(
!
qstrcmp
(
channel
->
label
,
s_colorbalance_labels
[
LABEL_BRIGHTNESS
]))
{
sink
->
delegate
->
setBrightness
(
value
);
}
else
if
(
!
qstrcmp
(
channel
->
label
,
s_colorbalance_labels
[
LABEL_HUE
]))
{
sink
->
delegate
->
setHue
(
value
);
}
else
if
(
!
qstrcmp
(
channel
->
label
,
s_colorbalance_labels
[
LABEL_SATURATION
]))
{
sink
->
delegate
->
setSaturation
(
value
);
}
else
{
GST_WARNING_OBJECT
(
sink
,
"Unknown colorbalance channel %s"
,
channel
->
label
);
}
}
gint
GstQtGLVideoSinkBase
::
colorbalance_get_value
(
GstColorBalance
*
balance
,
GstColorBalanceChannel
*
channel
)
{
GstQtVideoSinkBase
*
sink
=
GST_QT_VIDEO_SINK_BASE
(
balance
);
if
(
!
qstrcmp
(
channel
->
label
,
s_colorbalance_labels
[
LABEL_CONTRAST
]))
{
return
sink
->
delegate
->
contrast
();
}
else
if
(
!
qstrcmp
(
channel
->
label
,
s_colorbalance_labels
[
LABEL_BRIGHTNESS
]))
{
return
sink
->
delegate
->
brightness
();
}
else
if
(
!
qstrcmp
(
channel
->
label
,
s_colorbalance_labels
[
LABEL_HUE
]))
{
return
sink
->
delegate
->
hue
();
}
else
if
(
!
qstrcmp
(
channel
->
label
,
s_colorbalance_labels
[
LABEL_SATURATION
]))
{
return
sink
->
delegate
->
saturation
();
}
else
{
GST_WARNING_OBJECT
(
sink
,
"Unknown colorbalance channel %s"
,
channel
->
label
);
}
return
0
;
}
GstColorBalanceType
GstQtGLVideoSinkBase
::
colorbalance_get_balance_type
(
GstColorBalance
*
balance
)
{
Q_UNUSED
(
balance
);
return
GST_COLOR_BALANCE_HARDWARE
;
}
//------------------------------
void
GstQtGLVideoSinkBase
::
set_property
(
GObject
*
object
,
guint
prop_id
,
const
GValue
*
value
,
GParamSpec
*
pspec
)
{
GstQtVideoSinkBase
*
sink
=
GST_QT_VIDEO_SINK_BASE
(
object
);
switch
(
prop_id
)
{
case
PROP_CONTRAST
:
sink
->
delegate
->
setContrast
(
g_value_get_int
(
value
));
break
;
case
PROP_BRIGHTNESS
:
sink
->
delegate
->
setBrightness
(
g_value_get_int
(
value
));
break
;
case
PROP_HUE
:
sink
->
delegate
->
setHue
(
g_value_get_int
(
value
));
break
;
case
PROP_SATURATION
:
sink
->
delegate
->
setSaturation
(
g_value_get_int
(
value
));
break
;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID
(
object
,
prop_id
,
pspec
);
break
;
}
}
void
GstQtGLVideoSinkBase
::
get_property
(
GObject
*
object
,
guint
prop_id
,
GValue
*
value
,
GParamSpec
*
pspec
)
{
GstQtVideoSinkBase
*
sink
=
GST_QT_VIDEO_SINK_BASE
(
object
);
switch
(
prop_id
)
{
case
PROP_CONTRAST
:
g_value_set_int
(
value
,
sink
->
delegate
->
contrast
());
break
;
case
PROP_BRIGHTNESS
:
g_value_set_int
(
value
,
sink
->
delegate
->
brightness
());
break
;
case
PROP_HUE
:
g_value_set_int
(
value
,
sink
->
delegate
->
hue
());
break
;
case
PROP_SATURATION
:
g_value_set_int
(
value
,
sink
->
delegate
->
saturation
());
break
;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID
(
object
,
prop_id
,
pspec
);
break
;
}
}
//------------------------------
gboolean
GstQtGLVideoSinkBase
::
start
(
GstBaseSink
*
base
)
{
GstQtVideoSinkBase
*
sink
=
GST_QT_VIDEO_SINK_BASE
(
base
);
//fail on purpose if the user hasn't set a context
if
(
sink
->
delegate
->
supportedPainterTypes
()
==
QtVideoSinkDelegate
::
Generic
)
{
GST_WARNING_OBJECT
(
sink
,
"Neither GLSL nor ARB Fragment Program are supported "
"for painting. Did you forget to set a gl context?"
);
return
FALSE
;
}
else
{
return
TRUE
;
}
}
gboolean
GstQtGLVideoSinkBase
::
set_caps
(
GstBaseSink
*
base
,
GstCaps
*
caps
)
{
GstQtVideoSinkBase
*
sink
=
GST_QT_VIDEO_SINK_BASE
(
base
);
GST_LOG_OBJECT
(
sink
,
"new caps %"
GST_PTR_FORMAT
,
caps
);
BufferFormat
format
=
BufferFormat
::
fromCaps
(
caps
);
if
(
OpenGLSurfacePainter
::
supportedPixelFormats
().
contains
(
format
.
videoFormat
()))
{
QCoreApplication
::
postEvent
(
sink
->
delegate
,
new
BaseDelegate
::
BufferFormatEvent
(
format
));
return
TRUE
;
}
else
{
return
FALSE
;
}
}
src/VideoStreaming/gstqtvideosink/gstqtglvideosinkbase.h
0 → 100644
View file @
4b4f758b
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011-2012 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#ifndef GST_QT_GL_VIDEO_SINK_BASE_H
#define GST_QT_GL_VIDEO_SINK_BASE_H
#include "gstqtvideosinkbase.h"
#include <gst/video/colorbalance.h>
#ifndef GST_QT_VIDEO_SINK_NO_OPENGL
#define GST_TYPE_QT_GL_VIDEO_SINK_BASE \
(GstQtGLVideoSinkBase::get_type())
#define GST_QT_GL_VIDEO_SINK_BASE(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_QT_GL_VIDEO_SINK_BASE, GstQtGLVideoSinkBase))
struct
GstQtGLVideoSinkBase
{
public:
GstQtVideoSinkBase
parent
;
static
GType
get_type
();
private:
enum
{
PROP_0
,
PROP_CONTRAST
,
PROP_BRIGHTNESS
,
PROP_HUE
,
PROP_SATURATION
};
//index for s_colorbalance_labels
enum
{
LABEL_CONTRAST
=
0
,
LABEL_BRIGHTNESS
,
LABEL_HUE
,
LABEL_SATURATION
,
LABEL_LAST
};
static
void
init_interfaces
(
GType
type
);
static
void
base_init
(
gpointer
g_class
);
static
void
class_init
(
gpointer
g_class
,
gpointer
class_data
);
static
void
init
(
GTypeInstance
*
instance
,
gpointer
g_class
);
static
void
finalize
(
GObject
*
object
);
static
void
colorbalance_init
(
GstColorBalanceInterface
*
balance_interface
,
gpointer
data
);
static
const
GList
*
colorbalance_list_channels
(
GstColorBalance
*
balance
);
static
void
colorbalance_set_value
(
GstColorBalance
*
balance
,
GstColorBalanceChannel
*
channel
,
gint
value
);
static
gint
colorbalance_get_value
(
GstColorBalance
*
balance
,
GstColorBalanceChannel
*
channel
);
static
GstColorBalanceType
colorbalance_get_balance_type
(
GstColorBalance
*
balance
);
static
void
set_property
(
GObject
*
object
,
guint
prop_id
,
const
GValue
*
value
,
GParamSpec
*
pspec
);
static
void
get_property
(
GObject
*
object
,
guint
prop_id
,
GValue
*
value
,
GParamSpec
*
pspec
);
static
gboolean
start
(
GstBaseSink
*
sink
);
static
gboolean
set_caps
(
GstBaseSink
*
sink
,
GstCaps
*
caps
);
GList
*
m_channels_list
;
static
const
char
*
const
s_colorbalance_labels
[];
static
GstQtVideoSinkBaseClass
*
s_parent_class
;
};
struct
GstQtGLVideoSinkBaseClass
{
GstQtVideoSinkBaseClass
parent_class
;
};
#endif // GST_QT_VIDEO_SINK_NO_OPENGL
#endif // GST_QT_GL_VIDEO_SINK_BASE_H
src/VideoStreaming/gstqtvideosink/gstqtquick2videosink.cpp
0 → 100644
View file @
4b4f758b
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011-2013 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#include "gstqtquick2videosink.h"
#include "gstqtvideosinkplugin.h"
#include "gstqtvideosinkmarshal.h"
#include "delegates/qtquick2videosinkdelegate.h"
#include <gst/video/colorbalance.h>
#include <cstring>
#include <QCoreApplication>
#define CAPS_FORMATS "{ BGRA, BGRx, ARGB, xRGB, RGB, RGB16, BGR, v308, AYUV, YV12, I420 }"
#define GST_QT_QUICK2_VIDEO_SINK_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_QT_QUICK2_VIDEO_SINK, GstQtQuick2VideoSinkPrivate))
struct
_GstQtQuick2VideoSinkPrivate
{
QtQuick2VideoSinkDelegate
*
delegate
;
GList
*
channels_list
;
};
static
void
gst_qt_quick2_video_sink_colorbalance_init
(
GstColorBalanceInterface
*
iface
,
gpointer
data
);
#define parent_class gst_qt_quick2_video_sink_parent_class
G_DEFINE_TYPE_WITH_CODE
(
GstQtQuick2VideoSink
,
gst_qt_quick2_video_sink
,
GST_TYPE_VIDEO_SINK
,
G_IMPLEMENT_INTERFACE
(
GST_TYPE_COLOR_BALANCE
,
gst_qt_quick2_video_sink_colorbalance_init
));
enum
{
PROP_0
,
PROP_PIXEL_ASPECT_RATIO
,
PROP_FORCE_ASPECT_RATIO
,
PROP_CONTRAST
,
PROP_BRIGHTNESS
,
PROP_HUE
,
PROP_SATURATION
,
};
enum
{
ACTION_UPDATE_NODE
,
SIGNAL_UPDATE
,
LAST_SIGNAL
};
static
guint
s_signals
[
LAST_SIGNAL
]
=
{
0
};
const
char
*
const
s_colorbalance_labels
[]
=
{
"contrast"
,
"brightness"
,
"hue"
,
"saturation"
};
//index for s_colorbalance_labels
enum
{
LABEL_CONTRAST
=
0
,
LABEL_BRIGHTNESS
,
LABEL_HUE
,
LABEL_SATURATION
,
LABEL_LAST
};
static
void
gst_qt_quick2_video_sink_init
(
GstQtQuick2VideoSink
*
self
)
{
self
->
priv
=
GST_QT_QUICK2_VIDEO_SINK_GET_PRIVATE
(
self
);
// delegate
self
->
priv
->
delegate
=
new
QtQuick2VideoSinkDelegate
(
GST_ELEMENT
(
self
));
// colorbalance
GstColorBalanceChannel
*
channel
;
self
->
priv
->
channels_list
=
NULL
;
for
(
int
i
=
0
;
i
<
LABEL_LAST
;
i
++
)
{
channel
=
GST_COLOR_BALANCE_CHANNEL
(
g_object_new
(
GST_TYPE_COLOR_BALANCE_CHANNEL
,
NULL
));
channel
->
label
=
g_strdup
(
s_colorbalance_labels
[
i
]);
channel
->
min_value
=
-
100
;
channel
->
max_value
=
100
;
self
->
priv
->
channels_list
=
g_list_append
(
self
->
priv
->
channels_list
,
channel
);
}
}
static
void
gst_qt_quick2_video_sink_finalize
(
GObject
*
gobject
)
{
GstQtQuick2VideoSink
*
self
=
GST_QT_QUICK2_VIDEO_SINK
(
gobject
);
delete
self
->
priv
->
delegate
;
self
->
priv
->
delegate
=
0
;
while
(
self
->
priv
->
channels_list
)
{
GstColorBalanceChannel
*
channel
=
GST_COLOR_BALANCE_CHANNEL
(
self
->
priv
->
channels_list
->
data
);
g_object_unref
(
channel
);
self
->
priv
->
channels_list
=
g_list_next
(
self
->
priv
->
channels_list
);
}
g_list_free
(
self
->
priv
->
channels_list
);
G_OBJECT_CLASS
(
parent_class
)
->
finalize
(
gobject
);
}
static
void
gst_qt_quick2_video_sink_set_property
(
GObject
*
object
,
guint
property_id
,
const
GValue
*
value
,
GParamSpec
*
pspec
)
{
GstQtQuick2VideoSink
*
self
=
GST_QT_QUICK2_VIDEO_SINK
(
object
);
switch
(
property_id
)
{
case
PROP_PIXEL_ASPECT_RATIO
:
{
GValue
tmp
;
std
::
memset
(
&
tmp
,
0
,
sizeof
(
GValue
));
g_value_init
(
&
tmp
,
GST_TYPE_FRACTION
);
if
(
g_value_transform
(
value
,
&
tmp
))
{
int
n
=
gst_value_get_fraction_numerator
(
&
tmp
);
int
d
=
gst_value_get_fraction_denominator
(
&
tmp
);
self
->
priv
->
delegate
->
setPixelAspectRatio
(
Fraction
(
n
,
d
));
}
else
{
GST_WARNING_OBJECT
(
object
,
"Could not transform string to aspect ratio"
);
}
g_value_unset
(
&
tmp
);
break
;
}
case
PROP_FORCE_ASPECT_RATIO
:
self
->
priv
->
delegate
->
setForceAspectRatio
(
g_value_get_boolean
(
value
));
break
;
case
PROP_CONTRAST
:
self
->
priv
->
delegate
->
setContrast
(
g_value_get_int
(
value
));
break
;
case
PROP_BRIGHTNESS
:
self
->
priv
->
delegate
->
setBrightness
(
g_value_get_int
(
value
));
break
;
case
PROP_HUE
:
self
->
priv
->
delegate
->
setHue
(
g_value_get_int
(
value
));
break
;
case
PROP_SATURATION
:
self
->
priv
->
delegate
->
setSaturation
(
g_value_get_int
(
value
));
break
;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID
(
object
,
property_id
,
pspec
);
break
;
}
}
static
void
gst_qt_quick2_video_sink_get_property
(
GObject
*
object
,
guint
property_id
,
GValue
*
value
,
GParamSpec
*
pspec
)
{
GstQtQuick2VideoSink
*
self
=
GST_QT_QUICK2_VIDEO_SINK
(
object
);
switch
(
property_id
)
{
case
PROP_PIXEL_ASPECT_RATIO
:
{
GValue
tmp
;
Fraction
par
=
self
->
priv
->
delegate
->
pixelAspectRatio
();
std
::
memset
(
&
tmp
,
0
,
sizeof
(
GValue
));
g_value_init
(
&
tmp
,
GST_TYPE_FRACTION
);
gst_value_set_fraction
(
&
tmp
,
par
.
numerator
,
par
.
denominator
);
g_value_transform
(
&
tmp
,
value
);
g_value_unset
(
&
tmp
);
break
;
}
case
PROP_FORCE_ASPECT_RATIO
:
g_value_set_boolean
(
value
,
self
->
priv
->
delegate
->
forceAspectRatio
());
break
;
case
PROP_CONTRAST
:
g_value_set_int
(
value
,
self
->
priv
->
delegate
->
contrast
());
break
;
case
PROP_BRIGHTNESS
:
g_value_set_int
(
value
,
self
->
priv
->
delegate
->
brightness
());
break
;
case
PROP_HUE
:
g_value_set_int
(
value
,
self
->
priv
->
delegate
->
hue
());
break
;
case
PROP_SATURATION
:
g_value_set_int
(
value
,
self
->
priv
->
delegate
->
saturation
());
break
;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID
(
object
,
property_id
,
pspec
);
break
;
}
}
static
GstStateChangeReturn
gst_qt_quick2_video_sink_change_state
(
GstElement
*
element
,
GstStateChange
transition
)
{
GstQtQuick2VideoSink
*
self
=
GST_QT_QUICK2_VIDEO_SINK
(
element
);
switch
(
transition
)
{
case
GST_STATE_CHANGE_READY_TO_PAUSED
:
self
->
priv
->
delegate
->
setActive
(
true
);
break
;
case
GST_STATE_CHANGE_PAUSED_TO_READY
:
self
->
priv
->
delegate
->
setActive
(
false
);
break
;
default:
break
;
}
return
GST_ELEMENT_CLASS
(
parent_class
)
->
change_state
(
element
,
transition
);
}
static
gboolean
gst_qt_quick2_video_sink_set_caps
(
GstBaseSink
*
sink
,
GstCaps
*
caps
)
{
GstQtQuick2VideoSink
*
self
=
GST_QT_QUICK2_VIDEO_SINK
(
sink
);
GST_LOG_OBJECT
(
self
,
"new caps %"
GST_PTR_FORMAT
,
caps
);
BufferFormat
format
=
BufferFormat
::
fromCaps
(
caps
);
//too lazy to do proper checks. if the format is not UNKNOWN, then
//it should conform to the template caps formats, unless gstreamer
//core has a bug.
if
(
format
.
videoFormat
()
!=
GST_VIDEO_FORMAT_UNKNOWN
)
{
QCoreApplication
::
postEvent
(
self
->
priv
->
delegate
,
new
BaseDelegate
::
BufferFormatEvent
(
format
));
return
TRUE
;
}
else
{
return
FALSE
;
}
}
static
GstFlowReturn
gst_qt_quick2_video_sink_show_frame
(
GstVideoSink
*
sink
,
GstBuffer
*
buffer
)
{
GstQtQuick2VideoSink
*
self
=
GST_QT_QUICK2_VIDEO_SINK
(
sink
);
GST_TRACE_OBJECT
(
self
,
"Posting new buffer (%"
GST_PTR_FORMAT
") for rendering."
,
buffer
);
QCoreApplication
::
postEvent
(
self
->
priv
->
delegate
,
new
BaseDelegate
::
BufferEvent
(
buffer
));
return
GST_FLOW_OK
;
}
//------------------------------
static
gpointer
gst_qt_quick2_video_sink_update_node
(
GstQtQuick2VideoSink
*
self
,
gpointer
node
,
qreal
x
,
qreal
y
,
qreal
w
,
qreal
h
)
{
return
self
->
priv
->
delegate
->
updateNode
(
static_cast
<
QSGNode
*>
(
node
),
QRectF
(
x
,
y
,
w
,
h
));
}
//------------------------------
static
const
GList
*
gst_qt_quick2_video_sink_colorbalance_list_channels
(
GstColorBalance
*
balance
)
{
return
GST_QT_QUICK2_VIDEO_SINK
(
balance
)
->
priv
->
channels_list
;
}
static
void
gst_qt_quick2_video_sink_colorbalance_set_value
(
GstColorBalance
*
balance
,
GstColorBalanceChannel
*
channel
,
gint
value
)
{
GstQtQuick2VideoSink
*
self
=
GST_QT_QUICK2_VIDEO_SINK
(
balance
);
if
(
!
qstrcmp
(
channel
->
label
,
s_colorbalance_labels
[
LABEL_CONTRAST
]))
{
self
->
priv
->
delegate
->
setContrast
(
value
);
}
else
if
(
!
qstrcmp
(
channel
->
label
,
s_colorbalance_labels
[
LABEL_BRIGHTNESS
]))
{
self
->
priv
->
delegate
->
setBrightness
(
value
);
}
else
if
(
!
qstrcmp
(
channel
->
label
,
s_colorbalance_labels
[
LABEL_HUE
]))
{
self
->
priv
->
delegate
->
setHue
(
value
);
}
else
if
(
!
qstrcmp
(
channel
->
label
,
s_colorbalance_labels
[
LABEL_SATURATION
]))
{
self
->
priv
->
delegate
->
setSaturation
(
value
);
}
else
{
GST_WARNING_OBJECT
(
self
,
"Unknown colorbalance channel %s"
,
channel
->
label
);
}
}
static
gint
gst_qt_quick2_video_sink_colorbalance_get_value
(
GstColorBalance
*
balance
,
GstColorBalanceChannel
*
channel
)
{
GstQtQuick2VideoSink
*
self
=
GST_QT_QUICK2_VIDEO_SINK
(
balance
);
if
(
!
qstrcmp
(
channel
->
label
,
s_colorbalance_labels
[
LABEL_CONTRAST
]))
{
return
self
->
priv
->
delegate
->
contrast
();
}
else
if
(
!
qstrcmp
(
channel
->
label
,
s_colorbalance_labels
[
LABEL_BRIGHTNESS
]))
{
return
self
->
priv
->
delegate
->
brightness
();
}
else
if
(
!
qstrcmp
(
channel
->
label
,
s_colorbalance_labels
[
LABEL_HUE
]))
{
return
self
->
priv
->
delegate
->
hue
();
}
else
if
(
!
qstrcmp
(
channel
->
label
,
s_colorbalance_labels
[
LABEL_SATURATION
]))
{
return
self
->
priv
->
delegate
->
saturation
();
}
else
{
GST_WARNING_OBJECT
(
self
,
"Unknown colorbalance channel %s"
,
channel
->
label
);
}
return
0
;
}
static
GstColorBalanceType
gst_qt_quick2_video_sink_colorbalance_get_balance_type
(
GstColorBalance
*
balance
)
{
Q_UNUSED
(
balance
);
return
GST_COLOR_BALANCE_HARDWARE
;
}
static
void
gst_qt_quick2_video_sink_colorbalance_init
(
GstColorBalanceInterface
*
iface
,
gpointer
data
)
{
Q_UNUSED
(
data
);
iface
->
list_channels
=
gst_qt_quick2_video_sink_colorbalance_list_channels
;
iface
->
set_value
=
gst_qt_quick2_video_sink_colorbalance_set_value
;
iface
->
get_value
=
gst_qt_quick2_video_sink_colorbalance_get_value
;
iface
->
get_balance_type
=
gst_qt_quick2_video_sink_colorbalance_get_balance_type
;
}
//------------------------------
static
void
gst_qt_quick2_video_sink_class_init
(
GstQtQuick2VideoSinkClass
*
klass
)
{
GObjectClass
*
gobject_class
=
G_OBJECT_CLASS
(
klass
);
gobject_class
->
finalize
=
gst_qt_quick2_video_sink_finalize
;
gobject_class
->
set_property
=
gst_qt_quick2_video_sink_set_property
;
gobject_class
->
get_property
=
gst_qt_quick2_video_sink_get_property
;
GstElementClass
*
element_class
=
GST_ELEMENT_CLASS
(
klass
);
element_class
->
change_state
=
gst_qt_quick2_video_sink_change_state
;
GstBaseSinkClass
*
base_sink_class
=
GST_BASE_SINK_CLASS
(
klass
);
base_sink_class
->
set_caps
=
gst_qt_quick2_video_sink_set_caps
;
GstVideoSinkClass
*
video_sink_class
=
GST_VIDEO_SINK_CLASS
(
klass
);
video_sink_class
->
show_frame
=
gst_qt_quick2_video_sink_show_frame
;
GstQtQuick2VideoSinkClass
*
qtquick2_class
=
GST_QT_QUICK2_VIDEO_SINK_CLASS
(
klass
);
qtquick2_class
->
update_node
=
gst_qt_quick2_video_sink_update_node
;
/**
* GstQtQuick2VideoSink::pixel-aspect-ratio
*
* The pixel aspect ratio of the display device.
**/
g_object_class_install_property
(
gobject_class
,
PROP_PIXEL_ASPECT_RATIO
,
g_param_spec_string
(
"pixel-aspect-ratio"
,
"Pixel aspect ratio"
,
"The pixel aspect ratio of the display device"
,
"1/1"
,
static_cast
<
GParamFlags
>
(
G_PARAM_READWRITE
)));
/**
* GstQtQuick2VideoSink::force-aspect-ratio
*
* If set to TRUE, the sink will scale the video respecting its original aspect ratio
* and any remaining space will be filled with black.
* If set to FALSE, the sink will scale the video to fit the whole drawing area.
**/
g_object_class_install_property
(
gobject_class
,
PROP_FORCE_ASPECT_RATIO
,
g_param_spec_boolean
(
"force-aspect-ratio"
,
"Force aspect ratio"
,
"When enabled, scaling will respect original aspect ratio"
,
FALSE
,
static_cast
<
GParamFlags
>
(
G_PARAM_READWRITE
)));
g_object_class_install_property
(
gobject_class
,
PROP_CONTRAST
,
g_param_spec_int
(
"contrast"
,
"Contrast"
,
"The contrast of the video"
,
-
100
,
100
,
0
,
static_cast
<
GParamFlags
>
(
G_PARAM_READWRITE
)));
g_object_class_install_property
(
gobject_class
,
PROP_BRIGHTNESS
,
g_param_spec_int
(
"brightness"
,
"Brightness"
,
"The brightness of the video"
,
-
100
,
100
,
0
,
static_cast
<
GParamFlags
>
(
G_PARAM_READWRITE
)));
g_object_class_install_property
(
gobject_class
,
PROP_HUE
,
g_param_spec_int
(
"hue"
,
"Hue"
,
"The hue of the video"
,
-
100
,
100
,
0
,
static_cast
<
GParamFlags
>
(
G_PARAM_READWRITE
)));
g_object_class_install_property
(
gobject_class
,
PROP_SATURATION
,
g_param_spec_int
(
"saturation"
,
"Saturation"
,
"The saturation of the video"
,
-
100
,
100
,
0
,
static_cast
<
GParamFlags
>
(
G_PARAM_READWRITE
)));
/**
* GstQtQuick2VideoSink::update-node
* @node: The QSGNode to update
* @x: The x coordinate of the target area rectangle
* @y: The y coordinate of the target area rectangle
* @width: The width of the target area rectangle
* @height: The height of the target area rectangle
* @returns: The updated QGSNode
*
* This is an action signal that you can call from your QQuickItem subclass
* inside its updateNode function to render the video. It takes a QSGNode*
* and the item's area rectangle as arguments. You should schedule to call
* this function to repaint the surface whenever the ::update signal is
* emited.
*
* Note that the x,y,width and height arguments are actually qreal.
* This means that on architectures like arm they will be float instead
* of double. You should cast the arguments to qreal if they are not
* already when emitting this signal.
*/
s_signals
[
ACTION_UPDATE_NODE
]
=
g_signal_new
(
"update-node"
,
G_TYPE_FROM_CLASS
(
klass
),
static_cast
<
GSignalFlags
>
(
G_SIGNAL_RUN_LAST
|
G_SIGNAL_ACTION
),
G_STRUCT_OFFSET
(
GstQtQuick2VideoSinkClass
,
update_node
),
NULL
,
NULL
,
qRealIsDouble
()
?
g_cclosure_user_marshal_POINTER__POINTER_DOUBLE_DOUBLE_DOUBLE_DOUBLE
:
g_cclosure_user_marshal_POINTER__POINTER_FLOAT_FLOAT_FLOAT_FLOAT
,
G_TYPE_POINTER
,
5
,
G_TYPE_POINTER
,
G_TYPE_QREAL
,
G_TYPE_QREAL
,
G_TYPE_QREAL
,
G_TYPE_QREAL
);
/**
* GstQtQuick2VideoSink::update
*
* This signal is emited when the surface should be repainted. It should
* be connected to QQuickItem::update().
*/
s_signals
[
SIGNAL_UPDATE
]
=
g_signal_new
(
"update"
,
G_TYPE_FROM_CLASS
(
klass
),
G_SIGNAL_RUN_LAST
,
0
,
NULL
,
NULL
,
g_cclosure_marshal_VOID__VOID
,
G_TYPE_NONE
,
0
);
g_type_class_add_private
(
klass
,
sizeof
(
GstQtQuick2VideoSinkPrivate
));
static
GstStaticPadTemplate
sink_pad_template
=
GST_STATIC_PAD_TEMPLATE
(
"sink"
,
GST_PAD_SINK
,
GST_PAD_ALWAYS
,
GST_STATIC_CAPS
(
GST_VIDEO_CAPS_MAKE
(
CAPS_FORMATS
))
);
gst_element_class_add_pad_template
(
element_class
,
gst_static_pad_template_get
(
&
sink_pad_template
));
gst_element_class_set_details_simple
(
element_class
,
"QtQuick2 video sink"
,
"Sink/Video"
,
"A video sink that can draw on a QQuickItem"
,
"George Kiagiadakis <george.kiagiadakis@collabora.com>"
);
}
src/VideoStreaming/gstqtvideosink/gstqtquick2videosink.h
0 → 100644
View file @
4b4f758b
/*
Copyright (C) 2013 Collabora Ltd.
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#ifndef __GST_QT_QUICK2_VIDEO_SINK_H__
#define __GST_QT_QUICK2_VIDEO_SINK_H__
#include <gst/video/gstvideosink.h>
#include <QtGlobal>
#define GST_TYPE_QT_QUICK2_VIDEO_SINK \
(gst_qt_quick2_video_sink_get_type ())
#define GST_QT_QUICK2_VIDEO_SINK(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_QT_QUICK2_VIDEO_SINK, GstQtQuick2VideoSink))
#define GST_IS_QT_QUICK2_VIDEO_SINK(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_QT_QUICK2_VIDEO_SINK))
#define GST_QT_QUICK2_VIDEO_SINK_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_QT_QUICK2_VIDEO_SINK, GstQtQuick2VideoSinkClass))
#define GST_IS_QT_QUICK2_VIDEO_SINK_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_QT_QUICK2_VIDEO_SINK))
#define GST_QT_QUICK2_VIDEO_SINK_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_QT_QUICK2_VIDEO_SINK, GstQtQuick2VideoSinkClass))
typedef
struct
_GstQtQuick2VideoSink
GstQtQuick2VideoSink
;
typedef
struct
_GstQtQuick2VideoSinkClass
GstQtQuick2VideoSinkClass
;
typedef
struct
_GstQtQuick2VideoSinkPrivate
GstQtQuick2VideoSinkPrivate
;
struct
_GstQtQuick2VideoSink
{
GstVideoSink
parent_instance
;
GstQtQuick2VideoSinkPrivate
*
priv
;
};
struct
_GstQtQuick2VideoSinkClass
{
GstVideoSinkClass
parent_class
;
gpointer
(
*
update_node
)(
GstQtQuick2VideoSink
*
self
,
gpointer
node
,
qreal
x
,
qreal
y
,
qreal
w
,
qreal
h
);
};
GType
gst_qt_quick2_video_sink_get_type
(
void
);
#endif
/* __GST_QT_QUICK2_VIDEO_SINK_H__ */
src/VideoStreaming/gstqtvideosink/gstqtvideosink.cpp
0 → 100644
View file @
4b4f758b
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011-2012 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#include "gstqtvideosink.h"
#include "gstqtvideosinkmarshal.h"
#include "delegates/qtvideosinkdelegate.h"
guint
GstQtVideoSink
::
s_signals
[];
DEFINE_TYPE
(
GstQtVideoSink
,
GST_TYPE_QT_VIDEO_SINK_BASE
)
//------------------------------
void
GstQtVideoSink
::
emit_update
(
gpointer
sink
)
{
g_signal_emit
(
sink
,
GstQtVideoSink
::
s_signals
[
UPDATE_SIGNAL
],
0
,
NULL
);
}
//------------------------------
void
GstQtVideoSink
::
base_init
(
gpointer
g_class
)
{
GstElementClass
*
element_class
=
GST_ELEMENT_CLASS
(
g_class
);
gst_element_class_set_details_simple
(
element_class
,
"Qt video sink"
,
"Sink/Video"
,
"A video sink that can draw on any Qt surface"
,
"George Kiagiadakis <george.kiagiadakis@collabora.com>"
);
}
void
GstQtVideoSink
::
class_init
(
gpointer
g_class
,
gpointer
class_data
)
{
Q_UNUSED
(
class_data
);
GstQtVideoSinkClass
*
qt_video_sink_class
=
reinterpret_cast
<
GstQtVideoSinkClass
*>
(
g_class
);
qt_video_sink_class
->
paint
=
GstQtVideoSink
::
paint
;
/**
* GstQtVideoSink::paint
* @painter: A valid QPainter pointer that will be used to paint the video
* @x: The x coordinate of the target area rectangle
* @y: The y coordinate of the target area rectangle
* @width: The width of the target area rectangle
* @height: The height of the target area rectangle
*
* This is an action signal that you can call from your Qt surface class inside
* its paint function to render the video. It takes a QPainter* and the target
* area rectangle as arguments. You should schedule to call this function to
* repaint the surface whenever the ::update signal is emited.
*
* Note that the x,y,width and height arguments are actually qreal. This means
* that on architectures like arm they will be float instead of double. You should
* cast the arguments to qreal if they are not already when emitting this signal.
*/
s_signals
[
PAINT_SIGNAL
]
=
g_signal_new
(
"paint"
,
G_TYPE_FROM_CLASS
(
g_class
),
static_cast
<
GSignalFlags
>
(
G_SIGNAL_RUN_LAST
|
G_SIGNAL_ACTION
),
G_STRUCT_OFFSET
(
GstQtVideoSinkClass
,
paint
),
NULL
,
NULL
,
qRealIsDouble
()
?
g_cclosure_user_marshal_VOID__POINTER_DOUBLE_DOUBLE_DOUBLE_DOUBLE
:
g_cclosure_user_marshal_VOID__POINTER_FLOAT_FLOAT_FLOAT_FLOAT
,
G_TYPE_NONE
,
5
,
G_TYPE_POINTER
,
G_TYPE_QREAL
,
G_TYPE_QREAL
,
G_TYPE_QREAL
,
G_TYPE_QREAL
);
/**
* GstQtVideoSink::update
*
* This signal is emited when the surface should be repainted. It should
* be connected to QWidget::update() or QGraphicsItem::update() or any
* other similar function in your surface.
*/
s_signals
[
UPDATE_SIGNAL
]
=
g_signal_new
(
"update"
,
G_TYPE_FROM_CLASS
(
g_class
),
G_SIGNAL_RUN_LAST
,
0
,
NULL
,
NULL
,
g_cclosure_marshal_VOID__VOID
,
G_TYPE_NONE
,
0
);
}
void
GstQtVideoSink
::
init
(
GTypeInstance
*
instance
,
gpointer
g_class
)
{
Q_UNUSED
(
g_class
);
GstQtVideoSinkBase
*
sinkBase
=
GST_QT_VIDEO_SINK_BASE
(
instance
);
sinkBase
->
delegate
=
new
QtVideoSinkDelegate
(
GST_ELEMENT
(
sinkBase
));
}
//------------------------------
void
GstQtVideoSink
::
paint
(
GstQtVideoSink
*
sink
,
gpointer
painter
,
qreal
x
,
qreal
y
,
qreal
width
,
qreal
height
)
{
GST_QT_VIDEO_SINK_BASE
(
sink
)
->
delegate
->
paint
(
static_cast
<
QPainter
*>
(
painter
),
QRectF
(
x
,
y
,
width
,
height
));
}
src/VideoStreaming/gstqtvideosink/gstqtvideosink.h
0 → 100644
View file @
4b4f758b
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011-2012 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#ifndef GST_QT_VIDEO_SINK_H
#define GST_QT_VIDEO_SINK_H
#include "gstqtvideosinkbase.h"
#define GST_TYPE_QT_VIDEO_SINK \
(GstQtVideoSink::get_type())
struct
GstQtVideoSink
{
public:
GstQtVideoSinkBase
parent
;
static
GType
get_type
();
static
void
emit_update
(
gpointer
sink
);
private:
enum
{
PAINT_SIGNAL
,
UPDATE_SIGNAL
,
LAST_SIGNAL
};
static
void
base_init
(
gpointer
g_class
);
static
void
class_init
(
gpointer
g_class
,
gpointer
class_data
);
static
void
init
(
GTypeInstance
*
instance
,
gpointer
g_class
);
static
void
paint
(
GstQtVideoSink
*
sink
,
gpointer
painter
,
qreal
x
,
qreal
y
,
qreal
width
,
qreal
height
);
static
guint
s_signals
[
LAST_SIGNAL
];
};
struct
GstQtVideoSinkClass
{
GstQtVideoSinkBaseClass
parent_class
;
/* paint action signal */
void
(
*
paint
)
(
GstQtVideoSink
*
sink
,
gpointer
painter
,
qreal
x
,
qreal
y
,
qreal
width
,
qreal
height
);
};
#endif
src/VideoStreaming/gstqtvideosink/gstqtvideosinkbase.cpp
0 → 100644
View file @
4b4f758b
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011-2012 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#include "gstqtvideosinkbase.h"
#include "delegates/qtvideosinkdelegate.h"
#include "painters/genericsurfacepainter.h"
#include <cstring>
#include <QCoreApplication>
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
# define CAPS_FORMATS "{ ARGB, xRGB, RGB, RGB16 }"
#else
# define CAPS_FORMATS "{ BGRA, BGRx, RGB, RGB16 }"
#endif
GstVideoSinkClass
*
GstQtVideoSinkBase
::
s_parent_class
=
NULL
;
DEFINE_TYPE
(
GstQtVideoSinkBase
,
GST_TYPE_VIDEO_SINK
)
//------------------------------
void
GstQtVideoSinkBase
::
base_init
(
gpointer
g_class
)
{
GstElementClass
*
element_class
=
GST_ELEMENT_CLASS
(
g_class
);
static
GstStaticPadTemplate
sink_pad_template
=
GST_STATIC_PAD_TEMPLATE
(
"sink"
,
GST_PAD_SINK
,
GST_PAD_ALWAYS
,
GST_STATIC_CAPS
(
GST_VIDEO_CAPS_MAKE
(
CAPS_FORMATS
))
);
gst_element_class_add_pad_template
(
element_class
,
gst_static_pad_template_get
(
&
sink_pad_template
));
}
void
GstQtVideoSinkBase
::
class_init
(
gpointer
g_class
,
gpointer
class_data
)
{
Q_UNUSED
(
class_data
);
s_parent_class
=
reinterpret_cast
<
GstVideoSinkClass
*>
(
g_type_class_peek_parent
(
g_class
));
GObjectClass
*
object_class
=
G_OBJECT_CLASS
(
g_class
);
object_class
->
finalize
=
GstQtVideoSinkBase
::
finalize
;
object_class
->
set_property
=
GstQtVideoSinkBase
::
set_property
;
object_class
->
get_property
=
GstQtVideoSinkBase
::
get_property
;
GstElementClass
*
element_class
=
GST_ELEMENT_CLASS
(
g_class
);
element_class
->
change_state
=
GstQtVideoSinkBase
::
change_state
;
GstBaseSinkClass
*
base_sink_class
=
GST_BASE_SINK_CLASS
(
g_class
);
base_sink_class
->
set_caps
=
GstQtVideoSinkBase
::
set_caps
;
GstVideoSinkClass
*
video_sink_class
=
GST_VIDEO_SINK_CLASS
(
g_class
);
video_sink_class
->
show_frame
=
GstQtVideoSinkBase
::
show_frame
;
/**
* GstQtVideoSinkBase::pixel-aspect-ratio
*
* The pixel aspect ratio of the display device.
**/
g_object_class_install_property
(
object_class
,
PROP_PIXEL_ASPECT_RATIO
,
g_param_spec_string
(
"pixel-aspect-ratio"
,
"Pixel aspect ratio"
,
"The pixel aspect ratio of the display device"
,
"1/1"
,
static_cast
<
GParamFlags
>
(
G_PARAM_READWRITE
)));
/**
* GstQtVideoSinkBase::force-aspect-ratio
*
* If set to TRUE, the sink will scale the video respecting its original aspect ratio
* and any remaining space will be filled with black.
* If set to FALSE, the sink will scale the video to fit the whole drawing area.
**/
g_object_class_install_property
(
object_class
,
PROP_FORCE_ASPECT_RATIO
,
g_param_spec_boolean
(
"force-aspect-ratio"
,
"Force aspect ratio"
,
"When enabled, scaling will respect original aspect ratio"
,
FALSE
,
static_cast
<
GParamFlags
>
(
G_PARAM_READWRITE
)));
}
void
GstQtVideoSinkBase
::
init
(
GTypeInstance
*
instance
,
gpointer
g_class
)
{
Q_UNUSED
(
instance
);
Q_UNUSED
(
g_class
);
/* sink->delegate is initialized in the subclasses */
}
void
GstQtVideoSinkBase
::
finalize
(
GObject
*
object
)
{
GstQtVideoSinkBase
*
sink
=
GST_QT_VIDEO_SINK_BASE
(
object
);
delete
sink
->
delegate
;
sink
->
delegate
=
0
;
}
//------------------------------
void
GstQtVideoSinkBase
::
set_property
(
GObject
*
object
,
guint
prop_id
,
const
GValue
*
value
,
GParamSpec
*
pspec
)
{
GstQtVideoSinkBase
*
sink
=
GST_QT_VIDEO_SINK_BASE
(
object
);
switch
(
prop_id
)
{
case
PROP_PIXEL_ASPECT_RATIO
:
{
GValue
tmp
;
std
::
memset
(
&
tmp
,
0
,
sizeof
(
GValue
));
g_value_init
(
&
tmp
,
GST_TYPE_FRACTION
);
if
(
g_value_transform
(
value
,
&
tmp
))
{
int
n
=
gst_value_get_fraction_numerator
(
&
tmp
);
int
d
=
gst_value_get_fraction_denominator
(
&
tmp
);
sink
->
delegate
->
setPixelAspectRatio
(
Fraction
(
n
,
d
));
}
else
{
GST_WARNING_OBJECT
(
object
,
"Could not transform string to aspect ratio"
);
}
g_value_unset
(
&
tmp
);
break
;
}
case
PROP_FORCE_ASPECT_RATIO
:
sink
->
delegate
->
setForceAspectRatio
(
g_value_get_boolean
(
value
));
break
;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID
(
object
,
prop_id
,
pspec
);
break
;
}
}
void
GstQtVideoSinkBase
::
get_property
(
GObject
*
object
,
guint
prop_id
,
GValue
*
value
,
GParamSpec
*
pspec
)
{
GstQtVideoSinkBase
*
sink
=
GST_QT_VIDEO_SINK_BASE
(
object
);
switch
(
prop_id
)
{
case
PROP_PIXEL_ASPECT_RATIO
:
{
GValue
tmp
;
Fraction
par
=
sink
->
delegate
->
pixelAspectRatio
();
std
::
memset
(
&
tmp
,
0
,
sizeof
(
GValue
));
g_value_init
(
&
tmp
,
GST_TYPE_FRACTION
);
gst_value_set_fraction
(
&
tmp
,
par
.
numerator
,
par
.
denominator
);
g_value_transform
(
&
tmp
,
value
);
g_value_unset
(
&
tmp
);
break
;
}
case
PROP_FORCE_ASPECT_RATIO
:
g_value_set_boolean
(
value
,
sink
->
delegate
->
forceAspectRatio
());
break
;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID
(
object
,
prop_id
,
pspec
);
break
;
}
}
//------------------------------
GstStateChangeReturn
GstQtVideoSinkBase
::
change_state
(
GstElement
*
element
,
GstStateChange
transition
)
{
GstQtVideoSinkBase
*
sink
=
GST_QT_VIDEO_SINK_BASE
(
element
);
switch
(
transition
)
{
case
GST_STATE_CHANGE_READY_TO_PAUSED
:
sink
->
delegate
->
setActive
(
true
);
break
;
case
GST_STATE_CHANGE_PAUSED_TO_READY
:
sink
->
delegate
->
setActive
(
false
);
break
;
default:
break
;
}
return
GST_ELEMENT_CLASS
(
s_parent_class
)
->
change_state
(
element
,
transition
);
}
//------------------------------
gboolean
GstQtVideoSinkBase
::
set_caps
(
GstBaseSink
*
base
,
GstCaps
*
caps
)
{
GstQtVideoSinkBase
*
sink
=
GST_QT_VIDEO_SINK_BASE
(
base
);
GST_LOG_OBJECT
(
sink
,
"new caps %"
GST_PTR_FORMAT
,
caps
);
BufferFormat
format
=
BufferFormat
::
fromCaps
(
caps
);
if
(
GenericSurfacePainter
::
supportedPixelFormats
().
contains
(
format
.
videoFormat
()))
{
QCoreApplication
::
postEvent
(
sink
->
delegate
,
new
BaseDelegate
::
BufferFormatEvent
(
format
));
return
TRUE
;
}
else
{
return
FALSE
;
}
}
//------------------------------
GstFlowReturn
GstQtVideoSinkBase
::
show_frame
(
GstVideoSink
*
video_sink
,
GstBuffer
*
buffer
)
{
GstQtVideoSinkBase
*
sink
=
GST_QT_VIDEO_SINK_BASE
(
video_sink
);
GST_TRACE_OBJECT
(
sink
,
"Posting new buffer (%"
GST_PTR_FORMAT
") for rendering."
,
buffer
);
QCoreApplication
::
postEvent
(
sink
->
delegate
,
new
BaseDelegate
::
BufferEvent
(
buffer
));
return
GST_FLOW_OK
;
}
src/VideoStreaming/gstqtvideosink/gstqtvideosinkbase.h
0 → 100644
View file @
4b4f758b
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011-2012 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#ifndef GST_QT_VIDEO_SINK_BASE_H
#define GST_QT_VIDEO_SINK_BASE_H
#include "gstqtvideosinkplugin.h"
#include <gst/video/gstvideosink.h>
#define GST_TYPE_QT_VIDEO_SINK_BASE \
(GstQtVideoSinkBase::get_type())
#define GST_QT_VIDEO_SINK_BASE(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_QT_VIDEO_SINK_BASE, GstQtVideoSinkBase))
#define GST_QT_VIDEO_SINK_BASE_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_QT_VIDEO_SINK_BASE, GstQtVideoSinkBaseClass))
#define GST_QT_VIDEO_SINK_BASE_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_QT_VIDEO_SINK_BASE, GstQtVideoSinkBaseClass))
class
QtVideoSinkDelegate
;
struct
GstQtVideoSinkBase
{
public:
GstVideoSink
parent
;
static
GType
get_type
();
private:
enum
{
PROP_0
,
PROP_PIXEL_ASPECT_RATIO
,
PROP_FORCE_ASPECT_RATIO
,
};
static
void
base_init
(
gpointer
g_class
);
static
void
class_init
(
gpointer
g_class
,
gpointer
class_data
);
static
void
init
(
GTypeInstance
*
instance
,
gpointer
g_class
);
static
void
finalize
(
GObject
*
object
);
static
void
set_property
(
GObject
*
object
,
guint
prop_id
,
const
GValue
*
value
,
GParamSpec
*
pspec
);
static
void
get_property
(
GObject
*
object
,
guint
prop_id
,
GValue
*
value
,
GParamSpec
*
pspec
);
static
GstStateChangeReturn
change_state
(
GstElement
*
element
,
GstStateChange
transition
);
static
gboolean
set_caps
(
GstBaseSink
*
sink
,
GstCaps
*
caps
);
static
GstFlowReturn
show_frame
(
GstVideoSink
*
sink
,
GstBuffer
*
buffer
);
public:
QtVideoSinkDelegate
*
delegate
;
private:
static
GstVideoSinkClass
*
s_parent_class
;
};
struct
GstQtVideoSinkBaseClass
{
GstVideoSinkClass
parent_class
;
};
#endif
src/VideoStreaming/gstqtvideosink/gstqtvideosinkmarshal.c
0 → 100644
View file @
4b4f758b
#include <glib-object.h>
#ifdef G_ENABLE_DEBUG
#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v)
#define g_marshal_value_peek_char(v) g_value_get_schar (v)
#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v)
#define g_marshal_value_peek_int(v) g_value_get_int (v)
#define g_marshal_value_peek_uint(v) g_value_get_uint (v)
#define g_marshal_value_peek_long(v) g_value_get_long (v)
#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v)
#define g_marshal_value_peek_int64(v) g_value_get_int64 (v)
#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v)
#define g_marshal_value_peek_enum(v) g_value_get_enum (v)
#define g_marshal_value_peek_flags(v) g_value_get_flags (v)
#define g_marshal_value_peek_float(v) g_value_get_float (v)
#define g_marshal_value_peek_double(v) g_value_get_double (v)
#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v)
#define g_marshal_value_peek_param(v) g_value_get_param (v)
#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v)
#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v)
#define g_marshal_value_peek_object(v) g_value_get_object (v)
#define g_marshal_value_peek_variant(v) g_value_get_variant (v)
#else
/* !G_ENABLE_DEBUG */
/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.
* Do not access GValues directly in your code. Instead, use the
* g_value_get_*() functions
*/
#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int
#define g_marshal_value_peek_char(v) (v)->data[0].v_int
#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint
#define g_marshal_value_peek_int(v) (v)->data[0].v_int
#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint
#define g_marshal_value_peek_long(v) (v)->data[0].v_long
#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong
#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64
#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64
#define g_marshal_value_peek_enum(v) (v)->data[0].v_long
#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong
#define g_marshal_value_peek_float(v) (v)->data[0].v_float
#define g_marshal_value_peek_double(v) (v)->data[0].v_double
#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer
#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer
#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer
#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer
#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer
#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer
#endif
/* !G_ENABLE_DEBUG */
/* VOID:POINTER,FLOAT,FLOAT,FLOAT,FLOAT (marshaller.src:1) */
void
g_cclosure_user_marshal_VOID__POINTER_FLOAT_FLOAT_FLOAT_FLOAT
(
GClosure
*
closure
,
GValue
*
return_value
G_GNUC_UNUSED
,
guint
n_param_values
,
const
GValue
*
param_values
,
gpointer
invocation_hint
G_GNUC_UNUSED
,
gpointer
marshal_data
)
{
typedef
void
(
*
GMarshalFunc_VOID__POINTER_FLOAT_FLOAT_FLOAT_FLOAT
)
(
gpointer
data1
,
gpointer
arg_1
,
gfloat
arg_2
,
gfloat
arg_3
,
gfloat
arg_4
,
gfloat
arg_5
,
gpointer
data2
);
register
GMarshalFunc_VOID__POINTER_FLOAT_FLOAT_FLOAT_FLOAT
callback
;
register
GCClosure
*
cc
=
(
GCClosure
*
)
closure
;
register
gpointer
data1
,
data2
;
g_return_if_fail
(
n_param_values
==
6
);
if
(
G_CCLOSURE_SWAP_DATA
(
closure
))
{
data1
=
closure
->
data
;
data2
=
g_value_peek_pointer
(
param_values
+
0
);
}
else
{
data1
=
g_value_peek_pointer
(
param_values
+
0
);
data2
=
closure
->
data
;
}
callback
=
(
GMarshalFunc_VOID__POINTER_FLOAT_FLOAT_FLOAT_FLOAT
)
(
marshal_data
?
marshal_data
:
cc
->
callback
);
callback
(
data1
,
g_marshal_value_peek_pointer
(
param_values
+
1
),
g_marshal_value_peek_float
(
param_values
+
2
),
g_marshal_value_peek_float
(
param_values
+
3
),
g_marshal_value_peek_float
(
param_values
+
4
),
g_marshal_value_peek_float
(
param_values
+
5
),
data2
);
}
/* VOID:POINTER,DOUBLE,DOUBLE,DOUBLE,DOUBLE (marshaller.src:2) */
void
g_cclosure_user_marshal_VOID__POINTER_DOUBLE_DOUBLE_DOUBLE_DOUBLE
(
GClosure
*
closure
,
GValue
*
return_value
G_GNUC_UNUSED
,
guint
n_param_values
,
const
GValue
*
param_values
,
gpointer
invocation_hint
G_GNUC_UNUSED
,
gpointer
marshal_data
)
{
typedef
void
(
*
GMarshalFunc_VOID__POINTER_DOUBLE_DOUBLE_DOUBLE_DOUBLE
)
(
gpointer
data1
,
gpointer
arg_1
,
gdouble
arg_2
,
gdouble
arg_3
,
gdouble
arg_4
,
gdouble
arg_5
,
gpointer
data2
);
register
GMarshalFunc_VOID__POINTER_DOUBLE_DOUBLE_DOUBLE_DOUBLE
callback
;
register
GCClosure
*
cc
=
(
GCClosure
*
)
closure
;
register
gpointer
data1
,
data2
;
g_return_if_fail
(
n_param_values
==
6
);
if
(
G_CCLOSURE_SWAP_DATA
(
closure
))
{
data1
=
closure
->
data
;
data2
=
g_value_peek_pointer
(
param_values
+
0
);
}
else
{
data1
=
g_value_peek_pointer
(
param_values
+
0
);
data2
=
closure
->
data
;
}
callback
=
(
GMarshalFunc_VOID__POINTER_DOUBLE_DOUBLE_DOUBLE_DOUBLE
)
(
marshal_data
?
marshal_data
:
cc
->
callback
);
callback
(
data1
,
g_marshal_value_peek_pointer
(
param_values
+
1
),
g_marshal_value_peek_double
(
param_values
+
2
),
g_marshal_value_peek_double
(
param_values
+
3
),
g_marshal_value_peek_double
(
param_values
+
4
),
g_marshal_value_peek_double
(
param_values
+
5
),
data2
);
}
/* POINTER:POINTER,FLOAT,FLOAT,FLOAT,FLOAT (marshaller.src:3) */
void
g_cclosure_user_marshal_POINTER__POINTER_FLOAT_FLOAT_FLOAT_FLOAT
(
GClosure
*
closure
,
GValue
*
return_value
G_GNUC_UNUSED
,
guint
n_param_values
,
const
GValue
*
param_values
,
gpointer
invocation_hint
G_GNUC_UNUSED
,
gpointer
marshal_data
)
{
typedef
gpointer
(
*
GMarshalFunc_POINTER__POINTER_FLOAT_FLOAT_FLOAT_FLOAT
)
(
gpointer
data1
,
gpointer
arg_1
,
gfloat
arg_2
,
gfloat
arg_3
,
gfloat
arg_4
,
gfloat
arg_5
,
gpointer
data2
);
register
GMarshalFunc_POINTER__POINTER_FLOAT_FLOAT_FLOAT_FLOAT
callback
;
register
GCClosure
*
cc
=
(
GCClosure
*
)
closure
;
register
gpointer
data1
,
data2
;
gpointer
v_return
;
g_return_if_fail
(
return_value
!=
NULL
);
g_return_if_fail
(
n_param_values
==
6
);
if
(
G_CCLOSURE_SWAP_DATA
(
closure
))
{
data1
=
closure
->
data
;
data2
=
g_value_peek_pointer
(
param_values
+
0
);
}
else
{
data1
=
g_value_peek_pointer
(
param_values
+
0
);
data2
=
closure
->
data
;
}
callback
=
(
GMarshalFunc_POINTER__POINTER_FLOAT_FLOAT_FLOAT_FLOAT
)
(
marshal_data
?
marshal_data
:
cc
->
callback
);
v_return
=
callback
(
data1
,
g_marshal_value_peek_pointer
(
param_values
+
1
),
g_marshal_value_peek_float
(
param_values
+
2
),
g_marshal_value_peek_float
(
param_values
+
3
),
g_marshal_value_peek_float
(
param_values
+
4
),
g_marshal_value_peek_float
(
param_values
+
5
),
data2
);
g_value_set_pointer
(
return_value
,
v_return
);
}
/* POINTER:POINTER,DOUBLE,DOUBLE,DOUBLE,DOUBLE (marshaller.src:4) */
void
g_cclosure_user_marshal_POINTER__POINTER_DOUBLE_DOUBLE_DOUBLE_DOUBLE
(
GClosure
*
closure
,
GValue
*
return_value
G_GNUC_UNUSED
,
guint
n_param_values
,
const
GValue
*
param_values
,
gpointer
invocation_hint
G_GNUC_UNUSED
,
gpointer
marshal_data
)
{
typedef
gpointer
(
*
GMarshalFunc_POINTER__POINTER_DOUBLE_DOUBLE_DOUBLE_DOUBLE
)
(
gpointer
data1
,
gpointer
arg_1
,
gdouble
arg_2
,
gdouble
arg_3
,
gdouble
arg_4
,
gdouble
arg_5
,
gpointer
data2
);
register
GMarshalFunc_POINTER__POINTER_DOUBLE_DOUBLE_DOUBLE_DOUBLE
callback
;
register
GCClosure
*
cc
=
(
GCClosure
*
)
closure
;
register
gpointer
data1
,
data2
;
gpointer
v_return
;
g_return_if_fail
(
return_value
!=
NULL
);
g_return_if_fail
(
n_param_values
==
6
);
if
(
G_CCLOSURE_SWAP_DATA
(
closure
))
{
data1
=
closure
->
data
;
data2
=
g_value_peek_pointer
(
param_values
+
0
);
}
else
{
data1
=
g_value_peek_pointer
(
param_values
+
0
);
data2
=
closure
->
data
;
}
callback
=
(
GMarshalFunc_POINTER__POINTER_DOUBLE_DOUBLE_DOUBLE_DOUBLE
)
(
marshal_data
?
marshal_data
:
cc
->
callback
);
v_return
=
callback
(
data1
,
g_marshal_value_peek_pointer
(
param_values
+
1
),
g_marshal_value_peek_double
(
param_values
+
2
),
g_marshal_value_peek_double
(
param_values
+
3
),
g_marshal_value_peek_double
(
param_values
+
4
),
g_marshal_value_peek_double
(
param_values
+
5
),
data2
);
g_value_set_pointer
(
return_value
,
v_return
);
}
src/VideoStreaming/gstqtvideosink/gstqtvideosinkmarshal.h
0 → 100644
View file @
4b4f758b
#ifndef __g_cclosure_user_marshal_MARSHAL_H__
#define __g_cclosure_user_marshal_MARSHAL_H__
#include <glib-object.h>
G_BEGIN_DECLS
/* VOID:POINTER,FLOAT,FLOAT,FLOAT,FLOAT (marshaller.src:1) */
extern
void
g_cclosure_user_marshal_VOID__POINTER_FLOAT_FLOAT_FLOAT_FLOAT
(
GClosure
*
closure
,
GValue
*
return_value
,
guint
n_param_values
,
const
GValue
*
param_values
,
gpointer
invocation_hint
,
gpointer
marshal_data
);
/* VOID:POINTER,DOUBLE,DOUBLE,DOUBLE,DOUBLE (marshaller.src:2) */
extern
void
g_cclosure_user_marshal_VOID__POINTER_DOUBLE_DOUBLE_DOUBLE_DOUBLE
(
GClosure
*
closure
,
GValue
*
return_value
,
guint
n_param_values
,
const
GValue
*
param_values
,
gpointer
invocation_hint
,
gpointer
marshal_data
);
/* POINTER:POINTER,FLOAT,FLOAT,FLOAT,FLOAT (marshaller.src:3) */
extern
void
g_cclosure_user_marshal_POINTER__POINTER_FLOAT_FLOAT_FLOAT_FLOAT
(
GClosure
*
closure
,
GValue
*
return_value
,
guint
n_param_values
,
const
GValue
*
param_values
,
gpointer
invocation_hint
,
gpointer
marshal_data
);
/* POINTER:POINTER,DOUBLE,DOUBLE,DOUBLE,DOUBLE (marshaller.src:4) */
extern
void
g_cclosure_user_marshal_POINTER__POINTER_DOUBLE_DOUBLE_DOUBLE_DOUBLE
(
GClosure
*
closure
,
GValue
*
return_value
,
guint
n_param_values
,
const
GValue
*
param_values
,
gpointer
invocation_hint
,
gpointer
marshal_data
);
G_END_DECLS
#endif
/* __g_cclosure_user_marshal_MARSHAL_H__ */
src/VideoStreaming/gstqtvideosink/gstqtvideosinkplugin.cpp
0 → 100644
View file @
4b4f758b
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#include "gstqtvideosinkplugin.h"
#include "gstqtvideosink.h"
#include "gstqtglvideosink.h"
#include "gstqwidgetvideosink.h"
#define PACKAGE "mini-qt-gstreamer"
#define PACKAGE_NAME "QgcQtGStreamer"
#define PACKAGE_ORIGIN "http://gstreamer.freedesktop.org/"
#define PACKAGE_VERSION "1.2.0"
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
# include "gstqtquick2videosink.h"
#endif
GST_DEBUG_CATEGORY
(
gst_qt5gstvideosink_debug
);
/* entry point to initialize the plug-in */
static
gboolean
plugin_init
(
GstPlugin
*
plugin
)
{
GST_DEBUG_CATEGORY_INIT
(
gst_qt5gstvideosink_debug
,
G_STRINGIFY
(
QTVIDEOSINK_NAME
),
0
,
"Debug category for GstQtVideoSink"
);
if
(
!
gst_element_register
(
plugin
,
G_STRINGIFY
(
QTVIDEOSINK_NAME
),
GST_RANK_NONE
,
GST_TYPE_QT_VIDEO_SINK
))
{
GST_ERROR
(
"Failed to register "
G_STRINGIFY
(
QTVIDEOSINK_NAME
));
return
FALSE
;
}
#ifndef GST_QT_VIDEO_SINK_NO_OPENGL
if
(
!
gst_element_register
(
plugin
,
G_STRINGIFY
(
QTGLVIDEOSINK_NAME
),
GST_RANK_NONE
,
GST_TYPE_QT_GL_VIDEO_SINK
))
{
GST_ERROR
(
"Failed to register "
G_STRINGIFY
(
QTGLVIDEOSINK_NAME
));
return
FALSE
;
}
#endif
if
(
!
gst_element_register
(
plugin
,
G_STRINGIFY
(
QWIDGETVIDEOSINK_NAME
),
GST_RANK_NONE
,
GST_TYPE_QWIDGET_VIDEO_SINK
))
{
GST_ERROR
(
"Failed to register "
G_STRINGIFY
(
QWIDGETVIDEOSINK_NAME
));
return
FALSE
;
}
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
if
(
!
gst_element_register
(
plugin
,
"qtquick2videosink"
,
GST_RANK_NONE
,
GST_TYPE_QT_QUICK2_VIDEO_SINK
))
{
GST_ERROR
(
"Failed to register qtquick2videosink"
);
return
FALSE
;
}
#endif
return
TRUE
;
}
GST_PLUGIN_DEFINE
(
GST_VERSION_MAJOR
,
GST_VERSION_MINOR
,
QTVIDEOSINK_NAME
,
"A video sink that can draw on any Qt surface"
,
plugin_init
,
PACKAGE_VERSION
,
"LGPL"
,
PACKAGE_NAME
,
PACKAGE_ORIGIN
)
src/VideoStreaming/gstqtvideosink/gstqtvideosinkplugin.h
0 → 100644
View file @
4b4f758b
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#ifndef GST_QT_VIDEO_SINK_PLUGIN_H
#define GST_QT_VIDEO_SINK_PLUGIN_H
#include <gst/gst.h>
#include <QtGlobal>
GST_DEBUG_CATEGORY_EXTERN
(
gst_qt5gstvideosink_debug
);
#define GST_CAT_DEFAULT gst_qt5gstvideosink_debug
#define DEFINE_TYPE_FULL(cpp_type, type_name, parent_type, additional_initializations) \
GType cpp_type::get_type() \
{ \
static volatile gsize gonce_data = 0; \
if (g_once_init_enter(&gonce_data)) { \
GType type = 0; \
GTypeInfo info; \
info.class_size = sizeof(cpp_type##Class); \
info.base_init = &cpp_type::base_init; \
info.base_finalize = NULL; \
info.class_init = &cpp_type::class_init; \
info.class_finalize = NULL; \
info.class_data = NULL; \
info.instance_size = sizeof(cpp_type); \
info.n_preallocs = 0; \
info.instance_init = &cpp_type::init; \
info.value_table = 0; \
type = g_type_register_static(parent_type, g_intern_static_string(type_name), &info, (GTypeFlags)0); \
additional_initializations(type); \
g_once_init_leave(&gonce_data, (gsize) type); \
} \
return (GType) gonce_data; \
}
// To allow qt4 and qt5 versions of the plugin to be installed at the same time,
// use a different name for their GType, so that the glib type system can handle
// both plugins being loaded by the gstreamer registry
#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
# define DEFINE_TYPE(cpp_type, parent_type) \
DEFINE_TYPE_FULL(cpp_type, #cpp_type "_qt5", parent_type, Q_UNUSED)
# define DEFINE_TYPE_WITH_CODE(cpp_type, parent_type, additional_initializations) \
DEFINE_TYPE_FULL(cpp_type, #cpp_type "_qt5", parent_type, additional_initializations)
#else
# define DEFINE_TYPE(cpp_type, parent_type) \
DEFINE_TYPE_FULL(cpp_type, #cpp_type, parent_type, Q_UNUSED)
# define DEFINE_TYPE_WITH_CODE(cpp_type, parent_type, additional_initializations) \
DEFINE_TYPE_FULL(cpp_type, #cpp_type, parent_type, additional_initializations)
#endif
inline
bool
qRealIsDouble
()
{
return
sizeof
(
qreal
)
==
sizeof
(
double
);
}
#define G_TYPE_QREAL qRealIsDouble() ? G_TYPE_DOUBLE : G_TYPE_FLOAT
#endif
src/VideoStreaming/gstqtvideosink/gstqwidgetvideosink.cpp
0 → 100644
View file @
4b4f758b
/*
Copyright (C) 2010 George Kiagiadakis <kiagiadakis.george@gmail.com>
Copyright (C) 2012 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#include "gstqwidgetvideosink.h"
#include "delegates/qwidgetvideosinkdelegate.h"
DEFINE_TYPE
(
GstQWidgetVideoSink
,
GST_TYPE_QT_VIDEO_SINK_BASE
)
//------------------------------
void
GstQWidgetVideoSink
::
base_init
(
gpointer
gclass
)
{
GstElementClass
*
element_class
=
GST_ELEMENT_CLASS
(
gclass
);
gst_element_class_set_details_simple
(
element_class
,
"QWidget video sink"
,
"Sink/Video"
,
"A video sink that draws on a QWidget using QPainter"
,
"George Kiagiadakis <george.kiagiadakis@collabora.com>"
);
}
void
GstQWidgetVideoSink
::
class_init
(
gpointer
g_class
,
gpointer
class_data
)
{
Q_UNUSED
(
class_data
);
GObjectClass
*
gobject_class
=
G_OBJECT_CLASS
(
g_class
);
gobject_class
->
set_property
=
GstQWidgetVideoSink
::
set_property
;
gobject_class
->
get_property
=
GstQWidgetVideoSink
::
get_property
;
/**
* GstQWidgetVideoSink::widget
*
* This property holds a pointer to the QWidget on which the sink will paint the video.
* You can set this property at any time, even if the element is in PLAYING
* state. You can also set this property to NULL at any time to release
* the widget. In this case, qwidgetvideosink will behave like a fakesink,
* i.e. it will silently drop all the frames that it receives. It is also safe
* to delete the widget that has been set as this property; the sink will be
* signaled and this property will automatically be set to NULL.
**/
g_object_class_install_property
(
gobject_class
,
PROP_WIDGET
,
g_param_spec_pointer
(
"widget"
,
"Widget"
,
"The widget on which this element will paint the video"
,
static_cast
<
GParamFlags
>
(
G_PARAM_READWRITE
)));
}
void
GstQWidgetVideoSink
::
init
(
GTypeInstance
*
instance
,
gpointer
g_class
)
{
Q_UNUSED
(
g_class
);
GstQtVideoSinkBase
*
sinkBase
=
GST_QT_VIDEO_SINK_BASE
(
instance
);
sinkBase
->
delegate
=
new
QWidgetVideoSinkDelegate
(
GST_ELEMENT
(
sinkBase
));
}
void
GstQWidgetVideoSink
::
set_property
(
GObject
*
object
,
guint
prop_id
,
const
GValue
*
value
,
GParamSpec
*
pspec
)
{
GstQtVideoSinkBase
*
sinkBase
=
GST_QT_VIDEO_SINK_BASE
(
object
);
QWidgetVideoSinkDelegate
*
delegate
=
static_cast
<
QWidgetVideoSinkDelegate
*>
(
sinkBase
->
delegate
);
switch
(
prop_id
)
{
case
PROP_WIDGET
:
delegate
->
setWidget
(
static_cast
<
QWidget
*>
(
g_value_get_pointer
(
value
)));
break
;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID
(
object
,
prop_id
,
pspec
);
break
;
}
}
void
GstQWidgetVideoSink
::
get_property
(
GObject
*
object
,
guint
prop_id
,
GValue
*
value
,
GParamSpec
*
pspec
)
{
GstQtVideoSinkBase
*
sinkBase
=
GST_QT_VIDEO_SINK_BASE
(
object
);
QWidgetVideoSinkDelegate
*
delegate
=
static_cast
<
QWidgetVideoSinkDelegate
*>
(
sinkBase
->
delegate
);
switch
(
prop_id
)
{
case
PROP_WIDGET
:
g_value_set_pointer
(
value
,
delegate
->
widget
());
break
;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID
(
object
,
prop_id
,
pspec
);
break
;
}
}
src/VideoStreaming/gstqtvideosink/gstqwidgetvideosink.h
0 → 100644
View file @
4b4f758b
/*
Copyright (C) 2010 George Kiagiadakis <kiagiadakis.george@gmail.com>
Copyright (C) 2012 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#ifndef GST_QWIDGET_VIDEO_SINK_H
#define GST_QWIDGET_VIDEO_SINK_H
#include "gstqtvideosinkbase.h"
#define GST_TYPE_QWIDGET_VIDEO_SINK \
(GstQWidgetVideoSink::get_type())
struct
GstQWidgetVideoSink
{
public:
GstQtVideoSinkBase
parent
;
static
GType
get_type
();
private:
enum
{
PROP_0
,
PROP_WIDGET
};
static
void
base_init
(
gpointer
g_class
);
static
void
class_init
(
gpointer
g_class
,
gpointer
class_data
);
static
void
init
(
GTypeInstance
*
instance
,
gpointer
g_class
);
static
void
set_property
(
GObject
*
object
,
guint
prop_id
,
const
GValue
*
value
,
GParamSpec
*
pspec
);
static
void
get_property
(
GObject
*
object
,
guint
prop_id
,
GValue
*
value
,
GParamSpec
*
pspec
);
};
struct
GstQWidgetVideoSinkClass
{
GstQtVideoSinkBaseClass
parent_class
;
};
#endif
src/VideoStreaming/gstqtvideosink/marshaller.src
0 → 100644
View file @
4b4f758b
VOID:POINTER,FLOAT,FLOAT,FLOAT,FLOAT
VOID:POINTER,DOUBLE,DOUBLE,DOUBLE,DOUBLE
POINTER:POINTER,FLOAT,FLOAT,FLOAT,FLOAT
POINTER:POINTER,DOUBLE,DOUBLE,DOUBLE,DOUBLE
src/VideoStreaming/gstqtvideosink/painters/abstractsurfacepainter.h
0 → 100644
View file @
4b4f758b
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011-2012 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#ifndef ABSTRACTSURFACEPAINTER_H
#define ABSTRACTSURFACEPAINTER_H
#include "../utils/bufferformat.h"
#include <QRectF>
class
QPainter
;
/** Common interface for all the painters */
class
AbstractSurfacePainter
{
public:
virtual
~
AbstractSurfacePainter
()
{}
virtual
bool
supportsFormat
(
GstVideoFormat
format
)
const
=
0
;
virtual
void
init
(
const
BufferFormat
&
format
)
=
0
;
virtual
void
cleanup
()
=
0
;
virtual
void
paint
(
quint8
*
data
,
const
BufferFormat
&
frameFormat
,
QPainter
*
painter
,
const
PaintAreas
&
areas
)
=
0
;
virtual
void
updateColors
(
int
brightness
,
int
contrast
,
int
hue
,
int
saturation
)
=
0
;
};
#endif
src/VideoStreaming/gstqtvideosink/painters/genericsurfacepainter.cpp
0 → 100644
View file @
4b4f758b
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011-2012 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#include "genericsurfacepainter.h"
#include <QPainter>
GenericSurfacePainter
::
GenericSurfacePainter
()
:
m_imageFormat
(
QImage
::
Format_Invalid
)
{
}
//static
QSet
<
GstVideoFormat
>
GenericSurfacePainter
::
supportedPixelFormats
()
{
return
QSet
<
GstVideoFormat
>
()
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
<<
GST_VIDEO_FORMAT_ARGB
<<
GST_VIDEO_FORMAT_xRGB
#else
<<
GST_VIDEO_FORMAT_BGRA
<<
GST_VIDEO_FORMAT_BGRx
#endif
<<
GST_VIDEO_FORMAT_RGB
<<
GST_VIDEO_FORMAT_RGB16
;
}
void
GenericSurfacePainter
::
init
(
const
BufferFormat
&
format
)
{
switch
(
format
.
videoFormat
())
{
// QImage is shitty and reads integers instead of bytes,
// thus it is affected by the host's endianness
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
case
GST_VIDEO_FORMAT_ARGB
:
#else
case
GST_VIDEO_FORMAT_BGRA
:
#endif
m_imageFormat
=
QImage
::
Format_ARGB32
;
break
;
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
case
GST_VIDEO_FORMAT_xRGB
:
#else
case
GST_VIDEO_FORMAT_BGRx
:
#endif
m_imageFormat
=
QImage
::
Format_RGB32
;
break
;
//16-bit RGB formats use host's endianness in GStreamer
//FIXME-0.11 do endianness checks like above if semantics have changed
case
GST_VIDEO_FORMAT_RGB16
:
m_imageFormat
=
QImage
::
Format_RGB16
;
break
;
//This is not affected by endianness
case
GST_VIDEO_FORMAT_RGB
:
m_imageFormat
=
QImage
::
Format_RGB888
;
break
;
default:
throw
QString
(
"Unsupported format"
);
}
}
void
GenericSurfacePainter
::
cleanup
()
{
m_imageFormat
=
QImage
::
Format_Invalid
;
}
void
GenericSurfacePainter
::
paint
(
quint8
*
data
,
const
BufferFormat
&
frameFormat
,
QPainter
*
painter
,
const
PaintAreas
&
areas
)
{
Q_ASSERT
(
m_imageFormat
!=
QImage
::
Format_Invalid
);
QImage
image
(
data
,
frameFormat
.
frameSize
().
width
(),
frameFormat
.
frameSize
().
height
(),
frameFormat
.
bytesPerLine
(),
m_imageFormat
);
QRectF
sourceRect
=
areas
.
sourceRect
;
sourceRect
.
setX
(
sourceRect
.
x
()
*
frameFormat
.
frameSize
().
width
());
sourceRect
.
setY
(
sourceRect
.
y
()
*
frameFormat
.
frameSize
().
height
());
sourceRect
.
setWidth
(
sourceRect
.
width
()
*
frameFormat
.
frameSize
().
width
());
sourceRect
.
setHeight
(
sourceRect
.
height
()
*
frameFormat
.
frameSize
().
height
());
painter
->
fillRect
(
areas
.
blackArea1
,
Qt
::
black
);
painter
->
drawImage
(
areas
.
videoArea
,
image
,
sourceRect
);
painter
->
fillRect
(
areas
.
blackArea2
,
Qt
::
black
);
}
void
GenericSurfacePainter
::
updateColors
(
int
,
int
,
int
,
int
)
{
}
src/VideoStreaming/gstqtvideosink/painters/genericsurfacepainter.h
0 → 100644
View file @
4b4f758b
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#ifndef GENERICSURFACEPAINTER_H
#define GENERICSURFACEPAINTER_H
#include "abstractsurfacepainter.h"
#include <QSet>
#include <QImage>
/**
* Generic painter that paints using the QPainter API.
* No colorspace conversion is done and no colors adjustment either.
*/
class
GenericSurfacePainter
:
public
AbstractSurfacePainter
{
public:
GenericSurfacePainter
();
static
QSet
<
GstVideoFormat
>
supportedPixelFormats
();
virtual
bool
supportsFormat
(
GstVideoFormat
format
)
const
{
return
supportedPixelFormats
().
contains
(
format
);
}
virtual
void
init
(
const
BufferFormat
&
format
);
virtual
void
cleanup
();
virtual
void
paint
(
quint8
*
data
,
const
BufferFormat
&
frameFormat
,
QPainter
*
painter
,
const
PaintAreas
&
areas
);
virtual
void
updateColors
(
int
brightness
,
int
contrast
,
int
hue
,
int
saturation
);
private:
QImage
::
Format
m_imageFormat
;
};
#endif // GENERICSURFACEPAINTER_H
src/VideoStreaming/gstqtvideosink/painters/openglsurfacepainter.cpp
0 → 100644
View file @
4b4f758b
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011-2012 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#include "openglsurfacepainter.h"
#include <QtCore/qmath.h>
#ifndef GL_TEXTURE0
# define GL_TEXTURE0 0x84C0
# define GL_TEXTURE1 0x84C1
# define GL_TEXTURE2 0x84C2
#endif
#ifndef GL_PROGRAM_ERROR_STRING_ARB
# define GL_PROGRAM_ERROR_STRING_ARB 0x8874
#endif
#ifndef GL_UNSIGNED_SHORT_5_6_5
# define GL_UNSIGNED_SHORT_5_6_5 33635
#endif
#ifndef GL_CLAMP_TO_EDGE
# define GL_CLAMP_TO_EDGE 0x812F
#endif
#define QRECT_TO_GLMATRIX(rect) \
{ \
GLfloat(rect.left()) , GLfloat(rect.bottom() + 1), \
GLfloat(rect.right() + 1), GLfloat(rect.bottom() + 1), \
GLfloat(rect.left()) , GLfloat(rect.top()), \
GLfloat(rect.right() + 1), GLfloat(rect.top()) \
}
OpenGLSurfacePainter
::
OpenGLSurfacePainter
()
:
m_textureFormat
(
0
)
,
m_textureInternalFormat
(
0
)
,
m_textureType
(
0
)
,
m_textureCount
(
0
)
,
m_videoColorMatrix
(
GST_VIDEO_COLOR_MATRIX_UNKNOWN
)
{
#ifndef QT_OPENGL_ES
glActiveTexture
=
(
_glActiveTexture
)
QGLContext
::
currentContext
()
->
getProcAddress
(
QLatin1String
(
"glActiveTexture"
));
#endif
}
//static
QSet
<
GstVideoFormat
>
OpenGLSurfacePainter
::
supportedPixelFormats
()
{
return
QSet
<
GstVideoFormat
>
()
//also handled by the generic painter on LE
<<
GST_VIDEO_FORMAT_BGRA
<<
GST_VIDEO_FORMAT_BGRx
//also handled by the generic painter on BE
<<
GST_VIDEO_FORMAT_ARGB
<<
GST_VIDEO_FORMAT_xRGB
//also handled by the generic painter everywhere
<<
GST_VIDEO_FORMAT_RGB
<<
GST_VIDEO_FORMAT_RGB16
//not handled by the generic painter
<<
GST_VIDEO_FORMAT_BGR
<<
GST_VIDEO_FORMAT_v308
<<
GST_VIDEO_FORMAT_AYUV
<<
GST_VIDEO_FORMAT_YV12
<<
GST_VIDEO_FORMAT_I420
;
}
void
OpenGLSurfacePainter
::
updateColors
(
int
brightness
,
int
contrast
,
int
hue
,
int
saturation
)
{
const
qreal
b
=
brightness
/
200.0
;
const
qreal
c
=
contrast
/
100.0
+
1.0
;
const
qreal
h
=
hue
/
100.0
;
const
qreal
s
=
saturation
/
100.0
+
1.0
;
const
qreal
cosH
=
qCos
(
M_PI
*
h
);
const
qreal
sinH
=
qSin
(
M_PI
*
h
);
const
qreal
h11
=
0.787
*
cosH
-
0.213
*
sinH
+
0.213
;
const
qreal
h21
=
-
0.213
*
cosH
+
0.143
*
sinH
+
0.213
;
const
qreal
h31
=
-
0.213
*
cosH
-
0.787
*
sinH
+
0.213
;
const
qreal
h12
=
-
0.715
*
cosH
-
0.715
*
sinH
+
0.715
;
const
qreal
h22
=
0.285
*
cosH
+
0.140
*
sinH
+
0.715
;
const
qreal
h32
=
-
0.715
*
cosH
+
0.715
*
sinH
+
0.715
;
const
qreal
h13
=
-
0.072
*
cosH
+
0.928
*
sinH
+
0.072
;
const
qreal
h23
=
-
0.072
*
cosH
-
0.283
*
sinH
+
0.072
;
const
qreal
h33
=
0.928
*
cosH
+
0.072
*
sinH
+
0.072
;
const
qreal
sr
=
(
1.0
-
s
)
*
0.3086
;
const
qreal
sg
=
(
1.0
-
s
)
*
0.6094
;
const
qreal
sb
=
(
1.0
-
s
)
*
0.0820
;
const
qreal
sr_s
=
sr
+
s
;
const
qreal
sg_s
=
sg
+
s
;
const
qreal
sb_s
=
sr
+
s
;
const
float
m4
=
(
s
+
sr
+
sg
+
sb
)
*
(
0.5
-
0.5
*
c
+
b
);
m_colorMatrix
(
0
,
0
)
=
c
*
(
sr_s
*
h11
+
sg
*
h21
+
sb
*
h31
);
m_colorMatrix
(
0
,
1
)
=
c
*
(
sr_s
*
h12
+
sg
*
h22
+
sb
*
h32
);
m_colorMatrix
(
0
,
2
)
=
c
*
(
sr_s
*
h13
+
sg
*
h23
+
sb
*
h33
);
m_colorMatrix
(
0
,
3
)
=
m4
;
m_colorMatrix
(
1
,
0
)
=
c
*
(
sr
*
h11
+
sg_s
*
h21
+
sb
*
h31
);
m_colorMatrix
(
1
,
1
)
=
c
*
(
sr
*
h12
+
sg_s
*
h22
+
sb
*
h32
);
m_colorMatrix
(
1
,
2
)
=
c
*
(
sr
*
h13
+
sg_s
*
h23
+
sb
*
h33
);
m_colorMatrix
(
1
,
3
)
=
m4
;
m_colorMatrix
(
2
,
0
)
=
c
*
(
sr
*
h11
+
sg
*
h21
+
sb_s
*
h31
);
m_colorMatrix
(
2
,
1
)
=
c
*
(
sr
*
h12
+
sg
*
h22
+
sb_s
*
h32
);
m_colorMatrix
(
2
,
2
)
=
c
*
(
sr
*
h13
+
sg
*
h23
+
sb_s
*
h33
);
m_colorMatrix
(
2
,
3
)
=
m4
;
m_colorMatrix
(
3
,
0
)
=
0.0
;
m_colorMatrix
(
3
,
1
)
=
0.0
;
m_colorMatrix
(
3
,
2
)
=
0.0
;
m_colorMatrix
(
3
,
3
)
=
1.0
;
switch
(
m_videoColorMatrix
)
{
#if 0
//I have no idea what this is - it's not needed currently in this code
case BufferFormat::YCbCr_JPEG:
m_colorMatrix *= QMatrix4x4(
1.0, 0.000, 1.402, -0.701,
1.0, -0.344, -0.714, 0.529,
1.0, 1.772, 0.000, -0.886,
0.0, 0.000, 0.000, 1.0000);
break;
#endif
case
GST_VIDEO_COLOR_MATRIX_BT709
:
/*
* This is bogus (Gus Grubba 20150706)
m_colorMatrix *= QMatrix4x4(
1.164, 0.000, 1.793, -0.5727,
1.164, -0.534, -0.213, 0.3007,
1.164, 2.115, 0.000, -1.1302,
0.0, 0.000, 0.000, 1.0000);
break;
*/
case
GST_VIDEO_COLOR_MATRIX_BT601
:
m_colorMatrix
*=
QMatrix4x4
(
1.164
,
0.000
,
1.596
,
-
0.8708
,
1.164
,
-
0.392
,
-
0.813
,
0.5296
,
1.164
,
2.017
,
0.000
,
-
1.081
,
0.0
,
0.000
,
0.000
,
1.0000
);
break
;
default:
break
;
}
}
void
OpenGLSurfacePainter
::
paint
(
quint8
*
data
,
const
BufferFormat
&
/*frameFormat*/
,
QPainter
*
painter
,
const
PaintAreas
&
areas
)
{
// if these are enabled, we need to reenable them after beginNativePainting()
// has been called, as they may get disabled
bool
stencilTestEnabled
=
glIsEnabled
(
GL_STENCIL_TEST
);
bool
scissorTestEnabled
=
glIsEnabled
(
GL_SCISSOR_TEST
);
painter
->
beginNativePainting
();
if
(
stencilTestEnabled
)
glEnable
(
GL_STENCIL_TEST
);
if
(
scissorTestEnabled
)
glEnable
(
GL_SCISSOR_TEST
);
const
GLfloat
vertexCoordArray
[]
=
QRECT_TO_GLMATRIX
(
areas
.
videoArea
);
const
GLfloat
txLeft
=
areas
.
sourceRect
.
left
();
const
GLfloat
txRight
=
areas
.
sourceRect
.
right
();
const
GLfloat
txTop
=
areas
.
sourceRect
.
top
();
const
GLfloat
txBottom
=
areas
.
sourceRect
.
bottom
();
const
GLfloat
textureCoordArray
[]
=
{
txLeft
,
txBottom
,
txRight
,
txBottom
,
txLeft
,
txTop
,
txRight
,
txTop
};
for
(
int
i
=
0
;
i
<
m_textureCount
;
++
i
)
{
glBindTexture
(
GL_TEXTURE_2D
,
m_textureIds
[
i
]);
glTexImage2D
(
GL_TEXTURE_2D
,
0
,
m_textureInternalFormat
,
m_textureWidths
[
i
],
m_textureHeights
[
i
],
0
,
m_textureFormat
,
m_textureType
,
data
+
m_textureOffsets
[
i
]);
glTexParameterf
(
GL_TEXTURE_2D
,
GL_TEXTURE_MAG_FILTER
,
GL_LINEAR
);
glTexParameterf
(
GL_TEXTURE_2D
,
GL_TEXTURE_MIN_FILTER
,
GL_LINEAR
);
glTexParameterf
(
GL_TEXTURE_2D
,
GL_TEXTURE_WRAP_S
,
GL_CLAMP_TO_EDGE
);
glTexParameterf
(
GL_TEXTURE_2D
,
GL_TEXTURE_WRAP_T
,
GL_CLAMP_TO_EDGE
);
}
paintImpl
(
painter
,
vertexCoordArray
,
textureCoordArray
);
painter
->
endNativePainting
();
painter
->
fillRect
(
areas
.
blackArea1
,
Qt
::
black
);
painter
->
fillRect
(
areas
.
blackArea2
,
Qt
::
black
);
}
void
OpenGLSurfacePainter
::
initRgbTextureInfo
(
GLenum
internalFormat
,
GLuint
format
,
GLenum
type
,
const
QSize
&
size
)
{
#ifndef QT_OPENGL_ES
//make sure we get 8 bits per component, at least on the desktop GL where we can
switch
(
internalFormat
)
{
case
GL_RGBA
:
internalFormat
=
GL_RGBA8
;
break
;
case
GL_RGB
:
internalFormat
=
GL_RGB8
;
break
;
default:
break
;
}
#endif
m_textureInternalFormat
=
internalFormat
;
m_textureFormat
=
format
;
m_textureType
=
type
;
m_textureCount
=
1
;
m_textureWidths
[
0
]
=
size
.
width
();
m_textureHeights
[
0
]
=
size
.
height
();
m_textureOffsets
[
0
]
=
0
;
}
void
OpenGLSurfacePainter
::
initYuv420PTextureInfo
(
const
QSize
&
size
)
{
int
bytesPerLine
=
(
size
.
width
()
+
3
)
&
~
3
;
int
bytesPerLine2
=
(
size
.
width
()
/
2
+
3
)
&
~
3
;
m_textureInternalFormat
=
GL_LUMINANCE
;
m_textureFormat
=
GL_LUMINANCE
;
m_textureType
=
GL_UNSIGNED_BYTE
;
m_textureCount
=
3
;
m_textureWidths
[
0
]
=
bytesPerLine
;
m_textureHeights
[
0
]
=
size
.
height
();
m_textureOffsets
[
0
]
=
0
;
m_textureWidths
[
1
]
=
bytesPerLine2
;
m_textureHeights
[
1
]
=
size
.
height
()
/
2
;
m_textureOffsets
[
1
]
=
bytesPerLine
*
size
.
height
();
m_textureWidths
[
2
]
=
bytesPerLine2
;
m_textureHeights
[
2
]
=
size
.
height
()
/
2
;
m_textureOffsets
[
2
]
=
bytesPerLine
*
size
.
height
()
+
bytesPerLine2
*
size
.
height
()
/
2
;
}
void
OpenGLSurfacePainter
::
initYv12TextureInfo
(
const
QSize
&
size
)
{
int
bytesPerLine
=
(
size
.
width
()
+
3
)
&
~
3
;
int
bytesPerLine2
=
(
size
.
width
()
/
2
+
3
)
&
~
3
;
m_textureInternalFormat
=
GL_LUMINANCE
;
m_textureFormat
=
GL_LUMINANCE
;
m_textureType
=
GL_UNSIGNED_BYTE
;
m_textureCount
=
3
;
m_textureWidths
[
0
]
=
bytesPerLine
;
m_textureHeights
[
0
]
=
size
.
height
();
m_textureOffsets
[
0
]
=
0
;
m_textureWidths
[
1
]
=
bytesPerLine2
;
m_textureHeights
[
1
]
=
size
.
height
()
/
2
;
m_textureOffsets
[
1
]
=
bytesPerLine
*
size
.
height
()
+
bytesPerLine2
*
size
.
height
()
/
2
;
m_textureWidths
[
2
]
=
bytesPerLine2
;
m_textureHeights
[
2
]
=
size
.
height
()
/
2
;
m_textureOffsets
[
2
]
=
bytesPerLine
*
size
.
height
();
}
#ifndef QT_OPENGL_ES
# ifndef GL_FRAGMENT_PROGRAM_ARB
# define GL_FRAGMENT_PROGRAM_ARB 0x8804
# define GL_PROGRAM_FORMAT_ASCII_ARB 0x8875
# endif
// Interprets the RGBA texture as in fact being BGRx and paints it.
static
const
char
*
qt_arbfp_bgrxShaderProgram
=
"!!ARBfp1.0
\n
"
"PARAM matrix[4] = { program.local[0..2],"
"{ 0.0, 0.0, 0.0, 1.0 } };
\n
"
"TEMP bgrx;
\n
"
"TEX bgrx.xyz, fragment.texcoord[0], texture[0], 2D;
\n
"
"MOV bgrx.w, matrix[3].w;
\n
"
"DP4 result.color.x, bgrx.zyxw, matrix[0];
\n
"
"DP4 result.color.y, bgrx.zyxw, matrix[1];
\n
"
"DP4 result.color.z, bgrx.zyxw, matrix[2];
\n
"
"END"
;
// Interprets the RGBA texture as in fact being BGRA and paints it.
static
const
char
*
qt_arbfp_bgraShaderProgram
=
"!!ARBfp1.0
\n
"
"PARAM matrix[4] = { program.local[0..2],"
"{ 0.0, 0.0, 0.0, 1.0 } };
\n
"
"TEMP bgra;
\n
"
"TEX bgra, fragment.texcoord[0], texture[0], 2D;
\n
"
"MOV bgra.w, matrix[3].w;
\n
"
"DP4 result.color.x, bgra.zyxw, matrix[0];
\n
"
"DP4 result.color.y, bgra.zyxw, matrix[1];
\n
"
"DP4 result.color.z, bgra.zyxw, matrix[2];
\n
"
"TEX result.color.w, fragment.texcoord[0], texture, 2D;
\n
"
"END"
;
// Interprets the RGBA texture as in fact being xRGB and paints it.
static
const
char
*
qt_arbfp_xrgbShaderProgram
=
"!!ARBfp1.0
\n
"
"PARAM matrix[4] = { program.local[0..2],"
"{ 0.0, 0.0, 0.0, 1.0 } };
\n
"
"TEMP xrgb;
\n
"
"TEX xrgb, fragment.texcoord[0], texture[0], 2D;
\n
"
"MOV xrgb.x, matrix[3].w;
\n
"
"DP4 result.color.x, xrgb.yzwx, matrix[0];
\n
"
"DP4 result.color.y, xrgb.yzwx, matrix[1];
\n
"
"DP4 result.color.z, xrgb.yzwx, matrix[2];
\n
"
"END"
;
// Interprets the RGBA texture as in fact being ARGB and paints it.
static
const
char
*
qt_arbfp_argbShaderProgram
=
"!!ARBfp1.0
\n
"
"PARAM matrix[4] = { program.local[0..2],"
"{ 0.0, 0.0, 0.0, 1.0 } };
\n
"
"TEMP argb;
\n
"
"TEX argb, fragment.texcoord[0], texture[0], 2D;
\n
"
"MOV argb.x, matrix[3].w;
\n
"
"DP4 result.color.x, argb.yzwx, matrix[0];
\n
"
"DP4 result.color.y, argb.yzwx, matrix[1];
\n
"
"DP4 result.color.z, argb.yzwx, matrix[2];
\n
"
"TEX result.color.w, fragment.texcoord[0], texture, 2D;
\n
"
"END"
;
// Paints RGB frames without doing any color channel flipping.
static
const
char
*
qt_arbfp_rgbxShaderProgram
=
"!!ARBfp1.0
\n
"
"PARAM matrix[4] = { program.local[0..2],"
"{ 0.0, 0.0, 0.0, 1.0 } };
\n
"
"TEMP rgb;
\n
"
"TEX rgb.xyz, fragment.texcoord[0], texture[0], 2D;
\n
"
"MOV rgb.w, matrix[3].w;
\n
"
"DP4 result.color.x, rgb, matrix[0];
\n
"
"DP4 result.color.y, rgb, matrix[1];
\n
"
"DP4 result.color.z, rgb, matrix[2];
\n
"
"END"
;
// Paints a YUV420P or YV12 frame.
static
const
char
*
qt_arbfp_yuvPlanarShaderProgram
=
"!!ARBfp1.0
\n
"
"PARAM matrix[4] = { program.local[0..2],"
"{ 0.0, 0.0, 0.0, 1.0 } };
\n
"
"TEMP yuv;
\n
"
"TEX yuv.x, fragment.texcoord[0], texture[0], 2D;
\n
"
"TEX yuv.y, fragment.texcoord[0], texture[1], 2D;
\n
"
"TEX yuv.z, fragment.texcoord[0], texture[2], 2D;
\n
"
"MOV yuv.w, matrix[3].w;
\n
"
"DP4 result.color.x, yuv, matrix[0];
\n
"
"DP4 result.color.y, yuv, matrix[1];
\n
"
"DP4 result.color.z, yuv, matrix[2];
\n
"
"END"
;
ArbFpSurfacePainter
::
ArbFpSurfacePainter
()
:
OpenGLSurfacePainter
()
,
m_programId
(
0
)
{
const
QGLContext
*
context
=
QGLContext
::
currentContext
();
glProgramStringARB
=
(
_glProgramStringARB
)
context
->
getProcAddress
(
QLatin1String
(
"glProgramStringARB"
));
glBindProgramARB
=
(
_glBindProgramARB
)
context
->
getProcAddress
(
QLatin1String
(
"glBindProgramARB"
));
glDeleteProgramsARB
=
(
_glDeleteProgramsARB
)
context
->
getProcAddress
(
QLatin1String
(
"glDeleteProgramsARB"
));
glGenProgramsARB
=
(
_glGenProgramsARB
)
context
->
getProcAddress
(
QLatin1String
(
"glGenProgramsARB"
));
glProgramLocalParameter4fARB
=
(
_glProgramLocalParameter4fARB
)
context
->
getProcAddress
(
QLatin1String
(
"glProgramLocalParameter4fARB"
));
}
void
ArbFpSurfacePainter
::
init
(
const
BufferFormat
&
format
)
{
Q_ASSERT
(
m_textureCount
==
0
);
const
char
*
program
=
0
;
switch
(
format
.
videoFormat
())
{
case
GST_VIDEO_FORMAT_BGRx
:
initRgbTextureInfo
(
GL_RGBA
,
GL_RGBA
,
GL_UNSIGNED_BYTE
,
format
.
frameSize
());
program
=
qt_arbfp_bgrxShaderProgram
;
break
;
case
GST_VIDEO_FORMAT_xRGB
:
initRgbTextureInfo
(
GL_RGBA
,
GL_RGBA
,
GL_UNSIGNED_BYTE
,
format
.
frameSize
());
program
=
qt_arbfp_xrgbShaderProgram
;
break
;
case
GST_VIDEO_FORMAT_BGRA
:
initRgbTextureInfo
(
GL_RGBA
,
GL_RGBA
,
GL_UNSIGNED_BYTE
,
format
.
frameSize
());
program
=
qt_arbfp_bgraShaderProgram
;
break
;
case
GST_VIDEO_FORMAT_ARGB
:
initRgbTextureInfo
(
GL_RGBA
,
GL_RGBA
,
GL_UNSIGNED_BYTE
,
format
.
frameSize
());
program
=
qt_arbfp_argbShaderProgram
;
break
;
case
GST_VIDEO_FORMAT_RGB
:
initRgbTextureInfo
(
GL_RGB
,
GL_RGB
,
GL_UNSIGNED_BYTE
,
format
.
frameSize
());
program
=
qt_arbfp_rgbxShaderProgram
;
break
;
case
GST_VIDEO_FORMAT_BGR
:
initRgbTextureInfo
(
GL_RGB
,
GL_RGB
,
GL_UNSIGNED_BYTE
,
format
.
frameSize
());
program
=
qt_arbfp_bgrxShaderProgram
;
break
;
//NOTE: unlike the other formats, this is endianness-dependent,
//but using GL_UNSIGNED_SHORT_5_6_5 ensures that it's handled correctly
case
GST_VIDEO_FORMAT_RGB16
:
initRgbTextureInfo
(
GL_RGB
,
GL_RGB
,
GL_UNSIGNED_SHORT_5_6_5
,
format
.
frameSize
());
program
=
qt_arbfp_rgbxShaderProgram
;
break
;
case
GST_VIDEO_FORMAT_v308
:
initRgbTextureInfo
(
GL_RGB
,
GL_RGB
,
GL_UNSIGNED_BYTE
,
format
.
frameSize
());
program
=
qt_arbfp_rgbxShaderProgram
;
break
;
case
GST_VIDEO_FORMAT_AYUV
:
initRgbTextureInfo
(
GL_RGBA
,
GL_RGBA
,
GL_UNSIGNED_BYTE
,
format
.
frameSize
());
program
=
qt_arbfp_argbShaderProgram
;
break
;
case
GST_VIDEO_FORMAT_YV12
:
initYv12TextureInfo
(
format
.
frameSize
());
program
=
qt_arbfp_yuvPlanarShaderProgram
;
break
;
case
GST_VIDEO_FORMAT_I420
:
initYuv420PTextureInfo
(
format
.
frameSize
());
program
=
qt_arbfp_yuvPlanarShaderProgram
;
break
;
default:
Q_ASSERT
(
false
);
break
;
}
m_videoColorMatrix
=
format
.
colorMatrix
();
glGenProgramsARB
(
1
,
&
m_programId
);
GLenum
glError
=
glGetError
();
if
(
glError
!=
GL_NO_ERROR
)
{
throw
QString
(
"ARBfb Shader allocation error "
)
+
QString
::
number
(
static_cast
<
int
>
(
glError
),
16
);
}
else
{
glBindProgramARB
(
GL_FRAGMENT_PROGRAM_ARB
,
m_programId
);
glProgramStringARB
(
GL_FRAGMENT_PROGRAM_ARB
,
GL_PROGRAM_FORMAT_ASCII_ARB
,
qstrlen
(
program
),
reinterpret_cast
<
const
GLvoid
*>
(
program
));
if
((
glError
=
glGetError
())
!=
GL_NO_ERROR
)
{
const
GLubyte
*
errorString
=
glGetString
(
GL_PROGRAM_ERROR_STRING_ARB
);
glDeleteProgramsARB
(
1
,
&
m_programId
);
m_textureCount
=
0
;
m_programId
=
0
;
throw
QString
(
"ARBfp Shader compile error "
)
+
QString
::
number
(
static_cast
<
int
>
(
glError
),
16
)
+
reinterpret_cast
<
const
char
*>
(
errorString
);
}
else
{
glGenTextures
(
m_textureCount
,
m_textureIds
);
}
}
}
void
ArbFpSurfacePainter
::
cleanup
()
{
glDeleteTextures
(
m_textureCount
,
m_textureIds
);
glDeleteProgramsARB
(
1
,
&
m_programId
);
m_textureCount
=
0
;
m_programId
=
0
;
}
void
ArbFpSurfacePainter
::
paintImpl
(
const
QPainter
*
painter
,
const
GLfloat
*
vertexCoordArray
,
const
GLfloat
*
textureCoordArray
)
{
Q_UNUSED
(
painter
);
glEnable
(
GL_FRAGMENT_PROGRAM_ARB
);
glBindProgramARB
(
GL_FRAGMENT_PROGRAM_ARB
,
m_programId
);
glProgramLocalParameter4fARB
(
GL_FRAGMENT_PROGRAM_ARB
,
0
,
m_colorMatrix
(
0
,
0
),
m_colorMatrix
(
0
,
1
),
m_colorMatrix
(
0
,
2
),
m_colorMatrix
(
0
,
3
));
glProgramLocalParameter4fARB
(
GL_FRAGMENT_PROGRAM_ARB
,
1
,
m_colorMatrix
(
1
,
0
),
m_colorMatrix
(
1
,
1
),
m_colorMatrix
(
1
,
2
),
m_colorMatrix
(
1
,
3
));
glProgramLocalParameter4fARB
(
GL_FRAGMENT_PROGRAM_ARB
,
2
,
m_colorMatrix
(
2
,
0
),
m_colorMatrix
(
2
,
1
),
m_colorMatrix
(
2
,
2
),
m_colorMatrix
(
2
,
3
));
glActiveTexture
(
GL_TEXTURE0
);
glBindTexture
(
GL_TEXTURE_2D
,
m_textureIds
[
0
]);
if
(
m_textureCount
==
3
)
{
glActiveTexture
(
GL_TEXTURE1
);
glBindTexture
(
GL_TEXTURE_2D
,
m_textureIds
[
1
]);
glActiveTexture
(
GL_TEXTURE2
);
glBindTexture
(
GL_TEXTURE_2D
,
m_textureIds
[
2
]);
glActiveTexture
(
GL_TEXTURE0
);
}
glVertexPointer
(
2
,
GL_FLOAT
,
0
,
vertexCoordArray
);
glTexCoordPointer
(
2
,
GL_FLOAT
,
0
,
textureCoordArray
);
glEnableClientState
(
GL_VERTEX_ARRAY
);
glEnableClientState
(
GL_TEXTURE_COORD_ARRAY
);
glDrawArrays
(
GL_TRIANGLE_STRIP
,
0
,
4
);
glDisableClientState
(
GL_VERTEX_ARRAY
);
glDisableClientState
(
GL_TEXTURE_COORD_ARRAY
);
glDisable
(
GL_FRAGMENT_PROGRAM_ARB
);
}
#endif
static
const
char
*
qt_glsl_vertexShaderProgram
=
"attribute highp vec4 vertexCoordArray;
\n
"
"attribute highp vec2 textureCoordArray;
\n
"
"uniform highp mat4 positionMatrix;
\n
"
"varying highp vec2 textureCoord;
\n
"
"void main(void)
\n
"
"{
\n
"
" gl_Position = positionMatrix * vertexCoordArray;
\n
"
" textureCoord = textureCoordArray;
\n
"
"}
\n
"
;
// Interprets the RGBA texture as in fact being BGRx and paints it.
static
const
char
*
qt_glsl_bgrxShaderProgram
=
"uniform sampler2D texRgb;
\n
"
"uniform mediump mat4 colorMatrix;
\n
"
"varying highp vec2 textureCoord;
\n
"
"void main(void)
\n
"
"{
\n
"
" highp vec4 color = vec4(texture2D(texRgb, textureCoord.st).bgr, 1.0);
\n
"
" gl_FragColor = colorMatrix * color;
\n
"
"}
\n
"
;
// Interprets the RGBA texture as in fact being BGRA and paints it.
static
const
char
*
qt_glsl_bgraShaderProgram
=
"uniform sampler2D texRgb;
\n
"
"uniform mediump mat4 colorMatrix;
\n
"
"varying highp vec2 textureCoord;
\n
"
"void main(void)
\n
"
"{
\n
"
" highp vec4 color = vec4(texture2D(texRgb, textureCoord.st).bgr, 1.0);
\n
"
" color = colorMatrix * color;
\n
"
" gl_FragColor = vec4(color.rgb, texture2D(texRgb, textureCoord.st).a);
\n
"
"}
\n
"
;
// Interprets the RGBA texture as in fact being xRGB and paints it.
static
const
char
*
qt_glsl_xrgbShaderProgram
=
"uniform sampler2D texRgb;
\n
"
"uniform mediump mat4 colorMatrix;
\n
"
"varying highp vec2 textureCoord;
\n
"
"void main(void)
\n
"
"{
\n
"
" highp vec4 color = vec4(texture2D(texRgb, textureCoord.st).gba, 1.0);
\n
"
" gl_FragColor = colorMatrix * color;
\n
"
"}
\n
"
;
// Interprets the RGBA texture as in fact being ARGB and paints it.
static
const
char
*
qt_glsl_argbShaderProgram
=
"uniform sampler2D texRgb;
\n
"
"uniform mediump mat4 colorMatrix;
\n
"
"varying highp vec2 textureCoord;
\n
"
"void main(void)
\n
"
"{
\n
"
" highp vec4 color = vec4(texture2D(texRgb, textureCoord.st).gba, 1.0);
\n
"
" color = colorMatrix * color;
\n
"
" gl_FragColor = vec4(color.rgb, texture2D(texRgb, textureCoord.st).r);
\n
"
"}
\n
"
;
// Paints RGB frames without doing any color channel flipping.
static
const
char
*
qt_glsl_rgbxShaderProgram
=
"uniform sampler2D texRgb;
\n
"
"uniform mediump mat4 colorMatrix;
\n
"
"varying highp vec2 textureCoord;
\n
"
"void main(void)
\n
"
"{
\n
"
" highp vec4 color = vec4(texture2D(texRgb, textureCoord.st).rgb, 1.0);
\n
"
" gl_FragColor = colorMatrix * color;
\n
"
"}
\n
"
;
// Paints planar yuv frames.
static
const
char
*
qt_glsl_yuvPlanarShaderProgram
=
"uniform sampler2D texY;
\n
"
"uniform sampler2D texU;
\n
"
"uniform sampler2D texV;
\n
"
"uniform mediump mat4 colorMatrix;
\n
"
"varying highp vec2 textureCoord;
\n
"
"void main(void)
\n
"
"{
\n
"
" highp vec4 color = vec4(
\n
"
" texture2D(texY, textureCoord.st).r,
\n
"
" texture2D(texU, textureCoord.st).r,
\n
"
" texture2D(texV, textureCoord.st).r,
\n
"
" 1.0);
\n
"
" gl_FragColor = colorMatrix * color;
\n
"
"}
\n
"
;
GlslSurfacePainter
::
GlslSurfacePainter
()
:
OpenGLSurfacePainter
()
{
}
void
GlslSurfacePainter
::
init
(
const
BufferFormat
&
format
)
{
Q_ASSERT
(
m_textureCount
==
0
);
const
char
*
fragmentProgram
=
0
;
switch
(
format
.
videoFormat
())
{
case
GST_VIDEO_FORMAT_BGRx
:
initRgbTextureInfo
(
GL_RGBA
,
GL_RGBA
,
GL_UNSIGNED_BYTE
,
format
.
frameSize
());
fragmentProgram
=
qt_glsl_bgrxShaderProgram
;
break
;
case
GST_VIDEO_FORMAT_xRGB
:
initRgbTextureInfo
(
GL_RGBA
,
GL_RGBA
,
GL_UNSIGNED_BYTE
,
format
.
frameSize
());
fragmentProgram
=
qt_glsl_xrgbShaderProgram
;
break
;
case
GST_VIDEO_FORMAT_BGRA
:
initRgbTextureInfo
(
GL_RGBA
,
GL_RGBA
,
GL_UNSIGNED_BYTE
,
format
.
frameSize
());
fragmentProgram
=
qt_glsl_bgraShaderProgram
;
break
;
case
GST_VIDEO_FORMAT_ARGB
:
initRgbTextureInfo
(
GL_RGBA
,
GL_RGBA
,
GL_UNSIGNED_BYTE
,
format
.
frameSize
());
fragmentProgram
=
qt_glsl_argbShaderProgram
;
break
;
case
GST_VIDEO_FORMAT_RGB
:
initRgbTextureInfo
(
GL_RGB
,
GL_RGB
,
GL_UNSIGNED_BYTE
,
format
.
frameSize
());
fragmentProgram
=
qt_glsl_rgbxShaderProgram
;
break
;
case
GST_VIDEO_FORMAT_BGR
:
initRgbTextureInfo
(
GL_RGB
,
GL_RGB
,
GL_UNSIGNED_BYTE
,
format
.
frameSize
());
fragmentProgram
=
qt_glsl_bgrxShaderProgram
;
break
;
//NOTE: unlike the other formats, this is endianness-dependent,
//but using GL_UNSIGNED_SHORT_5_6_5 ensures that it's handled correctly
case
GST_VIDEO_FORMAT_RGB16
:
initRgbTextureInfo
(
GL_RGB
,
GL_RGB
,
GL_UNSIGNED_SHORT_5_6_5
,
format
.
frameSize
());
fragmentProgram
=
qt_glsl_rgbxShaderProgram
;
break
;
case
GST_VIDEO_FORMAT_v308
:
initRgbTextureInfo
(
GL_RGB
,
GL_RGB
,
GL_UNSIGNED_BYTE
,
format
.
frameSize
());
fragmentProgram
=
qt_glsl_rgbxShaderProgram
;
break
;
case
GST_VIDEO_FORMAT_AYUV
:
initRgbTextureInfo
(
GL_RGBA
,
GL_RGBA
,
GL_UNSIGNED_BYTE
,
format
.
frameSize
());
fragmentProgram
=
qt_glsl_argbShaderProgram
;
break
;
case
GST_VIDEO_FORMAT_YV12
:
initYv12TextureInfo
(
format
.
frameSize
());
fragmentProgram
=
qt_glsl_yuvPlanarShaderProgram
;
break
;
case
GST_VIDEO_FORMAT_I420
:
initYuv420PTextureInfo
(
format
.
frameSize
());
fragmentProgram
=
qt_glsl_yuvPlanarShaderProgram
;
break
;
default:
Q_ASSERT
(
false
);
break
;
}
m_videoColorMatrix
=
format
.
colorMatrix
();
if
(
!
m_program
.
addShaderFromSourceCode
(
QGLShader
::
Vertex
,
qt_glsl_vertexShaderProgram
))
{
throw
QString
(
"Vertex shader compile error "
)
+
m_program
.
log
();
}
if
(
!
m_program
.
addShaderFromSourceCode
(
QGLShader
::
Fragment
,
fragmentProgram
))
{
throw
QString
(
"Shader compile error "
)
+
m_program
.
log
();
}
if
(
!
m_program
.
link
())
{
throw
QString
(
"Shader link error "
)
+
m_program
.
log
();
}
glGenTextures
(
m_textureCount
,
m_textureIds
);
}
void
GlslSurfacePainter
::
cleanup
()
{
glDeleteTextures
(
m_textureCount
,
m_textureIds
);
m_program
.
removeAllShaders
();
m_textureCount
=
0
;
}
void
GlslSurfacePainter
::
paintImpl
(
const
QPainter
*
painter
,
const
GLfloat
*
vertexCoordArray
,
const
GLfloat
*
textureCoordArray
)
{
const
int
deviceWidth
=
painter
->
device
()
->
width
();
const
int
deviceHeight
=
painter
->
device
()
->
height
();
const
QTransform
transform
=
painter
->
deviceTransform
();
const
GLfloat
wfactor
=
2.0
/
deviceWidth
;
const
GLfloat
hfactor
=
-
2.0
/
deviceHeight
;
const
GLfloat
positionMatrix
[
4
][
4
]
=
{
{
/*(0,0)*/
GLfloat
(
wfactor
*
transform
.
m11
()
-
transform
.
m13
()),
/*(0,1)*/
GLfloat
(
hfactor
*
transform
.
m12
()
+
transform
.
m13
()),
/*(0,2)*/
0.0
,
/*(0,3)*/
GLfloat
(
transform
.
m13
())
},
{
/*(1,0)*/
GLfloat
(
wfactor
*
transform
.
m21
()
-
transform
.
m23
()),
/*(1,1)*/
GLfloat
(
hfactor
*
transform
.
m22
()
+
transform
.
m23
()),
/*(1,2)*/
0.0
,
/*(1,3)*/
GLfloat
(
transform
.
m23
())
},
{
/*(2,0)*/
0.0
,
/*(2,1)*/
0.0
,
/*(2,2)*/
-
1.0
,
/*(2,3)*/
0.0
},
{
/*(3,0)*/
GLfloat
(
wfactor
*
transform
.
dx
()
-
transform
.
m33
()),
/*(3,1)*/
GLfloat
(
hfactor
*
transform
.
dy
()
+
transform
.
m33
()),
/*(3,2)*/
0.0
,
/*(3,3)*/
GLfloat
(
transform
.
m33
())
}
};
m_program
.
bind
();
m_program
.
enableAttributeArray
(
"vertexCoordArray"
);
m_program
.
enableAttributeArray
(
"textureCoordArray"
);
m_program
.
setAttributeArray
(
"vertexCoordArray"
,
vertexCoordArray
,
2
);
m_program
.
setAttributeArray
(
"textureCoordArray"
,
textureCoordArray
,
2
);
m_program
.
setUniformValue
(
"positionMatrix"
,
positionMatrix
);
if
(
m_textureCount
==
3
)
{
glActiveTexture
(
GL_TEXTURE0
);
glBindTexture
(
GL_TEXTURE_2D
,
m_textureIds
[
0
]);
glActiveTexture
(
GL_TEXTURE1
);
glBindTexture
(
GL_TEXTURE_2D
,
m_textureIds
[
1
]);
glActiveTexture
(
GL_TEXTURE2
);
glBindTexture
(
GL_TEXTURE_2D
,
m_textureIds
[
2
]);
glActiveTexture
(
GL_TEXTURE0
);
m_program
.
setUniformValue
(
"texY"
,
0
);
m_program
.
setUniformValue
(
"texU"
,
1
);
m_program
.
setUniformValue
(
"texV"
,
2
);
}
else
{
glActiveTexture
(
GL_TEXTURE0
);
glBindTexture
(
GL_TEXTURE_2D
,
m_textureIds
[
0
]);
m_program
.
setUniformValue
(
"texRgb"
,
0
);
}
m_program
.
setUniformValue
(
"colorMatrix"
,
m_colorMatrix
);
glDrawArrays
(
GL_TRIANGLE_STRIP
,
0
,
4
);
m_program
.
release
();
}
src/VideoStreaming/gstqtvideosink/painters/openglsurfacepainter.h
0 → 100644
View file @
4b4f758b
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011-2012 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#ifndef OPENGLSURFACEPAINTER_H
#define OPENGLSURFACEPAINTER_H
#ifndef GST_QT_VIDEO_SINK_NO_OPENGL
#include "abstractsurfacepainter.h"
#include <QGLShaderProgram>
#ifndef Q_WS_MAC
# ifndef APIENTRYP
# ifdef APIENTRY
# define APIENTRYP APIENTRY *
# else
# define APIENTRY
# define APIENTRYP *
# endif
# endif
#else
# define APIENTRY
# define APIENTRYP *
#endif
class
OpenGLSurfacePainter
:
public
AbstractSurfacePainter
{
public:
OpenGLSurfacePainter
();
static
QSet
<
GstVideoFormat
>
supportedPixelFormats
();
virtual
bool
supportsFormat
(
GstVideoFormat
format
)
const
{
return
supportedPixelFormats
().
contains
(
format
);
}
virtual
void
updateColors
(
int
brightness
,
int
contrast
,
int
hue
,
int
saturation
);
virtual
void
paint
(
quint8
*
data
,
const
BufferFormat
&
frameFormat
,
QPainter
*
painter
,
const
PaintAreas
&
areas
);
protected:
void
initRgbTextureInfo
(
GLenum
internalFormat
,
GLuint
format
,
GLenum
type
,
const
QSize
&
size
);
void
initYuv420PTextureInfo
(
const
QSize
&
size
);
void
initYv12TextureInfo
(
const
QSize
&
size
);
virtual
void
paintImpl
(
const
QPainter
*
painter
,
const
GLfloat
*
vertexCoordArray
,
const
GLfloat
*
textureCoordArray
)
=
0
;
#ifndef QT_OPENGL_ES
typedef
void
(
APIENTRY
*
_glActiveTexture
)
(
GLenum
);
_glActiveTexture
glActiveTexture
;
#endif
GLenum
m_textureFormat
;
GLuint
m_textureInternalFormat
;
GLenum
m_textureType
;
int
m_textureCount
;
GLuint
m_textureIds
[
3
];
int
m_textureWidths
[
3
];
int
m_textureHeights
[
3
];
int
m_textureOffsets
[
3
];
QMatrix4x4
m_colorMatrix
;
GstVideoColorMatrix
m_videoColorMatrix
;
};
#ifndef QT_OPENGL_ES
class
ArbFpSurfacePainter
:
public
OpenGLSurfacePainter
{
public:
ArbFpSurfacePainter
();
virtual
void
init
(
const
BufferFormat
&
format
);
virtual
void
cleanup
();
protected:
virtual
void
paintImpl
(
const
QPainter
*
painter
,
const
GLfloat
*
vertexCoordArray
,
const
GLfloat
*
textureCoordArray
);
private:
typedef
void
(
APIENTRY
*
_glProgramStringARB
)
(
GLenum
,
GLenum
,
GLsizei
,
const
GLvoid
*
);
typedef
void
(
APIENTRY
*
_glBindProgramARB
)
(
GLenum
,
GLuint
);
typedef
void
(
APIENTRY
*
_glDeleteProgramsARB
)
(
GLsizei
,
const
GLuint
*
);
typedef
void
(
APIENTRY
*
_glGenProgramsARB
)
(
GLsizei
,
GLuint
*
);
typedef
void
(
APIENTRY
*
_glProgramLocalParameter4fARB
)
(
GLenum
,
GLuint
,
GLfloat
,
GLfloat
,
GLfloat
,
GLfloat
);
typedef
void
(
APIENTRY
*
_glActiveTexture
)
(
GLenum
);
_glProgramStringARB
glProgramStringARB
;
_glBindProgramARB
glBindProgramARB
;
_glDeleteProgramsARB
glDeleteProgramsARB
;
_glGenProgramsARB
glGenProgramsARB
;
_glProgramLocalParameter4fARB
glProgramLocalParameter4fARB
;
GLuint
m_programId
;
};
#endif
class
GlslSurfacePainter
:
public
OpenGLSurfacePainter
{
public:
GlslSurfacePainter
();
virtual
void
init
(
const
BufferFormat
&
format
);
virtual
void
cleanup
();
protected:
virtual
void
paintImpl
(
const
QPainter
*
painter
,
const
GLfloat
*
vertexCoordArray
,
const
GLfloat
*
textureCoordArray
);
private:
QGLShaderProgram
m_program
;
};
#endif // GST_QT_VIDEO_SINK_NO_OPENGL
#endif // OPENGLSURFACEPAINTER_H
src/VideoStreaming/gstqtvideosink/painters/videomaterial.cpp
0 → 100644
View file @
4b4f758b
/*
Copyright (C) 2011-2013 Collabora Ltd. <info@collabora.com>
Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
Copyright (C) 2013 basysKom GmbH <info@basyskom.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted (and fixed) from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#include "videomaterial.h"
#include <qmath.h>
#include <QOpenGLContext>
#include <QOpenGLFunctions>
#include <QtQuick/QSGMaterialShader>
static
const
char
*
const
qtvideosink_glsl_vertexShader
=
"uniform highp mat4 qt_Matrix;
\n
"
"attribute highp vec4 qt_VertexPosition;
\n
"
"attribute highp vec2 qt_VertexTexCoord;
\n
"
"varying highp vec2 qt_TexCoord;
\n
"
"void main() {
\n
"
" qt_TexCoord = qt_VertexTexCoord;
\n
"
" gl_Position = qt_Matrix * qt_VertexPosition;
\n
"
"}"
;
inline
const
char
*
qtvideosink_glsl_bgrxFragmentShader
()
{
return
"uniform sampler2D rgbTexture;
\n
"
"uniform lowp float opacity;
\n
"
"uniform mediump mat4 colorMatrix;
\n
"
"varying highp vec2 qt_TexCoord;
\n
"
"void main(void)
\n
"
"{
\n
"
" highp vec4 color = vec4(texture2D(rgbTexture, qt_TexCoord.st).bgr, 1.0);
\n
"
" gl_FragColor = colorMatrix * color * opacity;
\n
"
"}
\n
"
;
}
inline
const
char
*
qtvideosink_glsl_xrgbFragmentShader
()
{
return
"uniform sampler2D rgbTexture;
\n
"
"uniform lowp float opacity;
\n
"
"uniform mediump mat4 colorMatrix;
\n
"
"varying highp vec2 qt_TexCoord;
\n
"
"void main(void)
\n
"
"{
\n
"
" highp vec4 color = vec4(texture2D(rgbTexture, qt_TexCoord.st).gba, 1.0);
\n
"
" gl_FragColor = colorMatrix * color * opacity;
\n
"
"}
\n
"
;
}
inline
const
char
*
qtvideosink_glsl_rgbxFragmentShader
()
{
return
"uniform sampler2D rgbTexture;
\n
"
"uniform lowp float opacity;
\n
"
"uniform mediump mat4 colorMatrix;
\n
"
"varying highp vec2 qt_TexCoord;
\n
"
"void main(void)
\n
"
"{
\n
"
" highp vec4 color = vec4(texture2D(rgbTexture, qt_TexCoord.st).rgb, 1.0);
\n
"
" gl_FragColor = colorMatrix * color * opacity;
\n
"
"}
\n
"
;
}
inline
const
char
*
qtvideosink_glsl_yuvPlanarFragmentShader
()
{
return
"uniform sampler2D yTexture;
\n
"
"uniform sampler2D uTexture;
\n
"
"uniform sampler2D vTexture;
\n
"
"uniform mediump mat4 colorMatrix;
\n
"
"uniform lowp float opacity;
\n
"
"varying highp vec2 qt_TexCoord;
\n
"
"void main(void)
\n
"
"{
\n
"
" highp vec4 color = vec4(
\n
"
" texture2D(yTexture, qt_TexCoord.st).r,
\n
"
" texture2D(uTexture, qt_TexCoord.st).r,
\n
"
" texture2D(vTexture, qt_TexCoord.st).r,
\n
"
" 1.0);
\n
"
" gl_FragColor = colorMatrix * color * opacity;
\n
"
"}
\n
"
;
}
class
VideoMaterialShader
:
public
QSGMaterialShader
{
public:
virtual
void
updateState
(
const
RenderState
&
state
,
QSGMaterial
*
newMaterial
,
QSGMaterial
*
oldMaterial
)
{
Q_UNUSED
(
oldMaterial
);
VideoMaterial
*
material
=
static_cast
<
VideoMaterial
*>
(
newMaterial
);
if
(
m_id_rgbTexture
>
0
)
{
program
()
->
setUniformValue
(
m_id_rgbTexture
,
0
);
}
else
{
program
()
->
setUniformValue
(
m_id_yTexture
,
0
);
program
()
->
setUniformValue
(
m_id_uTexture
,
1
);
program
()
->
setUniformValue
(
m_id_vTexture
,
2
);
}
if
(
state
.
isOpacityDirty
())
{
material
->
setFlag
(
QSGMaterial
::
Blending
,
qFuzzyCompare
(
state
.
opacity
(),
1.0
f
)
?
false
:
true
);
program
()
->
setUniformValue
(
m_id_opacity
,
GLfloat
(
state
.
opacity
()));
}
if
(
state
.
isMatrixDirty
())
program
()
->
setUniformValue
(
m_id_matrix
,
state
.
combinedMatrix
());
program
()
->
setUniformValue
(
m_id_colorMatrix
,
material
->
m_colorMatrix
);
material
->
bind
();
}
virtual
char
const
*
const
*
attributeNames
()
const
{
static
const
char
*
names
[]
=
{
"qt_VertexPosition"
,
"qt_VertexTexCoord"
,
0
};
return
names
;
}
protected:
virtual
void
initialize
()
{
m_id_matrix
=
program
()
->
uniformLocation
(
"qt_Matrix"
);
m_id_rgbTexture
=
program
()
->
uniformLocation
(
"rgbTexture"
);
m_id_yTexture
=
program
()
->
uniformLocation
(
"yTexture"
);
m_id_uTexture
=
program
()
->
uniformLocation
(
"uTexture"
);
m_id_vTexture
=
program
()
->
uniformLocation
(
"vTexture"
);
m_id_colorMatrix
=
program
()
->
uniformLocation
(
"colorMatrix"
);
m_id_opacity
=
program
()
->
uniformLocation
(
"opacity"
);
}
virtual
const
char
*
vertexShader
()
const
{
return
qtvideosink_glsl_vertexShader
;
}
int
m_id_matrix
;
int
m_id_rgbTexture
;
int
m_id_yTexture
;
int
m_id_uTexture
;
int
m_id_vTexture
;
int
m_id_colorMatrix
;
int
m_id_opacity
;
};
template
<
const
char
*
(
*
FragmentShader
)()
>
class
VideoMaterialShaderImpl
:
public
VideoMaterialShader
{
protected:
virtual
const
char
*
fragmentShader
()
const
{
return
FragmentShader
();
}
};
template
<
const
char
*
(
*
FragmentShader
)()
>
class
VideoMaterialImpl
:
public
VideoMaterial
{
public:
virtual
QSGMaterialType
*
type
()
const
{
static
QSGMaterialType
theType
;
return
&
theType
;
}
virtual
QSGMaterialShader
*
createShader
()
const
{
return
new
VideoMaterialShaderImpl
<
FragmentShader
>
;
}
};
VideoMaterial
*
VideoMaterial
::
create
(
const
BufferFormat
&
format
)
{
VideoMaterial
*
material
=
NULL
;
switch
(
format
.
videoFormat
())
{
// BGRx
case
GST_VIDEO_FORMAT_BGRx
:
case
GST_VIDEO_FORMAT_BGRA
:
material
=
new
VideoMaterialImpl
<
qtvideosink_glsl_bgrxFragmentShader
>
;
material
->
initRgbTextureInfo
(
GL_RGBA
,
GL_RGBA
,
GL_UNSIGNED_BYTE
,
format
.
frameSize
());
break
;
case
GST_VIDEO_FORMAT_BGR
:
material
=
new
VideoMaterialImpl
<
qtvideosink_glsl_bgrxFragmentShader
>
;
material
->
initRgbTextureInfo
(
GL_RGB
,
GL_RGB
,
GL_UNSIGNED_BYTE
,
format
.
frameSize
());
break
;
// xRGB
case
GST_VIDEO_FORMAT_xRGB
:
case
GST_VIDEO_FORMAT_ARGB
:
case
GST_VIDEO_FORMAT_AYUV
:
material
=
new
VideoMaterialImpl
<
qtvideosink_glsl_xrgbFragmentShader
>
;
material
->
initRgbTextureInfo
(
GL_RGBA
,
GL_RGBA
,
GL_UNSIGNED_BYTE
,
format
.
frameSize
());
break
;
// RGBx
case
GST_VIDEO_FORMAT_RGB
:
case
GST_VIDEO_FORMAT_v308
:
material
=
new
VideoMaterialImpl
<
qtvideosink_glsl_rgbxFragmentShader
>
;
material
->
initRgbTextureInfo
(
GL_RGB
,
GL_RGB
,
GL_UNSIGNED_BYTE
,
format
.
frameSize
());
break
;
case
GST_VIDEO_FORMAT_RGB16
:
material
=
new
VideoMaterialImpl
<
qtvideosink_glsl_rgbxFragmentShader
>
;
material
->
initRgbTextureInfo
(
GL_RGB
,
GL_RGB
,
GL_UNSIGNED_SHORT_5_6_5
,
format
.
frameSize
());
break
;
// YUV 420 planar
case
GST_VIDEO_FORMAT_I420
:
case
GST_VIDEO_FORMAT_YV12
:
material
=
new
VideoMaterialImpl
<
qtvideosink_glsl_yuvPlanarFragmentShader
>
;
material
->
initYuv420PTextureInfo
(
(
format
.
videoFormat
()
==
GST_VIDEO_FORMAT_YV12
)
/* uvSwapped */
,
format
.
frameSize
());
break
;
default:
Q_ASSERT
(
false
);
break
;
}
material
->
init
(
format
.
colorMatrix
());
return
material
;
}
VideoMaterial
::
VideoMaterial
()
:
m_frame
(
0
)
,
m_textureCount
(
0
)
,
m_textureFormat
(
0
)
,
m_textureInternalFormat
(
0
)
,
m_textureType
(
0
)
,
m_colorMatrixType
(
GST_VIDEO_COLOR_MATRIX_UNKNOWN
)
{
memset
(
m_textureIds
,
0
,
sizeof
(
m_textureIds
));
setFlag
(
Blending
,
false
);
}
VideoMaterial
::~
VideoMaterial
()
{
if
(
!
m_textureSize
.
isEmpty
())
glDeleteTextures
(
m_textureCount
,
m_textureIds
);
gst_buffer_replace
(
&
m_frame
,
NULL
);
}
int
VideoMaterial
::
compare
(
const
QSGMaterial
*
other
)
const
{
const
VideoMaterial
*
m
=
static_cast
<
const
VideoMaterial
*>
(
other
);
int
d
=
m_textureIds
[
0
]
-
m
->
m_textureIds
[
0
];
if
(
d
||
m_textureCount
==
1
)
return
d
;
else
if
((
d
=
m_textureIds
[
1
]
-
m
->
m_textureIds
[
1
])
!=
0
)
return
d
;
else
return
m_textureIds
[
2
]
-
m
->
m_textureIds
[
2
];
}
void
VideoMaterial
::
initRgbTextureInfo
(
GLenum
internalFormat
,
GLuint
format
,
GLenum
type
,
const
QSize
&
size
)
{
#ifndef QT_OPENGL_ES
//make sure we get 8 bits per component, at least on the desktop GL where we can
switch
(
internalFormat
)
{
case
GL_RGBA
:
internalFormat
=
GL_RGBA8
;
break
;
case
GL_RGB
:
internalFormat
=
GL_RGB8
;
break
;
default:
break
;
}
#endif
m_textureInternalFormat
=
internalFormat
;
m_textureFormat
=
format
;
m_textureType
=
type
;
m_textureCount
=
1
;
m_textureWidths
[
0
]
=
size
.
width
();
m_textureHeights
[
0
]
=
size
.
height
();
m_textureOffsets
[
0
]
=
0
;
}
void
VideoMaterial
::
initYuv420PTextureInfo
(
bool
uvSwapped
,
const
QSize
&
size
)
{
int
bytesPerLine
=
(
size
.
width
()
+
3
)
&
~
3
;
int
bytesPerLine2
=
(
size
.
width
()
/
2
+
3
)
&
~
3
;
m_textureInternalFormat
=
GL_LUMINANCE
;
m_textureFormat
=
GL_LUMINANCE
;
m_textureType
=
GL_UNSIGNED_BYTE
;
m_textureCount
=
3
;
m_textureWidths
[
0
]
=
bytesPerLine
;
m_textureHeights
[
0
]
=
size
.
height
();
m_textureOffsets
[
0
]
=
0
;
m_textureWidths
[
1
]
=
bytesPerLine2
;
m_textureHeights
[
1
]
=
size
.
height
()
/
2
;
m_textureOffsets
[
1
]
=
bytesPerLine
*
size
.
height
();
m_textureWidths
[
2
]
=
bytesPerLine2
;
m_textureHeights
[
2
]
=
size
.
height
()
/
2
;
m_textureOffsets
[
2
]
=
bytesPerLine
*
size
.
height
()
+
bytesPerLine2
*
size
.
height
()
/
2
;
if
(
uvSwapped
)
qSwap
(
m_textureOffsets
[
1
],
m_textureOffsets
[
2
]);
}
void
VideoMaterial
::
init
(
GstVideoColorMatrix
colorMatrixType
)
{
glGenTextures
(
m_textureCount
,
m_textureIds
);
m_colorMatrixType
=
colorMatrixType
;
updateColors
(
0
,
0
,
0
,
0
);
}
void
VideoMaterial
::
setCurrentFrame
(
GstBuffer
*
buffer
)
{
QMutexLocker
lock
(
&
m_frameMutex
);
gst_buffer_replace
(
&
m_frame
,
buffer
);
}
void
VideoMaterial
::
updateColors
(
int
brightness
,
int
contrast
,
int
hue
,
int
saturation
)
{
const
qreal
b
=
brightness
/
200.0
;
const
qreal
c
=
contrast
/
100.0
+
1.0
;
const
qreal
h
=
hue
/
100.0
;
const
qreal
s
=
saturation
/
100.0
+
1.0
;
const
qreal
cosH
=
qCos
(
M_PI
*
h
);
const
qreal
sinH
=
qSin
(
M_PI
*
h
);
const
qreal
h11
=
0.787
*
cosH
-
0.213
*
sinH
+
0.213
;
const
qreal
h21
=
-
0.213
*
cosH
+
0.143
*
sinH
+
0.213
;
const
qreal
h31
=
-
0.213
*
cosH
-
0.787
*
sinH
+
0.213
;
const
qreal
h12
=
-
0.715
*
cosH
-
0.715
*
sinH
+
0.715
;
const
qreal
h22
=
0.285
*
cosH
+
0.140
*
sinH
+
0.715
;
const
qreal
h32
=
-
0.715
*
cosH
+
0.715
*
sinH
+
0.715
;
const
qreal
h13
=
-
0.072
*
cosH
+
0.928
*
sinH
+
0.072
;
const
qreal
h23
=
-
0.072
*
cosH
-
0.283
*
sinH
+
0.072
;
const
qreal
h33
=
0.928
*
cosH
+
0.072
*
sinH
+
0.072
;
const
qreal
sr
=
(
1.0
-
s
)
*
0.3086
;
const
qreal
sg
=
(
1.0
-
s
)
*
0.6094
;
const
qreal
sb
=
(
1.0
-
s
)
*
0.0820
;
const
qreal
sr_s
=
sr
+
s
;
const
qreal
sg_s
=
sg
+
s
;
const
qreal
sb_s
=
sr
+
s
;
const
float
m4
=
(
s
+
sr
+
sg
+
sb
)
*
(
0.5
-
0.5
*
c
+
b
);
m_colorMatrix
(
0
,
0
)
=
c
*
(
sr_s
*
h11
+
sg
*
h21
+
sb
*
h31
);
m_colorMatrix
(
0
,
1
)
=
c
*
(
sr_s
*
h12
+
sg
*
h22
+
sb
*
h32
);
m_colorMatrix
(
0
,
2
)
=
c
*
(
sr_s
*
h13
+
sg
*
h23
+
sb
*
h33
);
m_colorMatrix
(
0
,
3
)
=
m4
;
m_colorMatrix
(
1
,
0
)
=
c
*
(
sr
*
h11
+
sg_s
*
h21
+
sb
*
h31
);
m_colorMatrix
(
1
,
1
)
=
c
*
(
sr
*
h12
+
sg_s
*
h22
+
sb
*
h32
);
m_colorMatrix
(
1
,
2
)
=
c
*
(
sr
*
h13
+
sg_s
*
h23
+
sb
*
h33
);
m_colorMatrix
(
1
,
3
)
=
m4
;
m_colorMatrix
(
2
,
0
)
=
c
*
(
sr
*
h11
+
sg
*
h21
+
sb_s
*
h31
);
m_colorMatrix
(
2
,
1
)
=
c
*
(
sr
*
h12
+
sg
*
h22
+
sb_s
*
h32
);
m_colorMatrix
(
2
,
2
)
=
c
*
(
sr
*
h13
+
sg
*
h23
+
sb_s
*
h33
);
m_colorMatrix
(
2
,
3
)
=
m4
;
m_colorMatrix
(
3
,
0
)
=
0.0
;
m_colorMatrix
(
3
,
1
)
=
0.0
;
m_colorMatrix
(
3
,
2
)
=
0.0
;
m_colorMatrix
(
3
,
3
)
=
1.0
;
switch
(
m_colorMatrixType
)
{
case
GST_VIDEO_COLOR_MATRIX_BT709
:
/*
* This is bogus (Gus Grubba 20150706)
m_colorMatrix *= QMatrix4x4(
1.164, 0.000, 1.793, -0.5727,
1.164, -0.534, -0.213, 0.3007,
1.164, 2.115, 0.000, -1.1302,
0.0, 0.000, 0.000, 1.0000);
break;
*/
case
GST_VIDEO_COLOR_MATRIX_BT601
:
m_colorMatrix
*=
QMatrix4x4
(
1.164
,
0.000
,
1.596
,
-
0.8708
,
1.164
,
-
0.392
,
-
0.813
,
0.5296
,
1.164
,
2.017
,
0.000
,
-
1.081
,
0.0
,
0.000
,
0.000
,
1.0000
);
break
;
default:
break
;
}
}
void
VideoMaterial
::
bind
()
{
QOpenGLFunctions
*
functions
=
QOpenGLContext
::
currentContext
()
->
functions
();
GstBuffer
*
frame
=
NULL
;
m_frameMutex
.
lock
();
if
(
m_frame
)
frame
=
gst_buffer_ref
(
m_frame
);
m_frameMutex
.
unlock
();
if
(
frame
)
{
GstMapInfo
info
;
gst_buffer_map
(
frame
,
&
info
,
GST_MAP_READ
);
functions
->
glActiveTexture
(
GL_TEXTURE1
);
bindTexture
(
1
,
info
.
data
);
functions
->
glActiveTexture
(
GL_TEXTURE2
);
bindTexture
(
2
,
info
.
data
);
functions
->
glActiveTexture
(
GL_TEXTURE0
);
// Finish with 0 as default texture unit
bindTexture
(
0
,
info
.
data
);
gst_buffer_unmap
(
frame
,
&
info
);
gst_buffer_unref
(
frame
);
}
else
{
functions
->
glActiveTexture
(
GL_TEXTURE1
);
glBindTexture
(
GL_TEXTURE_2D
,
m_textureIds
[
1
]);
functions
->
glActiveTexture
(
GL_TEXTURE2
);
glBindTexture
(
GL_TEXTURE_2D
,
m_textureIds
[
2
]);
functions
->
glActiveTexture
(
GL_TEXTURE0
);
// Finish with 0 as default texture unit
glBindTexture
(
GL_TEXTURE_2D
,
m_textureIds
[
0
]);
}
}
void
VideoMaterial
::
bindTexture
(
int
i
,
const
quint8
*
data
)
{
glBindTexture
(
GL_TEXTURE_2D
,
m_textureIds
[
i
]);
glTexImage2D
(
GL_TEXTURE_2D
,
0
,
m_textureInternalFormat
,
m_textureWidths
[
i
],
m_textureHeights
[
i
],
0
,
m_textureFormat
,
m_textureType
,
data
+
m_textureOffsets
[
i
]);
glTexParameteri
(
GL_TEXTURE_2D
,
GL_TEXTURE_MAG_FILTER
,
GL_LINEAR
);
glTexParameteri
(
GL_TEXTURE_2D
,
GL_TEXTURE_MIN_FILTER
,
GL_LINEAR
);
glTexParameteri
(
GL_TEXTURE_2D
,
GL_TEXTURE_WRAP_S
,
GL_CLAMP_TO_EDGE
);
glTexParameteri
(
GL_TEXTURE_2D
,
GL_TEXTURE_WRAP_T
,
GL_CLAMP_TO_EDGE
);
}
src/VideoStreaming/gstqtvideosink/painters/videomaterial.h
0 → 100644
View file @
4b4f758b
/*
Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
Copyright (C) 2013 basysKom GmbH <info@basyskom.com>
Copyright (C) 2013 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#ifndef VIDEOMATERIAL_H
#define VIDEOMATERIAL_H
#include "../utils/bufferformat.h"
#include <QSize>
#include <QMutex>
#include <QMatrix4x4>
#include <QtQuick/QSGMaterial>
class
VideoMaterialShader
;
class
VideoMaterial
:
public
QSGMaterial
{
public:
static
VideoMaterial
*
create
(
const
BufferFormat
&
format
);
virtual
~
VideoMaterial
();
virtual
int
compare
(
const
QSGMaterial
*
other
)
const
;
void
setCurrentFrame
(
GstBuffer
*
buffer
);
void
updateColors
(
int
brightness
,
int
contrast
,
int
hue
,
int
saturation
);
void
bind
();
protected:
VideoMaterial
();
void
initRgbTextureInfo
(
GLenum
internalFormat
,
GLuint
format
,
GLenum
type
,
const
QSize
&
size
);
void
initYuv420PTextureInfo
(
bool
uvSwapped
,
const
QSize
&
size
);
void
init
(
GstVideoColorMatrix
colorMatrixType
);
private:
void
bindTexture
(
int
i
,
const
quint8
*
data
);
GstBuffer
*
m_frame
;
QMutex
m_frameMutex
;
static
const
int
Num_Texture_IDs
=
3
;
int
m_textureCount
;
GLuint
m_textureIds
[
Num_Texture_IDs
];
int
m_textureWidths
[
Num_Texture_IDs
];
int
m_textureHeights
[
Num_Texture_IDs
];
int
m_textureOffsets
[
Num_Texture_IDs
];
QSize
m_textureSize
;
GLenum
m_textureFormat
;
GLuint
m_textureInternalFormat
;
GLenum
m_textureType
;
QMatrix4x4
m_colorMatrix
;
GstVideoColorMatrix
m_colorMatrixType
;
friend
class
VideoMaterialShader
;
};
#endif // VIDEOMATERIAL_H
src/VideoStreaming/gstqtvideosink/painters/videonode.cpp
0 → 100644
View file @
4b4f758b
/*
Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
Copyright (C) 2013 basysKom GmbH <info@basyskom.com>
Copyright (C) 2013 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#include "videonode.h"
#include "videomaterial.h"
#include <QtQuick/QSGFlatColorMaterial>
VideoNode
::
VideoNode
()
:
QSGGeometryNode
()
{
setFlags
(
OwnsGeometry
|
OwnsMaterial
,
true
);
setMaterialTypeSolidBlack
();
}
void
VideoNode
::
changeFormat
(
const
BufferFormat
&
format
)
{
setMaterial
(
VideoMaterial
::
create
(
format
));
setGeometry
(
0
);
m_materialType
=
MaterialTypeVideo
;
}
void
VideoNode
::
setMaterialTypeSolidBlack
()
{
QSGFlatColorMaterial
*
m
=
new
QSGFlatColorMaterial
;
m
->
setColor
(
Qt
::
black
);
setMaterial
(
m
);
setGeometry
(
0
);
m_materialType
=
MaterialTypeSolidBlack
;
}
void
VideoNode
::
setCurrentFrame
(
GstBuffer
*
buffer
)
{
Q_ASSERT
(
m_materialType
==
MaterialTypeVideo
);
static_cast
<
VideoMaterial
*>
(
material
())
->
setCurrentFrame
(
buffer
);
markDirty
(
DirtyMaterial
);
}
void
VideoNode
::
updateColors
(
int
brightness
,
int
contrast
,
int
hue
,
int
saturation
)
{
Q_ASSERT
(
m_materialType
==
MaterialTypeVideo
);
static_cast
<
VideoMaterial
*>
(
material
())
->
updateColors
(
brightness
,
contrast
,
hue
,
saturation
);
markDirty
(
DirtyMaterial
);
}
/* Helpers */
template
<
typename
V
>
static
inline
void
setGeom
(
V
*
v
,
const
QPointF
&
p
)
{
v
->
x
=
p
.
x
();
v
->
y
=
p
.
y
();
}
static
inline
void
setTex
(
QSGGeometry
::
TexturedPoint2D
*
v
,
const
QPointF
&
p
)
{
v
->
tx
=
p
.
x
();
v
->
ty
=
p
.
y
();
}
void
VideoNode
::
updateGeometry
(
const
PaintAreas
&
areas
)
{
QSGGeometry
*
g
=
geometry
();
if
(
m_materialType
==
MaterialTypeVideo
)
{
if
(
!
g
)
g
=
new
QSGGeometry
(
QSGGeometry
::
defaultAttributes_TexturedPoint2D
(),
4
);
QSGGeometry
::
TexturedPoint2D
*
v
=
g
->
vertexDataAsTexturedPoint2D
();
// Set geometry first
setGeom
(
v
+
0
,
areas
.
videoArea
.
topLeft
());
setGeom
(
v
+
1
,
areas
.
videoArea
.
bottomLeft
());
setGeom
(
v
+
2
,
areas
.
videoArea
.
topRight
());
setGeom
(
v
+
3
,
areas
.
videoArea
.
bottomRight
());
// and then texture coordinates
setTex
(
v
+
0
,
areas
.
sourceRect
.
topLeft
());
setTex
(
v
+
1
,
areas
.
sourceRect
.
bottomLeft
());
setTex
(
v
+
2
,
areas
.
sourceRect
.
topRight
());
setTex
(
v
+
3
,
areas
.
sourceRect
.
bottomRight
());
}
else
{
if
(
!
g
)
g
=
new
QSGGeometry
(
QSGGeometry
::
defaultAttributes_Point2D
(),
4
);
QSGGeometry
::
Point2D
*
v
=
g
->
vertexDataAsPoint2D
();
setGeom
(
v
+
0
,
areas
.
videoArea
.
topLeft
());
setGeom
(
v
+
1
,
areas
.
videoArea
.
bottomLeft
());
setGeom
(
v
+
2
,
areas
.
videoArea
.
topRight
());
setGeom
(
v
+
3
,
areas
.
videoArea
.
bottomRight
());
}
if
(
!
geometry
())
setGeometry
(
g
);
markDirty
(
DirtyGeometry
);
}
src/VideoStreaming/gstqtvideosink/painters/videonode.h
0 → 100644
View file @
4b4f758b
/*
Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
Copyright (C) 2013 basysKom GmbH <info@basyskom.com>
Copyright (C) 2013 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#ifndef VIDEONODE_H
#define VIDEONODE_H
#include "../utils/bufferformat.h"
#include <QtQuick/QSGGeometryNode>
class
VideoNode
:
public
QSGGeometryNode
{
public:
VideoNode
();
enum
MaterialType
{
MaterialTypeVideo
,
MaterialTypeSolidBlack
};
MaterialType
materialType
()
const
{
return
m_materialType
;
}
void
changeFormat
(
const
BufferFormat
&
format
);
void
setMaterialTypeSolidBlack
();
void
setCurrentFrame
(
GstBuffer
*
buffer
);
void
updateColors
(
int
brightness
,
int
contrast
,
int
hue
,
int
saturation
);
void
updateGeometry
(
const
PaintAreas
&
areas
);
private:
MaterialType
m_materialType
;
};
#endif // VIDEONODE_H
src/VideoStreaming/gstqtvideosink/utils/bufferformat.cpp
0 → 100644
View file @
4b4f758b
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011-2012 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#include "bufferformat.h"
#include <QByteArray>
BufferFormat
BufferFormat
::
fromCaps
(
GstCaps
*
caps
)
{
BufferFormat
result
;
if
(
caps
&&
gst_video_info_from_caps
(
&
(
result
.
d
->
videoInfo
),
caps
))
{
return
result
;
}
else
{
return
BufferFormat
();
}
}
GstCaps
*
BufferFormat
::
newCaps
(
GstVideoFormat
format
,
const
QSize
&
size
,
const
Fraction
&
framerate
,
const
Fraction
&
pixelAspectRatio
)
{
GstVideoInfo
videoInfo
;
gst_video_info_init
(
&
videoInfo
);
gst_video_info_set_format
(
&
videoInfo
,
format
,
size
.
width
(),
size
.
height
());
videoInfo
.
fps_n
=
framerate
.
numerator
;
videoInfo
.
fps_d
=
framerate
.
denominator
;
videoInfo
.
par_n
=
pixelAspectRatio
.
numerator
;
videoInfo
.
par_d
=
pixelAspectRatio
.
denominator
;
return
gst_video_info_to_caps
(
&
videoInfo
);
}
int
BufferFormat
::
bytesPerLine
(
int
component
)
const
{
return
GST_VIDEO_INFO_PLANE_STRIDE
(
&
(
d
->
videoInfo
),
component
);
}
bool
operator
==
(
BufferFormat
a
,
BufferFormat
b
)
{
return
a
.
d
==
b
.
d
;
}
bool
operator
!=
(
BufferFormat
a
,
BufferFormat
b
)
{
return
a
.
d
!=
b
.
d
;
}
src/VideoStreaming/gstqtvideosink/utils/bufferformat.h
0 → 100644
View file @
4b4f758b
/*
Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
Copyright (C) 2011-2012 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef BUFFERFORMAT_H
#define BUFFERFORMAT_H
#include "utils.h"
#include <QSharedData>
#include <gst/video/video.h>
/**
* This class is a cheap way to represent Caps.
* Based on QVideoSurfaceFormat.
*/
class
BufferFormat
{
public:
static
BufferFormat
fromCaps
(
GstCaps
*
caps
);
static
GstCaps
*
newCaps
(
GstVideoFormat
format
,
const
QSize
&
size
,
const
Fraction
&
framerate
,
const
Fraction
&
pixelAspectRatio
);
inline
BufferFormat
()
:
d
(
new
Data
)
{}
inline
GstVideoInfo
videoInfo
()
const
{
return
d
->
videoInfo
;
}
inline
GstVideoFormat
videoFormat
()
const
{
return
GST_VIDEO_INFO_FORMAT
(
&
(
d
->
videoInfo
));
}
inline
GstVideoColorMatrix
colorMatrix
()
const
{
return
d
->
videoInfo
.
colorimetry
.
matrix
;
}
QSize
frameSize
()
const
{
return
QSize
(
GST_VIDEO_INFO_WIDTH
(
&
(
d
->
videoInfo
)),
GST_VIDEO_INFO_HEIGHT
(
&
(
d
->
videoInfo
)));
}
Fraction
pixelAspectRatio
()
const
{
return
Fraction
(
GST_VIDEO_INFO_PAR_N
(
&
(
d
->
videoInfo
)),
GST_VIDEO_INFO_PAR_D
(
&
(
d
->
videoInfo
)));
}
int
bytesPerLine
(
int
component
=
0
)
const
;
private:
friend
bool
operator
==
(
BufferFormat
a
,
BufferFormat
b
);
friend
bool
operator
!=
(
BufferFormat
a
,
BufferFormat
b
);
struct
Data
:
public
QSharedData
{
Data
()
{
gst_video_info_init
(
&
videoInfo
);
}
GstVideoInfo
videoInfo
;
};
QSharedDataPointer
<
Data
>
d
;
};
Q_DECLARE_METATYPE
(
GstVideoInfo
)
Q_DECLARE_METATYPE
(
GstVideoFormat
)
Q_DECLARE_METATYPE
(
GstVideoColorMatrix
)
Q_DECLARE_METATYPE
(
BufferFormat
)
#endif // BUFFERFORMAT_H
src/VideoStreaming/gstqtvideosink/utils/utils.cpp
0 → 100644
View file @
4b4f758b
/*
Copyright (C) 2011-2013 Collabora Ltd. <info@collabora.com>
Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
Copyright (C) 2013 basysKom GmbH <info@basyskom.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file
* @brief Extracted from QtGstreamer to avoid overly complex dependency
* @author Gus Grubba <mavlink@grubba.com>
*/
#include "utils.h"
void
PaintAreas
::
calculate
(
const
QRectF
&
targetArea
,
const
QSize
&
videoSize
,
const
Fraction
&
pixelAspectRatio
,
const
Fraction
&
displayAspectRatio
,
Qt
::
AspectRatioMode
aspectRatioMode
)
{
this
->
targetArea
=
targetArea
;
switch
(
aspectRatioMode
)
{
case
Qt
:
:
IgnoreAspectRatio
:
videoArea
=
targetArea
;
sourceRect
=
QRectF
(
0
,
0
,
1
,
1
);
blackArea1
=
blackArea2
=
QRectF
();
break
;
default:
{
qreal
aspectRatio
=
pixelAspectRatio
.
ratio
()
*
displayAspectRatio
.
invRatio
();
QSizeF
videoSizeAdjusted
=
QSizeF
(
videoSize
.
width
()
*
aspectRatio
,
videoSize
.
height
());
videoSizeAdjusted
.
scale
(
targetArea
.
size
(),
aspectRatioMode
);
// the area that the original video occupies, scaled
QRectF
videoRect
=
QRectF
(
QPointF
(),
videoSizeAdjusted
);
videoRect
.
moveCenter
(
targetArea
.
center
());
if
(
aspectRatioMode
==
Qt
::
KeepAspectRatio
)
{
videoArea
=
videoRect
;
sourceRect
=
QRectF
(
0
,
0
,
1
,
1
);
}
else
{
// Qt::KeepAspectRatioByExpanding
videoArea
=
targetArea
;
sourceRect
=
QRectF
(
(
videoArea
.
left
()
-
videoRect
.
left
())
/
videoRect
.
width
(),
(
videoArea
.
top
()
-
videoRect
.
top
())
/
videoRect
.
height
(),
videoArea
.
width
()
/
videoRect
.
width
(),
videoArea
.
height
()
/
videoRect
.
height
());
}
break
;
}
}
if
(
aspectRatioMode
==
Qt
::
IgnoreAspectRatio
||
aspectRatioMode
==
Qt
::
KeepAspectRatioByExpanding
||
videoArea
==
targetArea
)
{
blackArea1
=
blackArea2
=
QRectF
();
}
else
{
blackArea1
=
QRectF
(
targetArea
.
left
(),
targetArea
.
top
(),
videoArea
.
left
()
==
targetArea
.
left
()
?
targetArea
.
width
()
:
videoArea
.
left
()
-
targetArea
.
left
(),
videoArea
.
top
()
==
targetArea
.
top
()
?
targetArea
.
height
()
:
videoArea
.
top
()
-
targetArea
.
top
()
);
blackArea2
=
QRectF
(
videoArea
.
right
()
==
targetArea
.
right
()
?
targetArea
.
left
()
:
videoArea
.
right
(),
videoArea
.
bottom
()
==
targetArea
.
bottom
()
?
targetArea
.
top
()
:
videoArea
.
bottom
(),
videoArea
.
right
()
==
targetArea
.
right
()
?
targetArea
.
width
()
:
targetArea
.
right
()
-
videoArea
.
right
(),
videoArea
.
bottom
()
==
targetArea
.
bottom
()
?
targetArea
.
height
()
:
targetArea
.
bottom
()
-
videoArea
.
bottom
()
);
}
}
src/VideoStreaming/gstqtvideosink/utils/utils.h
0 → 100644
View file @
4b4f758b
/*
Copyright (C) 2011-2012 Collabora Ltd. <info@collabora.com>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 2.1
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef UTILS_H
#define UTILS_H
#include <QRectF>
#include <QSize>
#include <QMetaType>
// utilities for GST_DEBUG
#define QSIZE_FORMAT "(%d x %d)"
#define QSIZE_FORMAT_ARGS(size) \
size.width(), size.height()
#define QRECTF_FORMAT "(x: %f, y: %f, w: %f, h: %f)"
#define QRECTF_FORMAT_ARGS(rect) \
(float) rect.x(), (float) rect.y(), (float) rect.width(), (float) rect.height()
struct
Fraction
{
inline
Fraction
()
{}
inline
Fraction
(
int
numerator
,
int
denominator
)
:
numerator
(
numerator
),
denominator
(
denominator
)
{}
inline
bool
operator
==
(
const
Fraction
&
other
)
const
{
return
numerator
==
other
.
numerator
&&
denominator
==
other
.
denominator
;
}
inline
bool
operator
!=
(
const
Fraction
&
other
)
const
{
return
!
operator
==
(
other
);
}
inline
qreal
ratio
()
const
{
return
(
qreal
)
numerator
/
(
qreal
)
denominator
;
}
inline
qreal
invRatio
()
const
{
return
(
qreal
)
denominator
/
(
qreal
)
numerator
;
}
int
numerator
;
int
denominator
;
};
struct
PaintAreas
{
void
calculate
(
const
QRectF
&
targetArea
,
const
QSize
&
videoSize
,
const
Fraction
&
pixelAspectRatio
,
const
Fraction
&
displayAspectRatio
,
Qt
::
AspectRatioMode
aspectRatioMode
);
// the area that we paint on
QRectF
targetArea
;
// the area where the video should be painted on
// (subrect of or equal to targetArea)
QRectF
videoArea
;
// the part of the video rectangle that we are going to blit on the videoArea
// in the normalized (0,1] range (texture coordinates)
QRectF
sourceRect
;
// these are small subrects of targetArea that are not
// covered by videoArea to keep the video's aspect ratio
QRectF
blackArea1
;
QRectF
blackArea2
;
};
Q_DECLARE_METATYPE
(
Fraction
)
Q_DECLARE_METATYPE
(
PaintAreas
)
#endif
src/VideoStreaming/videosurface_p.h
0 → 100644
View file @
4b4f758b
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009, 2015 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/**
* @file
* @brief QGC Video Surface (Private Interface)
* @author Gus Grubba <mavlink@grubba.com>
*/
#ifndef VIDEO_SURFACE_P_H
#define VIDEO_SURFACE_P_H
#include "videosurface.h"
#include "videoitem.h"
class
VideoSurfacePrivate
{
public:
VideoSurfacePrivate
()
:
videoSink
(
NULL
)
{
}
QSet
<
VideoItem
*>
items
;
GstElement
*
videoSink
;
};
#endif // VIDEO_SURFACE_P_H
src/ui/flightdisplay/FlightDisplay.cc
View file @
4b4f758b
...
...
@@ -31,6 +31,12 @@ This file is part of the QGROUNDCONTROL project
#include <QQmlEngine>
#include <QSettings>
#if defined(QGC_GST_STREAMING)
#include <videoitem.h>
#include <videosurface.h>
#include "VideoReceiver.h"
#endif
#include "ScreenToolsController.h"
#include "FlightDisplay.h"
#include "UASManager.h"
...
...
@@ -52,6 +58,41 @@ FlightDisplay::FlightDisplay(QWidget *parent)
setMinimumHeight
(
33
*
ScreenToolsController
::
defaultFontPixelSize_s
());
#endif
setContextPropertyObject
(
"flightDisplay"
,
this
);
#if defined(QGC_GST_STREAMING)
/*
* This is the receiving end of an UDP RTP stream. The sender can be setup with this command:
*
* gst-launch-1.0 uvch264src initial-bitrate=1000000 average-bitrate=1000000 iframe-period=1000 name=src auto-start=true src.vidsrc ! \
* video/x-h264,width=1280,height=720,framerate=24/1 ! h264parse ! rtph264pay ! udpsink host=192.168.1.9 port=5000
*
* Where the main parameters are:
*
* uvch264src: Your h264 video source (the example above uses a Logitech C920 on an Raspberry PI 2+ or Odroid C1
* host=192.168.1.9 This is the IP address of QGC. You can use Avahi/Zeroconf to find QGC using the "_qgroundcontrol._udp" service.
*
* Advanced settings (you should probably read the gstreamer documentation before changing these):
*
* initial-bitrate=1000000 average-bitrate=1000000
* The bit rate to use. The greater, the better quality at the cost of higher bandwidth.
*
* width=1280,height=720,framerate=24/1
* The video resolution and frame rate. This depends on the camera used.
*
* iframe-period=1000
* Interval between iFrames. The greater the interval the lesser bandwidth at the cost of a longer time to recover from lost packets.
*
* Do not change anything else unless you know what you are doing. Any other change will require a matching change on the receiving end.
*
*/
VideoSurface
*
pSurface
=
new
VideoSurface
;
setContextPropertyObject
(
"videoDisplay"
,
pSurface
);
VideoReceiver
*
pReceiver
=
new
VideoReceiver
(
this
);
pReceiver
->
setUri
(
QLatin1Literal
(
"udp://0.0.0.0:5000"
));
pReceiver
->
setVideoSink
(
pSurface
->
videoSink
());
setContextPropertyObject
(
"videoReceiver"
,
pReceiver
);
#endif
setSource
(
QUrl
::
fromUserInput
(
"qrc:/qml/FlightDisplay.qml"
));
setVisible
(
true
);
}
...
...
src/ui/flightdisplay/FlightDisplay.qml
View file @
4b4f758b
...
...
@@ -27,7 +27,7 @@ This file is part of the QGROUNDCONTROL project
* @author Gus Grubba <mavlink@grubba.com>
*/
import
QtQuick
2.
3
import
QtQuick
2.
4
import
QtQuick
.
Controls
1.3
import
QtQuick
.
Controls
.
Styles
1.2
import
QtQuick
.
Dialogs
1.2
...
...
@@ -58,6 +58,10 @@ Item {
return
value
?
"
1
"
:
"
0
"
;
}
function
showHudInstruments
()
{
return
videoBackground
.
visible
||
mapBackground
.
visible
;
}
Connections
{
target
:
flightDisplay
onShowOptionsMenuChanged
:
{
...
...
@@ -70,6 +74,7 @@ Item {
mapBackground
.
visible
=
getBool
(
flightDisplay
.
loadSetting
(
"
showMapBackground
"
,
"
0
"
));
mapBackground
.
showWaypoints
=
getBool
(
flightDisplay
.
loadSetting
(
"
mapShowWaypoints
"
,
"
0
"
));
mapBackground
.
alwaysNorth
=
getBool
(
flightDisplay
.
loadSetting
(
"
mapAlwaysPointsNorth
"
,
"
0
"
));
videoBackground
.
visible
=
getBool
(
flightDisplay
.
loadSetting
(
"
showVideoBackground
"
,
"
0
"
));
showAttitudeIndicator
=
getBool
(
flightDisplay
.
loadSetting
(
"
showAttitudeIndicator
"
,
"
1
"
));
showPitchIndicator
=
getBool
(
flightDisplay
.
loadSetting
(
"
showPitchIndicator
"
,
"
1
"
));
showCompass
=
getBool
(
flightDisplay
.
loadSetting
(
"
showCompass
"
,
"
1
"
));
...
...
@@ -81,170 +86,29 @@ Item {
currentAltitude
.
showAltitude
=
getBool
(
flightDisplay
.
loadSetting
(
"
showCurrentAltitude
"
,
"
1
"
));
// Insert Map Type menu before separator
contextMenu
.
insertItem
(
2
,
mapBackground
.
mapMenu
);
}
// TODO: This is to replace the context menu but it is not working. Not only the buttons don't show,
// the default placement is random and mostly off screen on mobile devices.
Dialog
{
id
:
optionsDialog
modality
:
Qt
.
WindowModal
title
:
"
Flight Display Options
"
standardButtons
:
StandardButton
.
Close
|
StandardButton
.
RestoreDefaults
onReset
:
{
showPitchIndicator
=
true
;
flightDisplay
.
saveSetting
(
"
showPitchIndicator
"
,
setBool
(
showPitchIndicator
));
showAttitudeIndicator
=
true
;
flightDisplay
.
saveSetting
(
"
showAttitudeIndicator
"
,
setBool
(
showAttitudeIndicator
));
showCompass
=
true
;
flightDisplay
.
saveSetting
(
"
showCompass
"
,
setBool
(
showCompass
));
altitudeWidget
.
visible
=
true
;
flightDisplay
.
saveSetting
(
"
showAltitudeWidget
"
,
setBool
(
altitudeWidget
.
visible
));
currentAltitude
.
showAltitude
=
true
;
flightDisplay
.
saveSetting
(
"
showCurrentAltitude
"
,
setBool
(
currentAltitude
.
showAltitude
));
currentAltitude
.
showClimbRate
=
true
;
flightDisplay
.
saveSetting
(
"
showCurrentClimbRate
"
,
setBool
(
currentAltitude
.
showClimbRate
));
speedWidget
.
visible
=
true
;
flightDisplay
.
saveSetting
(
"
showSpeedWidget
"
,
setBool
(
speedWidget
.
visible
));
currentSpeed
.
showAirSpeed
=
true
;
flightDisplay
.
saveSetting
(
"
showCurrentAirSpeed
"
,
setBool
(
currentSpeed
.
showAirSpeed
));
currentSpeed
.
showGroundSpeed
=
true
;
flightDisplay
.
saveSetting
(
"
showCurrentGroundSpeed
"
,
setBool
(
currentSpeed
.
showGroundSpeed
));
mapBackground
.
visible
=
false
;
flightDisplay
.
saveSetting
(
"
showMapBackground
"
,
setBool
(
mapBackground
.
visible
));
mapBackground
.
alwaysNorth
=
false
;
flightDisplay
.
saveSetting
(
"
mapAlwaysPointsNorth
"
,
setBool
(
mapBackground
.
alwaysNorth
));
mapBackground
.
showWaypoints
=
false
flightDisplay
.
saveSetting
(
"
mapShowWaypoints
"
,
setBool
(
mapBackground
.
showWaypoints
));
}
contentItem
:
Rectangle
{
color
:
__qgcPal
.
window
implicitWidth
:
ScreenTools
.
defaultFontPixelSize
*
(
30
)
implicitHeight
:
ScreenTools
.
defaultFontPixelSize
*
(
30
)
Column
{
id
:
dialogColumn
anchors.centerIn
:
parent
spacing
:
ScreenTools
.
defaultFontPixelSize
width
:
parent
.
width
Grid
{
columns
:
2
spacing
:
ScreenTools
.
defaultFontPixelSize
*
(
0.66
)
rowSpacing
:
ScreenTools
.
defaultFontPixelSize
*
(
0.83
)
anchors.horizontalCenter
:
parent
.
horizontalCenter
QGCCheckBox
{
text
:
"
Map Background
"
checked
:
mapBackground
.
visible
onClicked
:
{
mapBackground
.
visible
=
!
mapBackground
.
visible
;
flightDisplay
.
saveSetting
(
"
showMapBackground
"
,
setBool
(
mapBackground
.
visible
));
}
}
QGCCheckBox
{
text
:
"
Map Show Waypoints
"
checked
:
mapBackground
.
showWaypoints
onClicked
:
{
mapBackground
.
showWaypoints
=
!
mapBackground
.
showWaypoints
;
flightDisplay
.
saveSetting
(
"
mapShowWaypoints
"
,
setBool
(
mapBackground
.
showWaypoints
));
}
}
QGCCheckBox
{
text
:
"
Pitch Indicator
"
checked
:
showPitchIndicator
onClicked
:
{
showPitchIndicator
=
!
showPitchIndicator
;
flightDisplay
.
saveSetting
(
"
showPitchIndicator
"
,
setBool
(
showPitchIndicator
));
}
}
QGCCheckBox
{
text
:
"
Attitude Indicator
"
checked
:
showAttitudeIndicator
onClicked
:
{
showAttitudeIndicator
=
!
showAttitudeIndicator
;
flightDisplay
.
saveSetting
(
"
showAttitudeIndicator
"
,
setBool
(
showAttitudeIndicator
));
}
}
QGCCheckBox
{
text
:
"
Compass
"
checked
:
showCompass
onClicked
:
{
showCompass
=
!
showCompass
;
flightDisplay
.
saveSetting
(
"
showCompass
"
,
setBool
(
showCompass
));
}
}
QGCCheckBox
{
text
:
"
Altitude Indicator
"
checked
:
altitudeWidget
.
visible
onClicked
:
{
altitudeWidget
.
visible
=
!
altitudeWidget
.
visible
;
flightDisplay
.
saveSetting
(
"
showAltitudeWidget
"
,
setBool
(
altitudeWidget
.
visible
));
}
}
QGCCheckBox
{
text
:
"
Current Altitude
"
checked
:
currentAltitude
.
showAltitude
onClicked
:
{
currentAltitude
.
showAltitude
=
!
currentAltitude
.
showAltitude
;
flightDisplay
.
saveSetting
(
"
showCurrentAltitude
"
,
setBool
(
currentAltitude
.
showAltitude
));
}
}
QGCCheckBox
{
text
:
"
Current Climb Rate
"
checked
:
currentAltitude
.
showClimbRate
onClicked
:
{
currentAltitude
.
showClimbRate
=
!
currentAltitude
.
showClimbRate
;
flightDisplay
.
saveSetting
(
"
showCurrentClimbRate
"
,
setBool
(
currentAltitude
.
showClimbRate
));
}
}
QGCCheckBox
{
text
:
"
Speed Indicator
"
checked
:
speedWidget
.
visible
onClicked
:
{
speedWidget
.
visible
=
!
speedWidget
.
visible
;
flightDisplay
.
saveSetting
(
"
showSpeedWidget
"
,
setBool
(
speedWidget
.
visible
));
}
}
QGCCheckBox
{
text
:
"
Current Air Speed
"
checked
:
currentSpeed
.
showAirSpeed
onClicked
:
{
currentSpeed
.
showAirSpeed
=
!
currentSpeed
.
showAirSpeed
;
flightDisplay
.
saveSetting
(
"
showCurrentAirSpeed
"
,
setBool
(
currentSpeed
.
showAirSpeed
));
}
}
QGCCheckBox
{
text
:
"
Current Ground Speed
"
checked
:
currentSpeed
.
showGroundSpeed
onClicked
:
{
currentSpeed
.
showGroundSpeed
=
!
currentSpeed
.
showGroundSpeed
;
flightDisplay
.
saveSetting
(
"
showCurrentGroundSpeed
"
,
setBool
(
currentSpeed
.
showGroundSpeed
));
}
}
}
}
// Video or Map. Not both:
if
(
mapBackground
.
visible
&&
videoBackground
.
visible
)
{
videoBackground
.
visible
=
false
;
flightDisplay
.
saveSetting
(
"
showVideoBackground
"
,
setBool
(
videoBackground
.
visible
));
}
}
Menu
{
id
:
contextMenu
ExclusiveGroup
{
id
:
backgroundDisplay
}
MenuItem
{
text
:
"
Map Background
"
checkable
:
true
checked
:
mapBackground
.
visible
exclusiveGroup
:
backgroundDisplay
onTriggered
:
{
mapBackground
.
visible
=
!
mapBackground
.
visible
;
flightDisplay
.
saveSetting
(
"
showMapBackground
"
,
setBool
(
mapBackground
.
visible
));
videoBackground
.
visible
=
mapBackground
.
visible
?
false
:
videoBackground
.
visible
;
flightDisplay
.
saveSetting
(
"
showVideoBackground
"
,
setBool
(
videoBackground
.
visible
));
}
}
...
...
@@ -252,6 +116,7 @@ Item {
text
:
"
Map Show Waypoints
"
checkable
:
true
checked
:
mapBackground
.
showWaypoints
enabled
:
mapBackground
.
visible
onTriggered
:
{
mapBackground
.
showWaypoints
=
!
mapBackground
.
showWaypoints
;
...
...
@@ -260,27 +125,34 @@ Item {
}
/*
//-- Off until Qt 5.5.x, which fixes bug in 5.4.x
MenuItem {
text: "Options Dialog"
text: "Map Always Points North"
checkable: true
checked: mapBackground.alwaysNorth
onTriggered:
{
optionsDialog.open()
mapBackground.alwaysNorth = !mapBackground.alwaysNorth;
flightDisplay.saveSetting("mapAlwaysPointsNorth", setBool(mapBackground.alwaysNorth));
}
}
*/
/*
MenuSeparator
{}
MenuItem
{
text: "
Map Always Points North
"
text
:
"
Video Background
"
checkable
:
true
checked: mapBackground.alwaysNorth
checked
:
videoBackground
.
visible
exclusiveGroup
:
backgroundDisplay
onTriggered
:
{
mapBackground.alwaysNorth = !mapBackground.alwaysNorth;
flightDisplay.saveSetting("mapAlwaysPointsNorth", setBool(mapBackground.alwaysNorth));
videoBackground
.
visible
=
!
videoBackground
.
visible
;
flightDisplay
.
saveSetting
(
"
showVideoBackground
"
,
setBool
(
videoBackground
.
visible
));
mapBackground
.
visible
=
videoBackground
.
visible
?
false
:
mapBackground
.
visible
;
flightDisplay
.
saveSetting
(
"
showMapBackground
"
,
setBool
(
mapBackground
.
visible
));
}
}
*/
MenuSeparator
{}
...
...
@@ -413,11 +285,21 @@ Item {
flightDisplay
.
saveSetting
(
"
mapAlwaysPointsNorth
"
,
setBool
(
mapBackground
.
alwaysNorth
));
mapBackground
.
showWaypoints
=
false
flightDisplay
.
saveSetting
(
"
mapShowWaypoints
"
,
setBool
(
mapBackground
.
showWaypoints
));
videoBackground
.
visible
=
false
;
flightDisplay
.
saveSetting
(
"
showVideoBackground
"
,
setBool
(
videoBackground
.
visible
));
}
}
}
QGCVideoBackground
{
id
:
videoBackground
anchors.fill
:
parent
display
:
videoDisplay
receiver
:
videoReceiver
z
:
10
}
QGCMapBackground
{
id
:
mapBackground
anchors.fill
:
parent
...
...
@@ -445,7 +327,7 @@ Item {
x
:
ScreenTools
.
defaultFontPixelSize
*
(
7.1
)
size
:
ScreenTools
.
defaultFontPixelSize
*
(
13.3
)
heading
:
isNaN
(
MavManager
.
heading
)
?
0
:
MavManager
.
heading
visible
:
mapBackground
.
visible
&&
showCompass
visible
:
showHudInstruments
()
&&
showCompass
z
:
mapBackground
.
z
+
2
onResetRequested
:
{
y
=
ScreenTools
.
defaultFontPixelSize
*
(
0.42
)
...
...
@@ -463,7 +345,7 @@ Item {
rollAngle
:
roll
pitchAngle
:
pitch
showPitch
:
showPitchIndicator
visible
:
mapBackground
.
visible
&&
showAttitudeIndicator
visible
:
showHudInstruments
()
&&
showAttitudeIndicator
anchors.right
:
root
.
right
anchors.rightMargin
:
ScreenTools
.
defaultFontPixelSize
*
(
7.1
)
z
:
mapBackground
.
z
+
2
...
...
@@ -482,14 +364,14 @@ Item {
anchors.fill
:
parent
rollAngle
:
roll
pitchAngle
:
pitch
visible
:
!
mapBackground
.
visible
visible
:
!
showHudInstruments
()
}
QGCAttitudeWidget
{
id
:
attitudeWidget
rollAngle
:
roll
pitchAngle
:
pitch
visible
:
!
mapBackground
.
visible
&&
showAttitudeIndicator
visible
:
!
showHudInstruments
()
&&
showAttitudeIndicator
width
:
ScreenTools
.
defaultFontPixelSize
*
(
21.7
)
height
:
ScreenTools
.
defaultFontPixelSize
*
(
21.7
)
z
:
20
...
...
@@ -497,7 +379,7 @@ Item {
QGCPitchWidget
{
id
:
pitchWidget
visible
:
showPitchIndicator
&&
!
mapBackground
.
visible
visible
:
showPitchIndicator
&&
!
showHudInstruments
()
anchors.verticalCenter
:
parent
.
verticalCenter
pitchAngle
:
pitch
rollAngle
:
roll
...
...
@@ -555,7 +437,7 @@ Item {
width
:
ScreenTools
.
defaultFontPixelSize
*
(
10
)
height
:
ScreenTools
.
defaultFontPixelSize
*
(
10
)
heading
:
isNaN
(
MavManager
.
heading
)
?
0
:
MavManager
.
heading
visible
:
!
mapBackground
.
visible
&&
showCompass
visible
:
!
showHudInstruments
()
&&
showCompass
z
:
70
}
...
...
src/ui/qmlcommon/QGCMapBackground.qml
View file @
4b4f758b
...
...
@@ -64,6 +64,7 @@ Item {
Menu
{
id
:
mapTypeMenu
title
:
"
Map Type...
"
enabled
:
root
.
visible
ExclusiveGroup
{
id
:
currMapType
}
function
setCurrentMap
(
mapID
)
{
for
(
var
i
=
0
;
i
<
map
.
supportedMapTypes
.
length
;
i
++
)
{
...
...
src/ui/qmlcommon/QGCVideoBackground.qml
0 → 100644
View file @
4b4f758b
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009, 2015 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/**
* @file
* @brief QGC Video Background
* @author Gus Grubba <mavlink@grubba.com>
*/
import
QtQuick
2.4
import
QtQuick
.
Controls
1.3
import
QGroundControl
.
QgcQtGStreamer
1.0
VideoItem
{
id
:
videoBackground
property
var
display
property
var
receiver
surface
:
display
onVisibleChanged
:
{
if
(
videoBackground
.
visible
)
{
receiver
.
start
();
}
else
{
receiver
.
stop
();
}
}
Component.onCompleted
:
{
if
(
videoBackground
.
visible
)
{
receiver
.
start
();
}
}
}
src/ui/qmlcommon/qmldir
View file @
4b4f758b
...
...
@@ -16,3 +16,4 @@ QGCCompassInstrument 1.0 QGCCompassInstrument.qml
QGCArtificialHorizon 1.0 QGCArtificialHorizon.qml
QGCWaypoint 1.0 QGCWaypoint.qml
QGCHudMessage 1.0 QGCHudMessage.qml
QGCVideoBackground 1.0 QGCVideoBackground.qml
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