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