1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39
40 #include "qgstreamervideowidget_p.h"
41 #include "qgstutils_p.h"
42
43 #include <QtCore/qcoreevent.h>
44 #include <QtCore/qdebug.h>
45 #include <QtGui/qpainter.h>
46
47 QT_BEGIN_NAMESPACE
48
49 class QGstreamerVideoWidget : public QWidget
50 {
51 public:
QGstreamerVideoWidget(QWidget * parent=0)52 QGstreamerVideoWidget(QWidget *parent = 0)
53 :QWidget(parent)
54 {
55 setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
56 QPalette palette;
57 palette.setColor(QPalette::Window, Qt::black);
58 setPalette(palette);
59 }
60
~QGstreamerVideoWidget()61 virtual ~QGstreamerVideoWidget() {}
62
sizeHint() const63 QSize sizeHint() const override
64 {
65 return m_nativeSize;
66 }
67
setNativeSize(const QSize & size)68 void setNativeSize( const QSize &size)
69 {
70 if (size != m_nativeSize) {
71 m_nativeSize = size;
72 if (size.isEmpty())
73 setMinimumSize(0,0);
74 else
75 setMinimumSize(160,120);
76
77 updateGeometry();
78 }
79 }
80
paint_helper()81 void paint_helper()
82 {
83 QPainter painter(this);
84 painter.fillRect(rect(), palette().window());
85 }
86
87 protected:
paintEvent(QPaintEvent *)88 void paintEvent(QPaintEvent *) override
89 {
90 paint_helper();
91 }
92
93 QSize m_nativeSize;
94 };
95
QGstreamerVideoWidgetControl(QObject * parent,const QByteArray & elementName)96 QGstreamerVideoWidgetControl::QGstreamerVideoWidgetControl(QObject *parent, const QByteArray &elementName)
97 : QVideoWidgetControl(parent)
98 , m_videoOverlay(this, !elementName.isEmpty() ? elementName : qgetenv("QT_GSTREAMER_WIDGET_VIDEOSINK"))
99 {
100 connect(&m_videoOverlay, &QGstreamerVideoOverlay::activeChanged,
101 this, &QGstreamerVideoWidgetControl::onOverlayActiveChanged);
102 connect(&m_videoOverlay, &QGstreamerVideoOverlay::nativeVideoSizeChanged,
103 this, &QGstreamerVideoWidgetControl::onNativeVideoSizeChanged);
104 connect(&m_videoOverlay, &QGstreamerVideoOverlay::brightnessChanged,
105 this, &QGstreamerVideoWidgetControl::brightnessChanged);
106 connect(&m_videoOverlay, &QGstreamerVideoOverlay::contrastChanged,
107 this, &QGstreamerVideoWidgetControl::contrastChanged);
108 connect(&m_videoOverlay, &QGstreamerVideoOverlay::hueChanged,
109 this, &QGstreamerVideoWidgetControl::hueChanged);
110 connect(&m_videoOverlay, &QGstreamerVideoOverlay::saturationChanged,
111 this, &QGstreamerVideoWidgetControl::saturationChanged);
112 }
113
~QGstreamerVideoWidgetControl()114 QGstreamerVideoWidgetControl::~QGstreamerVideoWidgetControl()
115 {
116 delete m_widget;
117 }
118
createVideoWidget()119 void QGstreamerVideoWidgetControl::createVideoWidget()
120 {
121 if (m_widget)
122 return;
123
124 m_widget = new QGstreamerVideoWidget;
125
126 m_widget->installEventFilter(this);
127 m_videoOverlay.setWindowHandle(m_windowId = m_widget->winId());
128 }
129
videoSink()130 GstElement *QGstreamerVideoWidgetControl::videoSink()
131 {
132 return m_videoOverlay.videoSink();
133 }
134
setVideoSink(GstElement * sink)135 void QGstreamerVideoWidgetControl::setVideoSink(GstElement *sink)
136 {
137 m_videoOverlay.setVideoSink(sink);
138 }
139
onOverlayActiveChanged()140 void QGstreamerVideoWidgetControl::onOverlayActiveChanged()
141 {
142 updateWidgetAttributes();
143 }
144
stopRenderer()145 void QGstreamerVideoWidgetControl::stopRenderer()
146 {
147 m_stopped = true;
148 updateWidgetAttributes();
149 m_widget->setNativeSize(QSize());
150 }
151
onNativeVideoSizeChanged()152 void QGstreamerVideoWidgetControl::onNativeVideoSizeChanged()
153 {
154 const QSize &size = m_videoOverlay.nativeVideoSize();
155
156 if (size.isValid())
157 m_stopped = false;
158
159 if (m_widget)
160 m_widget->setNativeSize(size);
161 }
162
eventFilter(QObject * object,QEvent * e)163 bool QGstreamerVideoWidgetControl::eventFilter(QObject *object, QEvent *e)
164 {
165 if (m_widget && object == m_widget) {
166 if (e->type() == QEvent::ParentChange || e->type() == QEvent::Show || e->type() == QEvent::WinIdChange) {
167 WId newWId = m_widget->winId();
168 if (newWId != m_windowId)
169 m_videoOverlay.setWindowHandle(m_windowId = newWId);
170 }
171
172 if (e->type() == QEvent::Paint) {
173 // Update overlay by new size if any.
174 if (QGstUtils::useOpenGL())
175 m_videoOverlay.setRenderRectangle(QRect(0, 0, m_widget->width(), m_widget->height()));
176 if (m_videoOverlay.isActive())
177 m_videoOverlay.expose(); // triggers a repaint of the last frame
178 else
179 m_widget->paint_helper(); // paints the black background
180
181 return true;
182 }
183 }
184
185 return false;
186 }
187
updateWidgetAttributes()188 void QGstreamerVideoWidgetControl::updateWidgetAttributes()
189 {
190 // When frames are being rendered (sink is active), we need the WA_PaintOnScreen attribute to
191 // be set in order to avoid flickering when the widget is repainted (for example when resized).
192 // We need to clear that flag when the the sink is inactive to allow the widget to paint its
193 // background, otherwise some garbage will be displayed.
194 if (m_videoOverlay.isActive() && !m_stopped) {
195 m_widget->setAttribute(Qt::WA_NoSystemBackground, true);
196 m_widget->setAttribute(Qt::WA_PaintOnScreen, true);
197 } else {
198 m_widget->setAttribute(Qt::WA_NoSystemBackground, false);
199 m_widget->setAttribute(Qt::WA_PaintOnScreen, false);
200 m_widget->update();
201 }
202 }
203
processSyncMessage(const QGstreamerMessage & message)204 bool QGstreamerVideoWidgetControl::processSyncMessage(const QGstreamerMessage &message)
205 {
206 return m_videoOverlay.processSyncMessage(message);
207 }
208
processBusMessage(const QGstreamerMessage & message)209 bool QGstreamerVideoWidgetControl::processBusMessage(const QGstreamerMessage &message)
210 {
211 return m_videoOverlay.processBusMessage(message);
212 }
213
videoWidget()214 QWidget *QGstreamerVideoWidgetControl::videoWidget()
215 {
216 createVideoWidget();
217 return m_widget;
218 }
219
aspectRatioMode() const220 Qt::AspectRatioMode QGstreamerVideoWidgetControl::aspectRatioMode() const
221 {
222 return m_videoOverlay.aspectRatioMode();
223 }
224
setAspectRatioMode(Qt::AspectRatioMode mode)225 void QGstreamerVideoWidgetControl::setAspectRatioMode(Qt::AspectRatioMode mode)
226 {
227 m_videoOverlay.setAspectRatioMode(mode);
228 }
229
isFullScreen() const230 bool QGstreamerVideoWidgetControl::isFullScreen() const
231 {
232 return m_fullScreen;
233 }
234
setFullScreen(bool fullScreen)235 void QGstreamerVideoWidgetControl::setFullScreen(bool fullScreen)
236 {
237 emit fullScreenChanged(m_fullScreen = fullScreen);
238 }
239
brightness() const240 int QGstreamerVideoWidgetControl::brightness() const
241 {
242 return m_videoOverlay.brightness();
243 }
244
setBrightness(int brightness)245 void QGstreamerVideoWidgetControl::setBrightness(int brightness)
246 {
247 m_videoOverlay.setBrightness(brightness);
248 }
249
contrast() const250 int QGstreamerVideoWidgetControl::contrast() const
251 {
252 return m_videoOverlay.contrast();
253 }
254
setContrast(int contrast)255 void QGstreamerVideoWidgetControl::setContrast(int contrast)
256 {
257 m_videoOverlay.setContrast(contrast);
258 }
259
hue() const260 int QGstreamerVideoWidgetControl::hue() const
261 {
262 return m_videoOverlay.hue();
263 }
264
setHue(int hue)265 void QGstreamerVideoWidgetControl::setHue(int hue)
266 {
267 m_videoOverlay.setHue(hue);
268 }
269
saturation() const270 int QGstreamerVideoWidgetControl::saturation() const
271 {
272 return m_videoOverlay.saturation();
273 }
274
setSaturation(int saturation)275 void QGstreamerVideoWidgetControl::setSaturation(int saturation)
276 {
277 m_videoOverlay.setSaturation(saturation);
278 }
279
280 QT_END_NAMESPACE
281