From cd3d5405225a328a0b2fa377823059723395a2ea Mon Sep 17 00:00:00 2001 From: Yoann Lopes Date: Thu, 23 Jul 2015 15:13:24 +0200 Subject: GStreamer: refactored widget and window control. Instead of always using xvimagesink as GStreamer backend for the widget and window control (works only with X11), we now try to pick a video sink that fits the current configuration. It first tries a set of known video sinks that can work with the Qt platform plugin in use. If none is available, it dynamically picks a video sink available on the system that can be used with our backend. Even if the video sink is now picked in a smarter way, xcb is still the only supported platform plugin. The reason is that it's the only Unix plugin which can provide a valid native window handle. Additional work is needed to support other plugins like wayland or directfb. Change-Id: I3843dea363d6a0b85a6cc1f2952783b743e48ac6 Reviewed-by: Christian Stromme --- src/gsttools/gsttools.pro | 6 +- src/gsttools/qgstreamervideooverlay.cpp | 429 +++++++++++++++++++++ src/gsttools/qgstreamervideowidget.cpp | 250 ++++-------- src/gsttools/qgstreamervideowindow.cpp | 266 ++----------- .../gsttools_headers/qgstreamervideooverlay_p.h | 120 ++++++ .../gsttools_headers/qgstreamervideowidget_p.h | 25 +- .../gsttools_headers/qgstreamervideowindow_p.h | 29 +- src/multimedia/gsttools_headers/qgstutils_p.h | 2 + .../gstreamer/camerabin/camerabinservice.cpp | 9 +- .../mediacapture/qgstreamercaptureservice.cpp | 9 +- .../mediaplayer/qgstreamerplayerservice.cpp | 8 +- 11 files changed, 707 insertions(+), 446 deletions(-) create mode 100644 src/gsttools/qgstreamervideooverlay.cpp create mode 100644 src/multimedia/gsttools_headers/qgstreamervideooverlay_p.h diff --git a/src/gsttools/gsttools.pro b/src/gsttools/gsttools.pro index 7c41f1ad1..a5c1d9493 100644 --- a/src/gsttools/gsttools.pro +++ b/src/gsttools/gsttools.pro @@ -53,7 +53,8 @@ PRIVATE_HEADERS += \ qgstcodecsinfo_p.h \ qgstreamervideoprobecontrol_p.h \ qgstreameraudioprobecontrol_p.h \ - qgstreamervideowindow_p.h + qgstreamervideowindow_p.h \ + qgstreamervideooverlay_p.h SOURCES += \ qgstreamerbushelper.cpp \ @@ -68,7 +69,8 @@ SOURCES += \ qgstcodecsinfo.cpp \ qgstreamervideoprobecontrol.cpp \ qgstreameraudioprobecontrol.cpp \ - qgstreamervideowindow.cpp + qgstreamervideowindow.cpp \ + qgstreamervideooverlay.cpp qtHaveModule(widgets) { QT += multimediawidgets diff --git a/src/gsttools/qgstreamervideooverlay.cpp b/src/gsttools/qgstreamervideooverlay.cpp new file mode 100644 index 000000000..1dcedbcd6 --- /dev/null +++ b/src/gsttools/qgstreamervideooverlay.cpp @@ -0,0 +1,429 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgstreamervideooverlay_p.h" + +#include +#include "qgstutils_p.h" + +#if !GST_CHECK_VERSION(1,0,0) +#include +#else +#include +#endif + +QT_BEGIN_NAMESPACE + +struct ElementMap +{ + const char *qtPlatform; + const char *gstreamerElement; +}; + +// Ordered by descending priority +static const ElementMap elementMap[] = +{ + { "xcb", "vaapisink" }, + { "xcb", "xvimagesink" }, + { "xcb", "ximagesink" } +}; + +QGstreamerVideoOverlay::QGstreamerVideoOverlay(QObject *parent, const QByteArray &elementName) + : QObject(parent) + , QGstreamerBufferProbe(QGstreamerBufferProbe::ProbeCaps) + , m_videoSink(0) + , m_isActive(false) + , m_hasForceAspectRatio(false) + , m_hasBrightness(false) + , m_hasContrast(false) + , m_hasHue(false) + , m_hasSaturation(false) + , m_hasShowPrerollFrame(false) + , m_windowId(0) + , m_aspectRatioMode(Qt::KeepAspectRatio) + , m_brightness(0) + , m_contrast(0) + , m_hue(0) + , m_saturation(0) +{ + if (!elementName.isEmpty()) + m_videoSink = gst_element_factory_make(elementName.constData(), NULL); + else + m_videoSink = findBestVideoSink(); + + if (m_videoSink) { + qt_gst_object_ref_sink(GST_OBJECT(m_videoSink)); //Take ownership + + GstPad *pad = gst_element_get_static_pad(m_videoSink, "sink"); + addProbeToPad(pad); + gst_object_unref(GST_OBJECT(pad)); + + m_hasForceAspectRatio = g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "force-aspect-ratio"); + m_hasBrightness = g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "brightness"); + m_hasContrast = g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "contrast"); + m_hasHue = g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "hue"); + m_hasSaturation = g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "saturation"); + m_hasShowPrerollFrame = g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "show-preroll-frame"); + + if (m_hasShowPrerollFrame) { + g_signal_connect(m_videoSink, "notify::show-preroll-frame", + G_CALLBACK(showPrerollFrameChanged), this); + } + } +} + +QGstreamerVideoOverlay::~QGstreamerVideoOverlay() +{ + if (m_videoSink) { + GstPad *pad = gst_element_get_static_pad(m_videoSink, "sink"); + removeProbeFromPad(pad); + gst_object_unref(GST_OBJECT(pad)); + gst_object_unref(GST_OBJECT(m_videoSink)); + } +} + +static bool qt_gst_element_is_functioning(GstElement *element) +{ + GstStateChangeReturn ret = gst_element_set_state(element, GST_STATE_READY); + if (ret == GST_STATE_CHANGE_SUCCESS) { + gst_element_set_state(element, GST_STATE_NULL); + return true; + } + + return false; +} + +GstElement *QGstreamerVideoOverlay::findBestVideoSink() const +{ + GstElement *choice = 0; + QString platform = QGuiApplication::platformName(); + + // We need a native window ID to use the GstVideoOverlay interface. + // Bail out if the Qt platform plugin in use cannot provide a sensible WId. + if (platform != QLatin1String("xcb")) + return 0; + + // First, try some known video sinks, depending on the Qt platform plugin in use. + for (quint32 i = 0; i < (sizeof(elementMap) / sizeof(ElementMap)); ++i) { + if (platform == QLatin1String(elementMap[i].qtPlatform) + && (choice = gst_element_factory_make(elementMap[i].gstreamerElement, NULL))) { + + if (qt_gst_element_is_functioning(choice)) + return choice; + + gst_object_unref(choice); + choice = 0; + } + } + + // If none of the known video sinks are available, try to find one that implements the + // GstVideoOverlay interface and has autoplugging rank. + GList *list = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_SINK | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO, + GST_RANK_MARGINAL); + + for (GList *item = list; item != NULL; item = item->next) { + GstElementFactory *f = GST_ELEMENT_FACTORY(item->data); + + if (!gst_element_factory_has_interface(f, QT_GSTREAMER_VIDEOOVERLAY_INTERFACE_NAME)) + continue; + + if (GstElement *el = gst_element_factory_create(f, NULL)) { + if (qt_gst_element_is_functioning(el)) { + choice = el; + break; + } + + gst_object_unref(el); + } + } + + gst_plugin_feature_list_free(list); + + return choice; +} + +GstElement *QGstreamerVideoOverlay::videoSink() const +{ + return m_videoSink; +} + +QSize QGstreamerVideoOverlay::nativeVideoSize() const +{ + return m_nativeVideoSize; +} + +void QGstreamerVideoOverlay::setWindowHandle(WId id) +{ + m_windowId = id; + + if (isActive()) + setWindowHandle_helper(id); +} + +void QGstreamerVideoOverlay::setWindowHandle_helper(WId id) +{ +#if GST_CHECK_VERSION(1,0,0) + if (m_videoSink && GST_IS_VIDEO_OVERLAY(m_videoSink)) { + gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(m_videoSink), id); +#else + if (m_videoSink && GST_IS_X_OVERLAY(m_videoSink)) { +# if GST_CHECK_VERSION(0,10,31) + gst_x_overlay_set_window_handle(GST_X_OVERLAY(m_videoSink), id); +# else + gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(m_videoSink), id); +# endif +#endif + + // Properties need to be reset when changing the winId. + setAspectRatioMode(m_aspectRatioMode); + setBrightness(m_brightness); + setContrast(m_contrast); + setHue(m_hue); + setSaturation(m_saturation); + } +} + +void QGstreamerVideoOverlay::expose() +{ + if (!isActive()) + return; + +#if !GST_CHECK_VERSION(1,0,0) + if (m_videoSink && GST_IS_X_OVERLAY(m_videoSink)) + gst_x_overlay_expose(GST_X_OVERLAY(m_videoSink)); +#else + if (m_videoSink && GST_IS_VIDEO_OVERLAY(m_videoSink)) { + gst_video_overlay_expose(GST_VIDEO_OVERLAY(m_videoSink)); + } +#endif +} + +void QGstreamerVideoOverlay::setRenderRectangle(const QRect &rect) +{ + int x = -1; + int y = -1; + int w = -1; + int h = -1; + + if (!rect.isEmpty()) { + x = rect.x(); + y = rect.y(); + w = rect.width(); + h = rect.height(); + } + +#if !GST_CHECK_VERSION(1,0,0) + if (m_videoSink && GST_IS_X_OVERLAY(m_videoSink)) + gst_x_overlay_set_render_rectangle(GST_X_OVERLAY(m_videoSink), x, y , w , h); +#else + if (m_videoSink && GST_IS_VIDEO_OVERLAY(m_videoSink)) + gst_video_overlay_set_render_rectangle(GST_VIDEO_OVERLAY(m_videoSink), x, y, w, h); +#endif +} + +bool QGstreamerVideoOverlay::processSyncMessage(const QGstreamerMessage &message) +{ + GstMessage* gm = message.rawMessage(); + +#if !GST_CHECK_VERSION(1,0,0) + if (gm && (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_ELEMENT) && + gst_structure_has_name(gm->structure, "prepare-xwindow-id")) { +#else + if (gm && (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_ELEMENT) && + gst_structure_has_name(gst_message_get_structure(gm), "prepare-window-handle")) { +#endif + setWindowHandle_helper(m_windowId); + return true; + } + + return false; +} + +bool QGstreamerVideoOverlay::processBusMessage(const QGstreamerMessage &message) +{ + GstMessage* gm = message.rawMessage(); + + if (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_STATE_CHANGED && + GST_MESSAGE_SRC(gm) == GST_OBJECT_CAST(m_videoSink)) { + + updateIsActive(); + } + + return false; +} + +void QGstreamerVideoOverlay::probeCaps(GstCaps *caps) +{ + QSize size = QGstUtils::capsCorrectedResolution(caps); + if (size != m_nativeVideoSize) { + m_nativeVideoSize = size; + emit nativeVideoSizeChanged(); + } +} + +bool QGstreamerVideoOverlay::isActive() const +{ + return m_isActive; +} + +void QGstreamerVideoOverlay::updateIsActive() +{ + if (!m_videoSink) + return; + + GstState state = GST_STATE(m_videoSink); + gboolean showPreroll = true; + + if (m_hasShowPrerollFrame) + g_object_get(G_OBJECT(m_videoSink), "show-preroll-frame", &showPreroll, NULL); + + bool newIsActive = (state == GST_STATE_PLAYING || (state == GST_STATE_PAUSED && showPreroll)); + + if (newIsActive != m_isActive) { + m_isActive = newIsActive; + emit activeChanged(); + } +} + +void QGstreamerVideoOverlay::showPrerollFrameChanged(GObject *, GParamSpec *, QGstreamerVideoOverlay *overlay) +{ + overlay->updateIsActive(); +} + +Qt::AspectRatioMode QGstreamerVideoOverlay::aspectRatioMode() const +{ + Qt::AspectRatioMode mode = Qt::KeepAspectRatio; + + if (m_hasForceAspectRatio) { + gboolean forceAR = false; + g_object_get(G_OBJECT(m_videoSink), "force-aspect-ratio", &forceAR, NULL); + if (!forceAR) + mode = Qt::IgnoreAspectRatio; + } + + return mode; +} + +void QGstreamerVideoOverlay::setAspectRatioMode(Qt::AspectRatioMode mode) +{ + if (m_hasForceAspectRatio) { + g_object_set(G_OBJECT(m_videoSink), + "force-aspect-ratio", + (mode == Qt::KeepAspectRatio), + (const char*)NULL); + } + + m_aspectRatioMode = mode; +} + +int QGstreamerVideoOverlay::brightness() const +{ + int brightness = 0; + + if (m_hasBrightness) + g_object_get(G_OBJECT(m_videoSink), "brightness", &brightness, NULL); + + return brightness / 10; +} + +void QGstreamerVideoOverlay::setBrightness(int brightness) +{ + if (m_hasBrightness) { + g_object_set(G_OBJECT(m_videoSink), "brightness", brightness * 10, NULL); + emit brightnessChanged(brightness); + } + + m_brightness = brightness; +} + +int QGstreamerVideoOverlay::contrast() const +{ + int contrast = 0; + + if (m_hasContrast) + g_object_get(G_OBJECT(m_videoSink), "contrast", &contrast, NULL); + + return contrast / 10; +} + +void QGstreamerVideoOverlay::setContrast(int contrast) +{ + if (m_hasContrast) { + g_object_set(G_OBJECT(m_videoSink), "contrast", contrast * 10, NULL); + emit contrastChanged(contrast); + } + + m_contrast = contrast; +} + +int QGstreamerVideoOverlay::hue() const +{ + int hue = 0; + + if (m_hasHue) + g_object_get(G_OBJECT(m_videoSink), "hue", &hue, NULL); + + return hue / 10; +} + +void QGstreamerVideoOverlay::setHue(int hue) +{ + if (m_hasHue) { + g_object_set(G_OBJECT(m_videoSink), "hue", hue * 10, NULL); + emit hueChanged(hue); + } + + m_hue = hue; +} + +int QGstreamerVideoOverlay::saturation() const +{ + int saturation = 0; + + if (m_hasSaturation) + g_object_get(G_OBJECT(m_videoSink), "saturation", &saturation, NULL); + + return saturation / 10; +} + +void QGstreamerVideoOverlay::setSaturation(int saturation) +{ + if (m_hasSaturation) { + g_object_set(G_OBJECT(m_videoSink), "saturation", saturation * 10, NULL); + emit saturationChanged(saturation); + } + + m_saturation = saturation; +} + +QT_END_NAMESPACE diff --git a/src/gsttools/qgstreamervideowidget.cpp b/src/gsttools/qgstreamervideowidget.cpp index 6e65b3065..2d273c652 100644 --- a/src/gsttools/qgstreamervideowidget.cpp +++ b/src/gsttools/qgstreamervideowidget.cpp @@ -32,22 +32,11 @@ ****************************************************************************/ #include "qgstreamervideowidget_p.h" -#include #include #include -#include #include -#include - -#if !GST_CHECK_VERSION(1,0,0) -#include -#include -#else -#include -#endif - QT_BEGIN_NAMESPACE class QGstreamerVideoWidget : public QWidget @@ -82,167 +71,133 @@ public: } } -protected: - void paintEvent(QPaintEvent *) + void paint_helper() { QPainter painter(this); painter.fillRect(rect(), palette().background()); } +protected: + void paintEvent(QPaintEvent *) + { + paint_helper(); + } + QSize m_nativeSize; }; -QGstreamerVideoWidgetControl::QGstreamerVideoWidgetControl(QObject *parent) +QGstreamerVideoWidgetControl::QGstreamerVideoWidgetControl(QObject *parent, const QByteArray &elementName) : QVideoWidgetControl(parent) - , m_videoSink(0) + , m_videoOverlay(this, !elementName.isEmpty() ? elementName : qgetenv("QT_GSTREAMER_WIDGET_VIDEOSINK")) , m_widget(0) + , m_stopped(false) + , m_windowId(0) , m_fullScreen(false) { - // The QWidget needs to have a native X window handle to be able to use xvimagesink. - // Bail out if Qt is not using xcb (the control will then be ignored by the plugin) - if (QGuiApplication::platformName().compare(QLatin1String("xcb"), Qt::CaseInsensitive) == 0) - m_videoSink = gst_element_factory_make ("xvimagesink", NULL); - - if (m_videoSink) { - // Check if the xv sink is usable - if (gst_element_set_state(m_videoSink, GST_STATE_READY) != GST_STATE_CHANGE_SUCCESS) { - gst_object_unref(GST_OBJECT(m_videoSink)); - m_videoSink = 0; - } else { - gst_element_set_state(m_videoSink, GST_STATE_NULL); - g_object_set(G_OBJECT(m_videoSink), "force-aspect-ratio", 1, (const char*)NULL); - qt_gst_object_ref_sink(GST_OBJECT (m_videoSink)); //Take ownership - } - } + connect(&m_videoOverlay, &QGstreamerVideoOverlay::activeChanged, + this, &QGstreamerVideoWidgetControl::onOverlayActiveChanged); + connect(&m_videoOverlay, &QGstreamerVideoOverlay::nativeVideoSizeChanged, + this, &QGstreamerVideoWidgetControl::onNativeVideoSizeChanged); + connect(&m_videoOverlay, &QGstreamerVideoOverlay::brightnessChanged, + this, &QGstreamerVideoWidgetControl::brightnessChanged); + connect(&m_videoOverlay, &QGstreamerVideoOverlay::contrastChanged, + this, &QGstreamerVideoWidgetControl::contrastChanged); + connect(&m_videoOverlay, &QGstreamerVideoOverlay::hueChanged, + this, &QGstreamerVideoWidgetControl::hueChanged); + connect(&m_videoOverlay, &QGstreamerVideoOverlay::saturationChanged, + this, &QGstreamerVideoWidgetControl::saturationChanged); } QGstreamerVideoWidgetControl::~QGstreamerVideoWidgetControl() { - if (m_videoSink) - gst_object_unref(GST_OBJECT(m_videoSink)); - delete m_widget; } void QGstreamerVideoWidgetControl::createVideoWidget() { - if (!m_videoSink || m_widget) + if (m_widget) return; m_widget = new QGstreamerVideoWidget; m_widget->installEventFilter(this); - m_windowId = m_widget->winId(); + m_videoOverlay.setWindowHandle(m_windowId = m_widget->winId()); } GstElement *QGstreamerVideoWidgetControl::videoSink() { - return m_videoSink; + return m_videoOverlay.videoSink(); } -bool QGstreamerVideoWidgetControl::eventFilter(QObject *object, QEvent *e) +void QGstreamerVideoWidgetControl::onOverlayActiveChanged() { - if (m_widget && object == m_widget) { - if (e->type() == QEvent::ParentChange || e->type() == QEvent::Show) { - WId newWId = m_widget->winId(); - if (newWId != m_windowId) { - m_windowId = newWId; - setOverlay(); - } - } - - if (e->type() == QEvent::Show) { - // Setting these values ensures smooth resizing since it - // will prevent the system from clearing the background - m_widget->setAttribute(Qt::WA_NoSystemBackground, true); - } else if (e->type() == QEvent::Resize) { - // This is a workaround for missing background repaints - // when reducing window size - windowExposed(); - } - } + updateWidgetAttributes(); +} - return false; +void QGstreamerVideoWidgetControl::stopRenderer() +{ + m_stopped = true; + updateWidgetAttributes(); + m_widget->setNativeSize(QSize()); } -bool QGstreamerVideoWidgetControl::processSyncMessage(const QGstreamerMessage &message) +void QGstreamerVideoWidgetControl::onNativeVideoSizeChanged() { - GstMessage* gm = message.rawMessage(); - -#if !GST_CHECK_VERSION(1,0,0) - if (gm && (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_ELEMENT) && - gst_structure_has_name(gm->structure, "prepare-xwindow-id")) { -#else - if (gm && (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_ELEMENT) && - gst_structure_has_name(gst_message_get_structure(gm), "prepare-window-handle")) { -#endif - setOverlay(); - QMetaObject::invokeMethod(this, "updateNativeVideoSize", Qt::QueuedConnection); - return true; - } + const QSize &size = m_videoOverlay.nativeVideoSize(); - return false; + if (size.isValid()) + m_stopped = false; + + if (m_widget) + m_widget->setNativeSize(size); } -bool QGstreamerVideoWidgetControl::processBusMessage(const QGstreamerMessage &message) +bool QGstreamerVideoWidgetControl::eventFilter(QObject *object, QEvent *e) { - GstMessage* gm = message.rawMessage(); + if (m_widget && object == m_widget) { + if (e->type() == QEvent::ParentChange || e->type() == QEvent::Show || e->type() == QEvent::WinIdChange) { + WId newWId = m_widget->winId(); + if (newWId != m_windowId) + m_videoOverlay.setWindowHandle(m_windowId = newWId); + } - if (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_STATE_CHANGED && - GST_MESSAGE_SRC(gm) == GST_OBJECT_CAST(m_videoSink)) { - GstState oldState; - GstState newState; - gst_message_parse_state_changed(gm, &oldState, &newState, 0); + if (e->type() == QEvent::Paint) { + if (m_videoOverlay.isActive()) + m_videoOverlay.expose(); // triggers a repaint of the last frame + else + m_widget->paint_helper(); // paints the black background - if (oldState == GST_STATE_READY && newState == GST_STATE_PAUSED) - updateNativeVideoSize(); + return true; + } } return false; } -void QGstreamerVideoWidgetControl::setOverlay() +void QGstreamerVideoWidgetControl::updateWidgetAttributes() { -#if !GST_CHECK_VERSION(1,0,0) - if (m_videoSink && GST_IS_X_OVERLAY(m_videoSink)) { - gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(m_videoSink), m_windowId); - } -#else - if (m_videoSink && GST_IS_VIDEO_OVERLAY(m_videoSink)) { - gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(m_videoSink), m_windowId); + // When frames are being rendered (sink is active), we need the WA_PaintOnScreen attribute to + // be set in order to avoid flickering when the widget is repainted (for example when resized). + // We need to clear that flag when the the sink is inactive to allow the widget to paint its + // background, otherwise some garbage will be displayed. + if (m_videoOverlay.isActive() && !m_stopped) { + m_widget->setAttribute(Qt::WA_NoSystemBackground, true); + m_widget->setAttribute(Qt::WA_PaintOnScreen, true); + } else { + m_widget->setAttribute(Qt::WA_NoSystemBackground, false); + m_widget->setAttribute(Qt::WA_PaintOnScreen, false); + m_widget->update(); } -#endif } -void QGstreamerVideoWidgetControl::updateNativeVideoSize() +bool QGstreamerVideoWidgetControl::processSyncMessage(const QGstreamerMessage &message) { - if (m_videoSink) { - //find video native size to update video widget size hint - GstPad *pad = gst_element_get_static_pad(m_videoSink, "sink"); - GstCaps *caps = qt_gst_pad_get_current_caps(pad); - - gst_object_unref(GST_OBJECT(pad)); - - if (caps) { - m_widget->setNativeSize(QGstUtils::capsCorrectedResolution(caps)); - gst_caps_unref(caps); - } - } else { - if (m_widget) - m_widget->setNativeSize(QSize()); - } + return m_videoOverlay.processSyncMessage(message); } - -void QGstreamerVideoWidgetControl::windowExposed() +bool QGstreamerVideoWidgetControl::processBusMessage(const QGstreamerMessage &message) { -#if !GST_CHECK_VERSION(1,0,0) - if (m_videoSink && GST_IS_X_OVERLAY(m_videoSink)) - gst_x_overlay_expose(GST_X_OVERLAY(m_videoSink)); -#else - if (m_videoSink && GST_IS_VIDEO_OVERLAY(m_videoSink)) - gst_video_overlay_expose(GST_VIDEO_OVERLAY(m_videoSink)); -#endif + return m_videoOverlay.processBusMessage(message); } QWidget *QGstreamerVideoWidgetControl::videoWidget() @@ -253,19 +208,12 @@ QWidget *QGstreamerVideoWidgetControl::videoWidget() Qt::AspectRatioMode QGstreamerVideoWidgetControl::aspectRatioMode() const { - return m_aspectRatioMode; + return m_videoOverlay.aspectRatioMode(); } void QGstreamerVideoWidgetControl::setAspectRatioMode(Qt::AspectRatioMode mode) { - if (m_videoSink) { - g_object_set(G_OBJECT(m_videoSink), - "force-aspect-ratio", - (mode == Qt::KeepAspectRatio), - (const char*)NULL); - } - - m_aspectRatioMode = mode; + m_videoOverlay.setAspectRatioMode(mode); } bool QGstreamerVideoWidgetControl::isFullScreen() const @@ -280,78 +228,42 @@ void QGstreamerVideoWidgetControl::setFullScreen(bool fullScreen) int QGstreamerVideoWidgetControl::brightness() const { - int brightness = 0; - - if (m_videoSink && g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "brightness")) - g_object_get(G_OBJECT(m_videoSink), "brightness", &brightness, NULL); - - return brightness / 10; + return m_videoOverlay.brightness(); } void QGstreamerVideoWidgetControl::setBrightness(int brightness) { - if (m_videoSink && g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "brightness")) { - g_object_set(G_OBJECT(m_videoSink), "brightness", brightness * 10, NULL); - - emit brightnessChanged(brightness); - } + m_videoOverlay.setBrightness(brightness); } int QGstreamerVideoWidgetControl::contrast() const { - int contrast = 0; - - if (m_videoSink && g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "contrast")) - g_object_get(G_OBJECT(m_videoSink), "contrast", &contrast, NULL); - - return contrast / 10; + return m_videoOverlay.contrast(); } void QGstreamerVideoWidgetControl::setContrast(int contrast) { - if (m_videoSink && g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "contrast")) { - g_object_set(G_OBJECT(m_videoSink), "contrast", contrast * 10, NULL); - - emit contrastChanged(contrast); - } + m_videoOverlay.setContrast(contrast); } int QGstreamerVideoWidgetControl::hue() const { - int hue = 0; - - if (m_videoSink && g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "hue")) - g_object_get(G_OBJECT(m_videoSink), "hue", &hue, NULL); - - return hue / 10; + return m_videoOverlay.hue(); } void QGstreamerVideoWidgetControl::setHue(int hue) { - if (m_videoSink && g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "hue")) { - g_object_set(G_OBJECT(m_videoSink), "hue", hue * 10, NULL); - - emit hueChanged(hue); - } + m_videoOverlay.setHue(hue); } int QGstreamerVideoWidgetControl::saturation() const { - int saturation = 0; - - if (m_videoSink && g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "saturation")) - g_object_get(G_OBJECT(m_videoSink), "saturation", &saturation, NULL); - - return saturation / 10; + return m_videoOverlay.saturation(); } void QGstreamerVideoWidgetControl::setSaturation(int saturation) { - if (m_videoSink && g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "saturation")) { - g_object_set(G_OBJECT(m_videoSink), "saturation", saturation * 10, NULL); - - emit saturationChanged(saturation); - } + m_videoOverlay.setSaturation(saturation); } QT_END_NAMESPACE diff --git a/src/gsttools/qgstreamervideowindow.cpp b/src/gsttools/qgstreamervideowindow.cpp index ee25acc48..befac0dda 100644 --- a/src/gsttools/qgstreamervideowindow.cpp +++ b/src/gsttools/qgstreamervideowindow.cpp @@ -35,52 +35,33 @@ #include #include -#include -#include - -#if !GST_CHECK_VERSION(1,0,0) -#include -#include -#else -#include -#endif - - -QGstreamerVideoWindow::QGstreamerVideoWindow(QObject *parent, const char *elementName) +QGstreamerVideoWindow::QGstreamerVideoWindow(QObject *parent, const QByteArray &elementName) : QVideoWindowControl(parent) - , QGstreamerBufferProbe(QGstreamerBufferProbe::ProbeCaps) - , m_videoSink(0) + , m_videoOverlay(this, !elementName.isEmpty() ? elementName : qgetenv("QT_GSTREAMER_WINDOW_VIDEOSINK")) , m_windowId(0) - , m_aspectRatioMode(Qt::KeepAspectRatio) , m_fullScreen(false) , m_colorKey(QColor::Invalid) { - if (elementName) { - m_videoSink = gst_element_factory_make(elementName, NULL); - } else if (QGuiApplication::platformName().compare(QLatin1String("xcb"), Qt::CaseInsensitive) == 0) { - // We need a native X window handle to be able to use xvimagesink. - // Bail out if Qt is not using xcb (the control will then be ignored by the plugin) - m_videoSink = gst_element_factory_make("xvimagesink", NULL); - } - - if (m_videoSink) { - qt_gst_object_ref_sink(GST_OBJECT(m_videoSink)); //Take ownership - - GstPad *pad = gst_element_get_static_pad(m_videoSink, "sink"); - addProbeToPad(pad); - gst_object_unref(GST_OBJECT(pad)); - } + connect(&m_videoOverlay, &QGstreamerVideoOverlay::nativeVideoSizeChanged, + this, &QGstreamerVideoWindow::nativeSizeChanged); + connect(&m_videoOverlay, &QGstreamerVideoOverlay::brightnessChanged, + this, &QGstreamerVideoWindow::brightnessChanged); + connect(&m_videoOverlay, &QGstreamerVideoOverlay::contrastChanged, + this, &QGstreamerVideoWindow::contrastChanged); + connect(&m_videoOverlay, &QGstreamerVideoOverlay::hueChanged, + this, &QGstreamerVideoWindow::hueChanged); + connect(&m_videoOverlay, &QGstreamerVideoOverlay::saturationChanged, + this, &QGstreamerVideoWindow::saturationChanged); } QGstreamerVideoWindow::~QGstreamerVideoWindow() { - if (m_videoSink) { - GstPad *pad = gst_element_get_static_pad(m_videoSink,"sink"); - removeProbeFromPad(pad); - gst_object_unref(GST_OBJECT(pad)); - gst_object_unref(GST_OBJECT(m_videoSink)); - } +} + +GstElement *QGstreamerVideoWindow::videoSink() +{ + return m_videoOverlay.videoSink(); } WId QGstreamerVideoWindow::winId() const @@ -94,17 +75,8 @@ void QGstreamerVideoWindow::setWinId(WId id) return; WId oldId = m_windowId; + m_videoOverlay.setWindowHandle(m_windowId = id); - m_windowId = id; -#if GST_CHECK_VERSION(1,0,0) - if (m_videoSink && GST_IS_VIDEO_OVERLAY(m_videoSink)) { - gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(m_videoSink), m_windowId); - } -#else - if (m_videoSink && GST_IS_X_OVERLAY(m_videoSink)) { - gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(m_videoSink), m_windowId); - } -#endif if (!oldId) emit readyChanged(true); @@ -114,28 +86,12 @@ void QGstreamerVideoWindow::setWinId(WId id) bool QGstreamerVideoWindow::processSyncMessage(const QGstreamerMessage &message) { - GstMessage* gm = message.rawMessage(); -#if GST_CHECK_VERSION(1,0,0) - const GstStructure *s = gst_message_get_structure(gm); - if ((GST_MESSAGE_TYPE(gm) == GST_MESSAGE_ELEMENT) && - gst_structure_has_name(s, "prepare-window-handle") && - m_videoSink && GST_IS_VIDEO_OVERLAY(m_videoSink)) { - - gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(m_videoSink), m_windowId); - - return true; - } -#else - if ((GST_MESSAGE_TYPE(gm) == GST_MESSAGE_ELEMENT) && - gst_structure_has_name(gm->structure, "prepare-xwindow-id") && - m_videoSink && GST_IS_X_OVERLAY(m_videoSink)) { - - gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(m_videoSink), m_windowId); + return m_videoOverlay.processSyncMessage(message); +} - return true; - } -#endif - return false; +bool QGstreamerVideoWindow::processBusMessage(const QGstreamerMessage &message) +{ + return m_videoOverlay.processBusMessage(message); } QRect QGstreamerVideoWindow::displayRect() const @@ -145,188 +101,63 @@ QRect QGstreamerVideoWindow::displayRect() const void QGstreamerVideoWindow::setDisplayRect(const QRect &rect) { - m_displayRect = rect; -#if GST_CHECK_VERSION(1,0,0) - if (m_videoSink && GST_IS_VIDEO_OVERLAY(m_videoSink)) { - if (m_displayRect.isEmpty()) - gst_video_overlay_set_render_rectangle(GST_VIDEO_OVERLAY(m_videoSink), -1, -1, -1, -1); - else - gst_video_overlay_set_render_rectangle(GST_VIDEO_OVERLAY(m_videoSink), - m_displayRect.x(), - m_displayRect.y(), - m_displayRect.width(), - m_displayRect.height()); - repaint(); - } -#else - if (m_videoSink && GST_IS_X_OVERLAY(m_videoSink)) { -#if GST_VERSION_MICRO >= 29 - if (m_displayRect.isEmpty()) - gst_x_overlay_set_render_rectangle(GST_X_OVERLAY(m_videoSink), -1, -1, -1, -1); - else - gst_x_overlay_set_render_rectangle(GST_X_OVERLAY(m_videoSink), - m_displayRect.x(), - m_displayRect.y(), - m_displayRect.width(), - m_displayRect.height()); - repaint(); -#endif - } -#endif + m_videoOverlay.setRenderRectangle(m_displayRect = rect); + repaint(); } Qt::AspectRatioMode QGstreamerVideoWindow::aspectRatioMode() const { - return m_aspectRatioMode; + return m_videoOverlay.aspectRatioMode(); } void QGstreamerVideoWindow::setAspectRatioMode(Qt::AspectRatioMode mode) { - m_aspectRatioMode = mode; - - if (m_videoSink) { - g_object_set(G_OBJECT(m_videoSink), - "force-aspect-ratio", - (m_aspectRatioMode == Qt::KeepAspectRatio), - (const char*)NULL); - } + m_videoOverlay.setAspectRatioMode(mode); } void QGstreamerVideoWindow::repaint() { -#if GST_CHECK_VERSION(1,0,0) - if (m_videoSink && GST_IS_VIDEO_OVERLAY(m_videoSink)) { - //don't call gst_x_overlay_expose if the sink is in null state - GstState state = GST_STATE_NULL; - GstStateChangeReturn res = gst_element_get_state(m_videoSink, &state, NULL, 1000000); - if (res != GST_STATE_CHANGE_FAILURE && state != GST_STATE_NULL) { - gst_video_overlay_expose(GST_VIDEO_OVERLAY(m_videoSink)); - } - } -#else - if (m_videoSink && GST_IS_X_OVERLAY(m_videoSink)) { - //don't call gst_x_overlay_expose if the sink is in null state - GstState state = GST_STATE_NULL; - GstStateChangeReturn res = gst_element_get_state(m_videoSink, &state, NULL, 1000000); - if (res != GST_STATE_CHANGE_FAILURE && state != GST_STATE_NULL) { - gst_x_overlay_expose(GST_X_OVERLAY(m_videoSink)); - } - } -#endif -} - -QColor QGstreamerVideoWindow::colorKey() const -{ - if (!m_colorKey.isValid()) { - gint colorkey = 0; - if (m_videoSink && g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "colorkey")) - g_object_get(G_OBJECT(m_videoSink), "colorkey", &colorkey, NULL); - - if (colorkey > 0) - m_colorKey.setRgb(colorkey); - } - - return m_colorKey; -} - -void QGstreamerVideoWindow::setColorKey(const QColor &color) -{ - m_colorKey = color; - - if (m_videoSink && g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "colorkey")) - g_object_set(G_OBJECT(m_videoSink), "colorkey", color.rgba(), NULL); -} - -bool QGstreamerVideoWindow::autopaintColorKey() const -{ - bool enabled = true; - - if (m_videoSink && g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "autopaint-colorkey")) - g_object_get(G_OBJECT(m_videoSink), "autopaint-colorkey", &enabled, NULL); - - return enabled; -} - -void QGstreamerVideoWindow::setAutopaintColorKey(bool enabled) -{ - if (m_videoSink && g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "autopaint-colorkey")) - g_object_set(G_OBJECT(m_videoSink), "autopaint-colorkey", enabled, NULL); + m_videoOverlay.expose(); } int QGstreamerVideoWindow::brightness() const { - int brightness = 0; - - if (m_videoSink && g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "brightness")) - g_object_get(G_OBJECT(m_videoSink), "brightness", &brightness, NULL); - - return brightness / 10; + return m_videoOverlay.brightness(); } void QGstreamerVideoWindow::setBrightness(int brightness) { - if (m_videoSink && g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "brightness")) { - g_object_set(G_OBJECT(m_videoSink), "brightness", brightness * 10, NULL); - - emit brightnessChanged(brightness); - } + m_videoOverlay.setBrightness(brightness); } int QGstreamerVideoWindow::contrast() const { - int contrast = 0; - - if (m_videoSink && g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "contrast")) - g_object_get(G_OBJECT(m_videoSink), "contrast", &contrast, NULL); - - return contrast / 10; + return m_videoOverlay.contrast(); } void QGstreamerVideoWindow::setContrast(int contrast) { - if (m_videoSink && g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "contrast")) { - g_object_set(G_OBJECT(m_videoSink), "contrast", contrast * 10, NULL); - - emit contrastChanged(contrast); - } + m_videoOverlay.setContrast(contrast); } int QGstreamerVideoWindow::hue() const { - int hue = 0; - - if (m_videoSink && g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "hue")) - g_object_get(G_OBJECT(m_videoSink), "hue", &hue, NULL); - - return hue / 10; + return m_videoOverlay.hue(); } void QGstreamerVideoWindow::setHue(int hue) { - if (m_videoSink && g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "hue")) { - g_object_set(G_OBJECT(m_videoSink), "hue", hue * 10, NULL); - - emit hueChanged(hue); - } + m_videoOverlay.setHue(hue); } int QGstreamerVideoWindow::saturation() const { - int saturation = 0; - - if (m_videoSink && g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "saturation")) - g_object_get(G_OBJECT(m_videoSink), "saturation", &saturation, NULL); - - return saturation / 10; + return m_videoOverlay.saturation(); } void QGstreamerVideoWindow::setSaturation(int saturation) { - if (m_videoSink && g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "saturation")) { - g_object_set(G_OBJECT(m_videoSink), "saturation", saturation * 10, NULL); - - emit saturationChanged(saturation); - } + m_videoOverlay.setSaturation(saturation); } bool QGstreamerVideoWindow::isFullScreen() const @@ -341,28 +172,5 @@ void QGstreamerVideoWindow::setFullScreen(bool fullScreen) QSize QGstreamerVideoWindow::nativeSize() const { - return m_nativeSize; -} - -void QGstreamerVideoWindow::probeCaps(GstCaps *caps) -{ - QSize resolution = QGstUtils::capsCorrectedResolution(caps); - QMetaObject::invokeMethod( - this, - "updateNativeVideoSize", - Qt::QueuedConnection, - Q_ARG(QSize, resolution)); -} - -void QGstreamerVideoWindow::updateNativeVideoSize(const QSize &size) -{ - if (m_nativeSize != size) { - m_nativeSize = size; - emit nativeSizeChanged(); - } -} - -GstElement *QGstreamerVideoWindow::videoSink() -{ - return m_videoSink; + return m_videoOverlay.nativeVideoSize(); } diff --git a/src/multimedia/gsttools_headers/qgstreamervideooverlay_p.h b/src/multimedia/gsttools_headers/qgstreamervideooverlay_p.h new file mode 100644 index 000000000..e18a1b5ca --- /dev/null +++ b/src/multimedia/gsttools_headers/qgstreamervideooverlay_p.h @@ -0,0 +1,120 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGSTREAMERVIDEOOVERLAY_P_H +#define QGSTREAMERVIDEOOVERLAY_P_H + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QGstreamerVideoOverlay + : public QObject + , public QGstreamerSyncMessageFilter + , public QGstreamerBusMessageFilter + , private QGstreamerBufferProbe +{ + Q_OBJECT + Q_INTERFACES(QGstreamerSyncMessageFilter QGstreamerBusMessageFilter) +public: + explicit QGstreamerVideoOverlay(QObject *parent = 0, const QByteArray &elementName = QByteArray()); + virtual ~QGstreamerVideoOverlay(); + + GstElement *videoSink() const; + QSize nativeVideoSize() const; + + void setWindowHandle(WId id); + void expose(); + void setRenderRectangle(const QRect &rect); + + bool isActive() const; + + Qt::AspectRatioMode aspectRatioMode() const; + void setAspectRatioMode(Qt::AspectRatioMode mode); + + 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); + + bool processSyncMessage(const QGstreamerMessage &message); + bool processBusMessage(const QGstreamerMessage &message); + +Q_SIGNALS: + void nativeVideoSizeChanged(); + void activeChanged(); + void brightnessChanged(int brightness); + void contrastChanged(int contrast); + void hueChanged(int hue); + void saturationChanged(int saturation); + +private: + GstElement *findBestVideoSink() const; + void setWindowHandle_helper(WId id); + void updateIsActive(); + void probeCaps(GstCaps *caps); + static void showPrerollFrameChanged(GObject *, GParamSpec *, QGstreamerVideoOverlay *); + + GstElement *m_videoSink; + QSize m_nativeVideoSize; + bool m_isActive; + + bool m_hasForceAspectRatio; + bool m_hasBrightness; + bool m_hasContrast; + bool m_hasHue; + bool m_hasSaturation; + bool m_hasShowPrerollFrame; + + WId m_windowId; + Qt::AspectRatioMode m_aspectRatioMode; + int m_brightness; + int m_contrast; + int m_hue; + int m_saturation; +}; + +QT_END_NAMESPACE + +#endif // QGSTREAMERVIDEOOVERLAY_P_H + diff --git a/src/multimedia/gsttools_headers/qgstreamervideowidget_p.h b/src/multimedia/gsttools_headers/qgstreamervideowidget_p.h index 32a143c07..4526a8ac9 100644 --- a/src/multimedia/gsttools_headers/qgstreamervideowidget_p.h +++ b/src/multimedia/gsttools_headers/qgstreamervideowidget_p.h @@ -38,6 +38,7 @@ #include "qgstreamervideorendererinterface_p.h" #include +#include QT_BEGIN_NAMESPACE @@ -52,13 +53,15 @@ class QGstreamerVideoWidgetControl Q_OBJECT Q_INTERFACES(QGstreamerVideoRendererInterface QGstreamerSyncMessageFilter QGstreamerBusMessageFilter) public: - QGstreamerVideoWidgetControl(QObject *parent = 0); + explicit QGstreamerVideoWidgetControl(QObject *parent = 0, const QByteArray &elementName = QByteArray()); virtual ~QGstreamerVideoWidgetControl(); GstElement *videoSink(); QWidget *videoWidget(); + void stopRenderer(); + Qt::AspectRatioMode aspectRatioMode() const; void setAspectRatioMode(Qt::AspectRatioMode mode); @@ -77,27 +80,27 @@ public: int saturation() const; void setSaturation(int saturation); - void setOverlay(); - bool eventFilter(QObject *object, QEvent *event); - bool processSyncMessage(const QGstreamerMessage &message); - bool processBusMessage(const QGstreamerMessage &message); - -public slots: - void updateNativeVideoSize(); signals: void sinkChanged(); void readyChanged(bool); +private Q_SLOTS: + void onOverlayActiveChanged(); + void onNativeVideoSizeChanged(); + private: void createVideoWidget(); - void windowExposed(); + void updateWidgetAttributes(); + + bool processSyncMessage(const QGstreamerMessage &message); + bool processBusMessage(const QGstreamerMessage &message); - GstElement *m_videoSink; + QGstreamerVideoOverlay m_videoOverlay; QGstreamerVideoWidget *m_widget; + bool m_stopped; WId m_windowId; - Qt::AspectRatioMode m_aspectRatioMode; bool m_fullScreen; }; diff --git a/src/multimedia/gsttools_headers/qgstreamervideowindow_p.h b/src/multimedia/gsttools_headers/qgstreamervideowindow_p.h index 5111fc884..8884aa2c0 100644 --- a/src/multimedia/gsttools_headers/qgstreamervideowindow_p.h +++ b/src/multimedia/gsttools_headers/qgstreamervideowindow_p.h @@ -38,23 +38,22 @@ #include "qgstreamervideorendererinterface_p.h" #include -#include +#include #include QT_BEGIN_NAMESPACE class QAbstractVideoSurface; -class QGstreamerVideoWindow : public QVideoWindowControl, +class QGstreamerVideoWindow : + public QVideoWindowControl, public QGstreamerVideoRendererInterface, public QGstreamerSyncMessageFilter, - private QGstreamerBufferProbe + public QGstreamerBusMessageFilter { Q_OBJECT - Q_INTERFACES(QGstreamerVideoRendererInterface QGstreamerSyncMessageFilter) - Q_PROPERTY(QColor colorKey READ colorKey WRITE setColorKey) - Q_PROPERTY(bool autopaintColorKey READ autopaintColorKey WRITE setAutopaintColorKey) + Q_INTERFACES(QGstreamerVideoRendererInterface QGstreamerSyncMessageFilter QGstreamerBusMessageFilter) public: - QGstreamerVideoWindow(QObject *parent = 0, const char *elementName = 0); + explicit QGstreamerVideoWindow(QObject *parent = 0, const QByteArray &elementName = QByteArray()); ~QGstreamerVideoWindow(); WId winId() const; @@ -71,12 +70,6 @@ public: Qt::AspectRatioMode aspectRatioMode() const; void setAspectRatioMode(Qt::AspectRatioMode mode); - QColor colorKey() const; - void setColorKey(const QColor &); - - bool autopaintColorKey() const; - void setAutopaintColorKey(bool); - void repaint(); int brightness() const; @@ -96,24 +89,18 @@ public: GstElement *videoSink(); bool processSyncMessage(const QGstreamerMessage &message); + bool processBusMessage(const QGstreamerMessage &message); bool isReady() const { return m_windowId != 0; } signals: void sinkChanged(); void readyChanged(bool); -private slots: - void updateNativeVideoSize(const QSize &size); - private: - void probeCaps(GstCaps *caps); - - GstElement *m_videoSink; + QGstreamerVideoOverlay m_videoOverlay; WId m_windowId; - Qt::AspectRatioMode m_aspectRatioMode; QRect m_displayRect; bool m_fullScreen; - QSize m_nativeSize; mutable QColor m_colorKey; }; diff --git a/src/multimedia/gsttools_headers/qgstutils_p.h b/src/multimedia/gsttools_headers/qgstutils_p.h index 78b9db3df..31fb85847 100644 --- a/src/multimedia/gsttools_headers/qgstutils_p.h +++ b/src/multimedia/gsttools_headers/qgstutils_p.h @@ -61,11 +61,13 @@ # define QT_GSTREAMER_CAMERABIN_ELEMENT_NAME "camerabin" # define QT_GSTREAMER_COLORCONVERSION_ELEMENT_NAME "videoconvert" # define QT_GSTREAMER_RAW_AUDIO_MIME "audio/x-raw" +# define QT_GSTREAMER_VIDEOOVERLAY_INTERFACE_NAME "GstVideoOverlay" #else # define QT_GSTREAMER_PLAYBIN_ELEMENT_NAME "playbin2" # define QT_GSTREAMER_CAMERABIN_ELEMENT_NAME "camerabin2" # define QT_GSTREAMER_COLORCONVERSION_ELEMENT_NAME "ffmpegcolorspace" # define QT_GSTREAMER_RAW_AUDIO_MIME "audio/x-raw-int" +# define QT_GSTREAMER_VIDEOOVERLAY_INTERFACE_NAME "GstXOverlay" #endif QT_BEGIN_NAMESPACE diff --git a/src/plugins/gstreamer/camerabin/camerabinservice.cpp b/src/plugins/gstreamer/camerabin/camerabinservice.cpp index 25fd44817..a22301e2e 100644 --- a/src/plugins/gstreamer/camerabin/camerabinservice.cpp +++ b/src/plugins/gstreamer/camerabin/camerabinservice.cpp @@ -124,8 +124,8 @@ CameraBinService::CameraBinService(GstElementFactory *sourceFactory, QObject *pa #else m_videoWindow = new QGstreamerVideoWindow(this); #endif - // If the GStreamer sink element is not available (xvimagesink), don't provide - // the video window control since it won't work anyway. + // If the GStreamer video sink is not available, don't provide the video window control since + // it won't work anyway. if (!m_videoWindow->videoSink()) { delete m_videoWindow; m_videoWindow = 0; @@ -133,9 +133,8 @@ CameraBinService::CameraBinService(GstElementFactory *sourceFactory, QObject *pa #if defined(HAVE_WIDGETS) m_videoWidgetControl = new QGstreamerVideoWidgetControl(this); - // If the GStreamer sink element is not available (xvimagesink or ximagesink), don't provide - // the video widget control since it won't work anyway. - // QVideoWidget will fall back to QVideoRendererControl in that case. + // If the GStreamer video sink is not available, don't provide the video widget control since + // it won't work anyway. QVideoWidget will fall back to QVideoRendererControl in that case. if (!m_videoWidgetControl->videoSink()) { delete m_videoWidgetControl; m_videoWidgetControl = 0; diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.cpp b/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.cpp index bf9b474d6..a29c1d26f 100644 --- a/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.cpp +++ b/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.cpp @@ -102,8 +102,8 @@ QGstreamerCaptureService::QGstreamerCaptureService(const QString &service, QObje m_videoRenderer = new QGstreamerVideoRenderer(this); m_videoWindow = new QGstreamerVideoWindow(this); - // If the GStreamer sink element is not available (xvimagesink), don't provide - // the video window control since it won't work anyway. + // If the GStreamer video sink is not available, don't provide the video window control since + // it won't work anyway. if (!m_videoWindow->videoSink()) { delete m_videoWindow; m_videoWindow = 0; @@ -112,9 +112,8 @@ QGstreamerCaptureService::QGstreamerCaptureService(const QString &service, QObje #if defined(HAVE_WIDGETS) m_videoWidgetControl = new QGstreamerVideoWidgetControl(this); - // If the GStreamer sink element is not available (xvimagesink or ximagesink), don't provide - // the video widget control since it won't work anyway. - // QVideoWidget will fall back to QVideoRendererControl in that case. + // If the GStreamer video sink is not available, don't provide the video widget control since + // it won't work anyway. QVideoWidget will fall back to QVideoRendererControl in that case. if (!m_videoWidgetControl->videoSink()) { delete m_videoWidgetControl; m_videoWidgetControl = 0; diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayerservice.cpp b/src/plugins/gstreamer/mediaplayer/qgstreamerplayerservice.cpp index 48cbd937a..69250c0b3 100644 --- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayerservice.cpp +++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayerservice.cpp @@ -99,8 +99,8 @@ QGstreamerPlayerService::QGstreamerPlayerService(QObject *parent): #else m_videoWindow = new QGstreamerVideoWindow(this); #endif - // If the GStreamer sink element is not available (xvimagesink), don't provide - // the video window control since it won't work anyway. + // If the GStreamer video sink is not available, don't provide the video window control since + // it won't work anyway. if (!m_videoWindow->videoSink()) { delete m_videoWindow; m_videoWindow = 0; @@ -109,8 +109,8 @@ QGstreamerPlayerService::QGstreamerPlayerService(QObject *parent): #if defined(HAVE_WIDGETS) m_videoWidget = new QGstreamerVideoWidgetControl(this); - // If the GStreamer sink element is not available (xvimagesink or ximagesink), don't provide - // the video widget control since it won't work anyway. + // If the GStreamer video sink is not available, don't provide the video widget control since + // it won't work anyway. // QVideoWidget will fall back to QVideoRendererControl in that case. if (!m_videoWidget->videoSink()) { delete m_videoWidget; -- cgit v1.2.3