[oe] [meta-qt5][PATCH 6/8] qtmultimedia: Update the GStreamer 1.0 support patch
Otavio Salvador
otavio at ossystems.com.br
Sun Feb 8 21:34:38 UTC 2015
This updates the patch which adds support for GStreamer 1.0 to the one
merged in the 5.5 development branch. For instance it fixes a color
mismatch in one of our devices.
Signed-off-by: Otavio Salvador <otavio at ossystems.com.br>
---
recipes-qt/qt5/qtmultimedia.inc | 2 +-
.../qtmultimedia/0001-GStreamer-port-to-1.0.patch | 7648 ++++++++++++++++++++
...1-Initial-porting-effort-to-GStreamer-1.0.patch | 2369 ------
3 files changed, 7649 insertions(+), 2370 deletions(-)
create mode 100644 recipes-qt/qt5/qtmultimedia/0001-GStreamer-port-to-1.0.patch
delete mode 100644 recipes-qt/qt5/qtmultimedia/0001-Initial-porting-effort-to-GStreamer-1.0.patch
diff --git a/recipes-qt/qt5/qtmultimedia.inc b/recipes-qt/qt5/qtmultimedia.inc
index c4792e6..77ba159 100644
--- a/recipes-qt/qt5/qtmultimedia.inc
+++ b/recipes-qt/qt5/qtmultimedia.inc
@@ -21,7 +21,7 @@ EXTRA_QMAKEVARS_PRE += "${@bb.utils.contains('PACKAGECONFIG', 'gstreamer010', 'G
EXTRA_QMAKEVARS_PRE += "${@bb.utils.contains_any('PACKAGECONFIG', 'gstreamer gstreamer010', '', 'CONFIG+=done_config_streamer', d)}"
SRC_URI += "\
- file://0001-Initial-porting-effort-to-GStreamer-1.0.patch \
+ file://0001-GStreamer-port-to-1.0.patch \
"
LICENSE += "| GPL-2.0"
diff --git a/recipes-qt/qt5/qtmultimedia/0001-GStreamer-port-to-1.0.patch b/recipes-qt/qt5/qtmultimedia/0001-GStreamer-port-to-1.0.patch
new file mode 100644
index 0000000..65281a6
--- /dev/null
+++ b/recipes-qt/qt5/qtmultimedia/0001-GStreamer-port-to-1.0.patch
@@ -0,0 +1,7648 @@
+From: Yoann Lopes <yoann.lopes at theqtcompany.com>
+Subject: [PATCH] GStreamer: port to 1.0.
+
+0.10 is still used by default.
+To enable GStreamer 1.0, pass GST_VERSION=1.0 to qmake
+for qtmultimedia.pro.
+
+Contributions from:
+Andrew den Exter <andrew.den.exter at qinetic.com.au>
+Ilya Smelykh <ilya at videoexpertsgroup.com>
+Jim Hodapp <jim.hodapp at canonical.com>
+Sergio Schvezov <sergio.schvezov at canonical.com>
+
+Upstream-Status: Backport [5.5]
+
+Change-Id: I72a46d1170a8794a149bdb5e20767afcc5b7587c
+Reviewed-by: Andrew den Exter <andrew.den.exter at qinetic.com.au>
+---
+ config.tests/gstreamer/gstreamer.pro | 11 +-
+ config.tests/gstreamer_appsrc/gstreamer_appsrc.pro | 13 +-
+ .../gstreamer_encodingprofiles.pro | 13 +-
+ .../gstreamer_photography.pro | 15 +-
+ .../declarative-camera/declarative-camera.qml | 2 +-
+ qtmultimedia.pro | 26 +-
+ src/gsttools/gsttools.pro | 72 +-
+ src/gsttools/qgstappsrc.cpp | 29 +-
+ src/gsttools/qgstcodecsinfo.cpp | 8 +-
+ src/gsttools/qgstreameraudioprobecontrol.cpp | 47 +-
+ src/gsttools/qgstreamerbufferprobe.cpp | 174 +++++
+ src/gsttools/qgstreamerbushelper.cpp | 8 +
+ src/gsttools/qgstreamermirtexturerenderer.cpp | 351 +++++++++
+ src/gsttools/qgstreamervideoprobecontrol.cpp | 58 +-
+ src/gsttools/qgstreamervideorenderer.cpp | 3 +-
+ src/gsttools/qgstreamervideowidget.cpp | 29 +-
+ src/gsttools/qgstreamervideowindow.cpp | 105 ++-
+ src/gsttools/qgstutils.cpp | 785 ++++++++++++++++++++-
+ src/gsttools/qgstvideobuffer.cpp | 70 +-
+ src/gsttools/qgstvideorendererplugin.cpp | 53 ++
+ src/gsttools/qgstvideorenderersink.cpp | 605 ++++++++++++++++
+ src/gsttools/qvideosurfacegstsink.cpp | 232 +-----
+ src/multimedia/gsttools_headers/qgstappsrc_p.h | 3 +
+ .../qgstreameraudioprobecontrol_p.h | 13 +-
+ .../gsttools_headers/qgstreamerbufferprobe_p.h | 86 +++
+ .../qgstreamermirtexturerenderer_p.h | 102 +++
+ .../qgstreamervideoprobecontrol_p.h | 23 +-
+ .../gsttools_headers/qgstreamervideowindow_p.h | 9 +-
+ src/multimedia/gsttools_headers/qgstutils_p.h | 55 +-
+ .../gsttools_headers/qgstvideobuffer_p.h | 23 +-
+ .../gsttools_headers/qgstvideorendererplugin_p.h | 111 +++
+ .../gsttools_headers/qgstvideorenderersink_p.h | 183 +++++
+ .../gsttools_headers/qvideosurfacegstsink_p.h | 19 +-
+ src/multimedia/multimedia.pro | 2 +
+ .../qgstreameraudiodecoderserviceplugin.cpp | 89 +--
+ .../audiodecoder/qgstreameraudiodecodersession.cpp | 36 +-
+ .../audiodecoder/qgstreameraudiodecodersession.h | 2 +-
+ src/plugins/gstreamer/camerabin/camerabin.pro | 2 +-
+ .../gstreamer/camerabin/camerabincontainer.cpp | 2 +-
+ .../gstreamer/camerabin/camerabincontrol.cpp | 7 +-
+ .../gstreamer/camerabin/camerabinexposure.cpp | 8 +-
+ src/plugins/gstreamer/camerabin/camerabinflash.cpp | 8 +-
+ src/plugins/gstreamer/camerabin/camerabinfocus.cpp | 15 +-
+ .../gstreamer/camerabin/camerabinimagecapture.cpp | 146 ++--
+ .../gstreamer/camerabin/camerabinimagecapture.h | 50 +-
+ .../gstreamer/camerabin/camerabinimageencoder.cpp | 1 -
+ .../camerabin/camerabinimageprocessing.cpp | 8 +-
+ .../gstreamer/camerabin/camerabinimageprocessing.h | 7 +-
+ .../gstreamer/camerabin/camerabinmetadata.cpp | 5 +-
+ .../gstreamer/camerabin/camerabinrecorder.cpp | 9 +-
+ .../gstreamer/camerabin/camerabinservice.cpp | 7 +-
+ .../gstreamer/camerabin/camerabinsession.cpp | 339 ++++-----
+ src/plugins/gstreamer/common.pri | 22 +-
+ src/plugins/gstreamer/gstreamer.pro | 4 +-
+ .../gstreamer/mediacapture/mediacapturecamera.json | 2 +-
+ .../mediacapture/qgstreameraudioencode.cpp | 3 +-
+ .../mediacapture/qgstreamercaptureservice.cpp | 58 +-
+ .../mediacapture/qgstreamercaptureservice.h | 3 +
+ .../qgstreamercaptureserviceplugin.cpp | 90 +--
+ .../mediacapture/qgstreamercapturesession.cpp | 285 +++-----
+ .../mediacapture/qgstreamercapturesession.h | 19 +-
+ .../mediacapture/qgstreamervideoencode.cpp | 39 +-
+ src/plugins/gstreamer/mediaplayer/mediaplayer.pro | 1 -
+ .../mediaplayer/qgstreamerplayercontrol.cpp | 1 -
+ .../mediaplayer/qgstreamerplayerservice.cpp | 65 +-
+ .../mediaplayer/qgstreamerplayerservice.h | 5 +
+ .../mediaplayer/qgstreamerplayerserviceplugin.cpp | 88 +--
+ .../mediaplayer/qgstreamerplayersession.cpp | 238 ++++---
+ .../mediaplayer/qgstreamerplayersession.h | 19 +-
+ .../qcamerabackend/tst_qcamerabackend.cpp | 10 +-
+ .../tst_qmediaplayerbackend.cpp | 4 +-
+ 71 files changed, 3661 insertions(+), 1374 deletions(-)
+ create mode 100644 src/gsttools/qgstreamerbufferprobe.cpp
+ create mode 100644 src/gsttools/qgstreamermirtexturerenderer.cpp
+ create mode 100644 src/gsttools/qgstvideorendererplugin.cpp
+ create mode 100644 src/gsttools/qgstvideorenderersink.cpp
+ create mode 100644 src/multimedia/gsttools_headers/qgstreamerbufferprobe_p.h
+ create mode 100644 src/multimedia/gsttools_headers/qgstreamermirtexturerenderer_p.h
+ create mode 100644 src/multimedia/gsttools_headers/qgstvideorendererplugin_p.h
+ create mode 100644 src/multimedia/gsttools_headers/qgstvideorenderersink_p.h
+
+diff --git a/config.tests/gstreamer/gstreamer.pro b/config.tests/gstreamer/gstreamer.pro
+index 02a7e34..6b9843a 100644
+--- a/config.tests/gstreamer/gstreamer.pro
++++ b/config.tests/gstreamer/gstreamer.pro
+@@ -3,11 +3,10 @@ SOURCES += main.cpp
+ CONFIG += link_pkgconfig
+
+ PKGCONFIG += \
+- gstreamer-0.10 \
+- gstreamer-base-0.10 \
+- gstreamer-interfaces-0.10 \
+- gstreamer-audio-0.10 \
+- gstreamer-video-0.10 \
+- gstreamer-pbutils-0.10
++ gstreamer-$$GST_VERSION \
++ gstreamer-base-$$GST_VERSION \
++ gstreamer-audio-$$GST_VERSION \
++ gstreamer-video-$$GST_VERSION \
++ gstreamer-pbutils-$$GST_VERSION
+
+
+diff --git a/config.tests/gstreamer_appsrc/gstreamer_appsrc.pro b/config.tests/gstreamer_appsrc/gstreamer_appsrc.pro
+index 9f61703..0f3ca2b 100644
+--- a/config.tests/gstreamer_appsrc/gstreamer_appsrc.pro
++++ b/config.tests/gstreamer_appsrc/gstreamer_appsrc.pro
+@@ -3,11 +3,8 @@ SOURCES += main.cpp
+ CONFIG += link_pkgconfig
+
+ PKGCONFIG += \
+- gstreamer-0.10 \
+- gstreamer-base-0.10 \
+- gstreamer-interfaces-0.10 \
+- gstreamer-audio-0.10 \
+- gstreamer-video-0.10 \
+- gstreamer-app-0.10
+-
+-
++ gstreamer-$$GST_VERSION \
++ gstreamer-base-$$GST_VERSION \
++ gstreamer-audio-$$GST_VERSION \
++ gstreamer-video-$$GST_VERSION \
++ gstreamer-pbutils-$$GST_VERSION
+diff --git a/config.tests/gstreamer_encodingprofiles/gstreamer_encodingprofiles.pro b/config.tests/gstreamer_encodingprofiles/gstreamer_encodingprofiles.pro
+index 7e8a9e7..fad40b0 100644
+--- a/config.tests/gstreamer_encodingprofiles/gstreamer_encodingprofiles.pro
++++ b/config.tests/gstreamer_encodingprofiles/gstreamer_encodingprofiles.pro
+@@ -2,11 +2,10 @@ SOURCES += main.cpp
+
+ CONFIG += link_pkgconfig
+
+-PKGCONFIG += \
+- gstreamer-0.10 \
+- gstreamer-base-0.10 \
+- gstreamer-interfaces-0.10 \
+- gstreamer-audio-0.10 \
+- gstreamer-video-0.10 \
+- gstreamer-pbutils-0.10
+
++PKGCONFIG += \
++ gstreamer-$$GST_VERSION \
++ gstreamer-base-$$GST_VERSION \
++ gstreamer-audio-$$GST_VERSION \
++ gstreamer-video-$$GST_VERSION \
++ gstreamer-pbutils-$$GST_VERSION
+diff --git a/config.tests/gstreamer_photography/gstreamer_photography.pro b/config.tests/gstreamer_photography/gstreamer_photography.pro
+index 6b530cb..975991f 100644
+--- a/config.tests/gstreamer_photography/gstreamer_photography.pro
++++ b/config.tests/gstreamer_photography/gstreamer_photography.pro
+@@ -3,12 +3,11 @@ SOURCES += main.cpp
+ CONFIG += link_pkgconfig
+
+ PKGCONFIG += \
+- gstreamer-0.10 \
+- gstreamer-base-0.10 \
+- gstreamer-interfaces-0.10 \
+- gstreamer-audio-0.10 \
+- gstreamer-video-0.10 \
+- gstreamer-pbutils-0.10
+-
+-LIBS += -lgstphotography-0.10
++ gstreamer-$$GST_VERSION \
++ gstreamer-base-$$GST_VERSION \
++ gstreamer-audio-$$GST_VERSION \
++ gstreamer-video-$$GST_VERSION \
++ gstreamer-pbutils-$$GST_VERSION
++
++LIBS += -lgstphotography-$$GST_VERSION
+
+diff --git a/examples/multimedia/declarative-camera/declarative-camera.qml b/examples/multimedia/declarative-camera/declarative-camera.qml
+index 751b38d..251df34 100644
+--- a/examples/multimedia/declarative-camera/declarative-camera.qml
++++ b/examples/multimedia/declarative-camera/declarative-camera.qml
+@@ -96,7 +96,7 @@ Rectangle {
+
+ videoRecorder {
+ resolution: "640x480"
+- frameRate: 15
++ frameRate: 30
+ }
+ }
+
+diff --git a/qtmultimedia.pro b/qtmultimedia.pro
+index 3cec526..84f2548 100644
+--- a/qtmultimedia.pro
++++ b/qtmultimedia.pro
+@@ -17,11 +17,27 @@ win32 {
+ } else {
+ qtCompileTest(alsa)
+ qtCompileTest(pulseaudio)
+- qtCompileTest(gstreamer) {
+- qtCompileTest(gstreamer_photography)
+- qtCompileTest(gstreamer_encodingprofiles)
+- qtCompileTest(gstreamer_appsrc)
+- qtCompileTest(linux_v4l)
++ !done_config_gstreamer {
++ gstver=0.10
++ !isEmpty(GST_VERSION): gstver=$$GST_VERSION
++ cache(GST_VERSION, set, gstver);
++ qtCompileTest(gstreamer) {
++ qtCompileTest(gstreamer_photography)
++ qtCompileTest(gstreamer_encodingprofiles)
++ qtCompileTest(gstreamer_appsrc)
++ qtCompileTest(linux_v4l)
++ } else {
++ gstver=1.0
++ cache(GST_VERSION, set, gstver);
++ # Force a re-run of the test
++ CONFIG -= done_config_gstreamer
++ qtCompileTest(gstreamer) {
++ qtCompileTest(gstreamer_photography)
++ qtCompileTest(gstreamer_encodingprofiles)
++ qtCompileTest(gstreamer_appsrc)
++ qtCompileTest(linux_v4l)
++ }
++ }
+ }
+ qtCompileTest(resourcepolicy)
+ qtCompileTest(gpu_vivante)
+diff --git a/src/gsttools/gsttools.pro b/src/gsttools/gsttools.pro
+index 7c809a7..7c41f1a 100644
+--- a/src/gsttools/gsttools.pro
++++ b/src/gsttools/gsttools.pro
+@@ -2,6 +2,7 @@ TEMPLATE = lib
+
+ TARGET = qgsttools_p
+ QPRO_PWD = $$PWD
++
+ QT = core-private multimedia-private gui-private
+
+ !static:DEFINES += QT_MAKEDLL
+@@ -15,15 +16,17 @@ LIBS_PRIVATE += \
+
+ CONFIG += link_pkgconfig
+
+-PKGCONFIG_PRIVATE += \
+- gstreamer-0.10 \
+- gstreamer-base-0.10 \
+- gstreamer-interfaces-0.10 \
+- gstreamer-audio-0.10 \
+- gstreamer-video-0.10 \
+- gstreamer-pbutils-0.10
++PKGCONFIG += \
++ gstreamer-$$GST_VERSION \
++ gstreamer-base-$$GST_VERSION \
++ gstreamer-audio-$$GST_VERSION \
++ gstreamer-video-$$GST_VERSION \
++ gstreamer-pbutils-$$GST_VERSION
+
+-maemo*: PKGCONFIG_PRIVATE +=gstreamer-plugins-bad-0.10
++equals(GST_VERSION,"0.10") {
++ PKGCONFIG_PRIVATE += gstreamer-interfaces-0.10
++ maemo*: PKGCONFIG_PRIVATE +=gstreamer-plugins-bad-0.10
++}
+
+ config_resourcepolicy {
+ DEFINES += HAVE_RESOURCE_POLICY
+@@ -33,38 +36,36 @@ config_resourcepolicy {
+ # Header files must go inside source directory of a module
+ # to be installed by syncqt.
+ INCLUDEPATH += ../multimedia/gsttools_headers/
++INCLUDEPATH += ../plugins/gstreamer/mediaplayer/
+ VPATH += ../multimedia/gsttools_headers/
+
+ PRIVATE_HEADERS += \
+- qgstbufferpoolinterface_p.h \
+ qgstreamerbushelper_p.h \
+ qgstreamermessage_p.h \
+ qgstutils_p.h \
+ qgstvideobuffer_p.h \
+ qvideosurfacegstsink_p.h \
++ qgstreamerbufferprobe_p.h \
+ qgstreamervideorendererinterface_p.h \
+ qgstreameraudioinputselector_p.h \
+ qgstreamervideorenderer_p.h \
+ qgstreamervideoinputdevicecontrol_p.h \
+- gstvideoconnector_p.h \
+ qgstcodecsinfo_p.h \
+ qgstreamervideoprobecontrol_p.h \
+ qgstreameraudioprobecontrol_p.h \
+ qgstreamervideowindow_p.h
+
+ SOURCES += \
+- qgstbufferpoolinterface.cpp \
+ qgstreamerbushelper.cpp \
+ qgstreamermessage.cpp \
+ qgstutils.cpp \
+ qgstvideobuffer.cpp \
+- qvideosurfacegstsink.cpp \
++ qgstreamerbufferprobe.cpp \
+ qgstreamervideorendererinterface.cpp \
+ qgstreameraudioinputselector.cpp \
+ qgstreamervideorenderer.cpp \
+ qgstreamervideoinputdevicecontrol.cpp \
+ qgstcodecsinfo.cpp \
+- gstvideoconnector.c \
+ qgstreamervideoprobecontrol.cpp \
+ qgstreameraudioprobecontrol.cpp \
+ qgstreamervideowindow.cpp
+@@ -79,25 +80,54 @@ qtHaveModule(widgets) {
+ qgstreamervideowidget.cpp
+ }
+
+-maemo6 {
+- PKGCONFIG_PRIVATE += qmsystem2
++equals(GST_VERSION,"0.10") {
++ PRIVATE_HEADERS += \
++ qgstbufferpoolinterface_p.h \
++ gstvideoconnector_p.h \
++
++ SOURCES += \
++ qgstbufferpoolinterface.cpp \
++ qvideosurfacegstsink.cpp \
++ gstvideoconnector.c
++
++ maemo6 {
++ PKGCONFIG_PRIVATE += qmsystem2
++
++ contains(QT_CONFIG, opengles2):qtHaveModule(widgets) {
++ PRIVATE_HEADERS += qgstreamergltexturerenderer_p.h
++ SOURCES += qgstreamergltexturerenderer.cpp
++ QT += opengl
++ LIBS_PRIVATE += -lEGL -lgstmeegointerfaces-0.10
++ }
++ }
++} else {
++ PRIVATE_HEADERS += \
++ qgstvideorendererplugin_p.h \
++ qgstvideorenderersink_p.h
++
++ SOURCES += \
++ qgstvideorendererplugin.cpp \
++ qgstvideorenderersink.cpp
++}
+
++mir: {
+ contains(QT_CONFIG, opengles2):qtHaveModule(widgets) {
+- PRIVATE_HEADERS += qgstreamergltexturerenderer_p.h
+- SOURCES += qgstreamergltexturerenderer.cpp
+- QT += opengl
+- LIBS_PRIVATE += -lEGL -lgstmeegointerfaces-0.10
++ PRIVATE_HEADERS += qgstreamermirtexturerenderer_p.h
++ SOURCES += qgstreamermirtexturerenderer.cpp
++ QT += opengl quick
++ LIBS += -lEGL
+ }
++ DEFINES += HAVE_MIR
+ }
+
+ config_gstreamer_appsrc {
+- PKGCONFIG_PRIVATE += gstreamer-app-0.10
++ PKGCONFIG_PRIVATE += gstreamer-app-$$GST_VERSION
+ PRIVATE_HEADERS += qgstappsrc_p.h
+ SOURCES += qgstappsrc.cpp
+
+ DEFINES += HAVE_GST_APPSRC
+
+- LIBS_PRIVATE += -lgstapp-0.10
++ LIBS_PRIVATE += -lgstapp-$$GST_VERSION
+ }
+
+ config_linux_v4l: DEFINES += USE_V4L
+diff --git a/src/gsttools/qgstappsrc.cpp b/src/gsttools/qgstappsrc.cpp
+index 148366b..57eaacd 100644
+--- a/src/gsttools/qgstappsrc.cpp
++++ b/src/gsttools/qgstappsrc.cpp
+@@ -147,23 +147,44 @@ void QGstAppSrc::pushDataToAppSrc()
+ size = qMin(m_stream->bytesAvailable(), (qint64)m_dataRequestSize);
+
+ if (size) {
+- void *data = g_malloc(size);
+- GstBuffer* buffer = gst_app_buffer_new(data, size, g_free, data);
++ GstBuffer* buffer = gst_buffer_new_and_alloc(size);
++
++#if GST_CHECK_VERSION(1,0,0)
++ GstMapInfo mapInfo;
++ gst_buffer_map(buffer, &mapInfo, GST_MAP_WRITE);
++ void* bufferData = mapInfo.data;
++#else
++ void* bufferData = GST_BUFFER_DATA(buffer);
++#endif
++
+ buffer->offset = m_stream->pos();
+- qint64 bytesRead = m_stream->read((char*)GST_BUFFER_DATA(buffer), size);
++ qint64 bytesRead = m_stream->read((char*)bufferData, size);
+ buffer->offset_end = buffer->offset + bytesRead - 1;
+
++#if GST_CHECK_VERSION(1,0,0)
++ gst_buffer_unmap(buffer, &mapInfo);
++#endif
++
+ if (bytesRead > 0) {
+ m_dataRequested = false;
+ m_enoughData = false;
+ GstFlowReturn ret = gst_app_src_push_buffer (GST_APP_SRC (element()), buffer);
+ if (ret == GST_FLOW_ERROR) {
+ qWarning()<<"appsrc: push buffer error";
++#if GST_CHECK_VERSION(1,0,0)
++ } else if (ret == GST_FLOW_FLUSHING) {
++ qWarning()<<"appsrc: push buffer wrong state";
++ }
++#else
+ } else if (ret == GST_FLOW_WRONG_STATE) {
+ qWarning()<<"appsrc: push buffer wrong state";
+- } else if (ret == GST_FLOW_RESEND) {
++ }
++#endif
++#if GST_VERSION_MAJOR < 1
++ else if (ret == GST_FLOW_RESEND) {
+ qWarning()<<"appsrc: push buffer resend";
+ }
++#endif
+ }
+ } else {
+ sendEOS();
+diff --git a/src/gsttools/qgstcodecsinfo.cpp b/src/gsttools/qgstcodecsinfo.cpp
+index f584fbe..888722a 100644
+--- a/src/gsttools/qgstcodecsinfo.cpp
++++ b/src/gsttools/qgstcodecsinfo.cpp
+@@ -32,7 +32,7 @@
+ ****************************************************************************/
+
+ #include "qgstcodecsinfo_p.h"
+-
++#include "qgstutils_p.h"
+ #include <QtCore/qset.h>
+
+ #ifdef QMEDIA_GSTREAMER_CAMERABIN
+@@ -146,7 +146,7 @@ GstCaps* QGstCodecsInfo::supportedElementCaps(GstElementFactoryListType elementT
+ if (fakeEncoderMimeTypes.contains(gst_structure_get_name(structure)))
+ continue;
+
+- GstStructure *newStructure = gst_structure_new(gst_structure_get_name(structure), NULL);
++ GstStructure *newStructure = qt_gst_structure_new_empty(gst_structure_get_name(structure));
+
+ //add structure fields to distinguish between formats with similar mime types,
+ //like audio/mpeg
+@@ -166,7 +166,11 @@ GstCaps* QGstCodecsInfo::supportedElementCaps(GstElementFactoryListType elementT
+ }
+ }
+
++#if GST_CHECK_VERSION(1,0,0)
++ res =
++#endif
+ gst_caps_merge_structure(res, newStructure);
++
+ }
+ gst_caps_unref(caps);
+ }
+diff --git a/src/gsttools/qgstreameraudioprobecontrol.cpp b/src/gsttools/qgstreameraudioprobecontrol.cpp
+index 3baca53..9670d0f 100644
+--- a/src/gsttools/qgstreameraudioprobecontrol.cpp
++++ b/src/gsttools/qgstreameraudioprobecontrol.cpp
+@@ -37,32 +37,48 @@
+ QGstreamerAudioProbeControl::QGstreamerAudioProbeControl(QObject *parent)
+ : QMediaAudioProbeControl(parent)
+ {
+-
+ }
+
+ QGstreamerAudioProbeControl::~QGstreamerAudioProbeControl()
+ {
+-
+ }
+
+-void QGstreamerAudioProbeControl::bufferProbed(GstBuffer* buffer)
++void QGstreamerAudioProbeControl::probeCaps(GstCaps *caps)
+ {
+- GstCaps* caps = gst_buffer_get_caps(buffer);
+- if (!caps)
+- return;
+-
+ QAudioFormat format = QGstUtils::audioFormatForCaps(caps);
+- gst_caps_unref(caps);
+- if (!format.isValid())
+- return;
+
+- QAudioBuffer audioBuffer = QAudioBuffer(QByteArray((const char*)buffer->data, buffer->size), format);
++ QMutexLocker locker(&m_bufferMutex);
++ m_format = format;
++}
+
+- {
+- QMutexLocker locker(&m_bufferMutex);
+- m_pendingBuffer = audioBuffer;
+- QMetaObject::invokeMethod(this, "bufferProbed", Qt::QueuedConnection);
++bool QGstreamerAudioProbeControl::probeBuffer(GstBuffer *buffer)
++{
++ qint64 position = GST_BUFFER_TIMESTAMP(buffer);
++ position = position >= 0
++ ? position / G_GINT64_CONSTANT(1000) // microseconds
++ : -1;
++
++ QByteArray data;
++#if GST_CHECK_VERSION(1,0,0)
++ GstMapInfo info;
++ if (gst_buffer_map(buffer, &info, GST_MAP_READ)) {
++ data = QByteArray(reinterpret_cast<const char *>(info.data), info.size);
++ gst_buffer_unmap(buffer, &info);
++ } else {
++ return true;
++ }
++#else
++ data = QByteArray(reinterpret_cast<const char *>(buffer->data), buffer->size);
++#endif
++
++ QMutexLocker locker(&m_bufferMutex);
++ if (m_format.isValid()) {
++ if (!m_pendingBuffer.isValid())
++ QMetaObject::invokeMethod(this, "bufferProbed", Qt::QueuedConnection);
++ m_pendingBuffer = QAudioBuffer(data, m_format, position);
+ }
++
++ return true;
+ }
+
+ void QGstreamerAudioProbeControl::bufferProbed()
+@@ -73,6 +89,7 @@ void QGstreamerAudioProbeControl::bufferProbed()
+ if (!m_pendingBuffer.isValid())
+ return;
+ audioBuffer = m_pendingBuffer;
++ m_pendingBuffer = QAudioBuffer();
+ }
+ emit audioBufferProbed(audioBuffer);
+ }
+diff --git a/src/gsttools/qgstreamerbufferprobe.cpp b/src/gsttools/qgstreamerbufferprobe.cpp
+new file mode 100644
+index 0000000..91f8126
+--- /dev/null
++++ b/src/gsttools/qgstreamerbufferprobe.cpp
+@@ -0,0 +1,174 @@
++/****************************************************************************
++**
++** Copyright (C) 2014 Jolla Ltd.
++** Contact: http://www.qt-project.org/legal
++**
++** This file is part of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:LGPL$
++** 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 Digia. For licensing terms and
++** conditions see http://qt.digia.com/licensing. For further information
++** use the contact form at http://qt.digia.com/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 as published by the Free Software
++** Foundation and appearing in the file LICENSE.LGPL included in the
++** packaging of this file. Please review the following information to
++** ensure the GNU Lesser General Public License version 2.1 requirements
++** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
++**
++** In addition, as a special exception, Digia gives you certain additional
++** rights. These rights are described in the Digia Qt LGPL Exception
++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
++**
++** GNU General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU
++** General Public License version 3.0 as published by the Free Software
++** Foundation and appearing in the file LICENSE.GPL included in the
++** packaging of this file. Please review the following information to
++** ensure the GNU General Public License version 3.0 requirements will be
++** met: http://www.gnu.org/copyleft/gpl.html.
++**
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++#include "qgstreamerbufferprobe_p.h"
++#include "qgstutils_p.h"
++
++QT_BEGIN_NAMESPACE
++
++QGstreamerBufferProbe::QGstreamerBufferProbe(Flags flags)
++#if GST_CHECK_VERSION(1,0,0)
++ : m_capsProbeId(-1)
++#else
++ : m_caps(0)
++#endif
++ , m_bufferProbeId(-1)
++ , m_flags(flags)
++{
++}
++
++QGstreamerBufferProbe::~QGstreamerBufferProbe()
++{
++#if !GST_CHECK_VERSION(1,0,0)
++ if (m_caps)
++ gst_caps_unref(m_caps);
++#endif
++}
++
++void QGstreamerBufferProbe::addProbeToPad(GstPad *pad, bool downstream)
++{
++ if (GstCaps *caps = qt_gst_pad_get_current_caps(pad)) {
++ probeCaps(caps);
++ gst_caps_unref(caps);
++ }
++#if GST_CHECK_VERSION(1,0,0)
++ if (m_flags & ProbeCaps) {
++ m_capsProbeId = gst_pad_add_probe(
++ pad,
++ downstream
++ ? GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM
++ : GST_PAD_PROBE_TYPE_EVENT_UPSTREAM,
++ capsProbe,
++ this,
++ NULL);
++ }
++ if (m_flags & ProbeBuffers) {
++ m_bufferProbeId = gst_pad_add_probe(
++ pad, GST_PAD_PROBE_TYPE_BUFFER, bufferProbe, this, NULL);
++ }
++#else
++ Q_UNUSED(downstream);
++
++ m_bufferProbeId = gst_pad_add_buffer_probe(pad, G_CALLBACK(bufferProbe), this);
++#endif
++}
++
++void QGstreamerBufferProbe::removeProbeFromPad(GstPad *pad)
++{
++#if GST_CHECK_VERSION(1,0,0)
++ if (m_capsProbeId != -1) {
++ gst_pad_remove_probe(pad, m_capsProbeId);
++ m_capsProbeId = -1;
++ }
++ if (m_bufferProbeId != -1) {
++ gst_pad_remove_probe(pad, m_bufferProbeId);
++ m_bufferProbeId = -1;
++ }
++#else
++ if (m_bufferProbeId != -1) {
++ gst_pad_remove_buffer_probe(pad, m_bufferProbeId);
++ m_bufferProbeId = -1;
++ if (m_caps) {
++ gst_caps_unref(m_caps);
++ m_caps = 0;
++ }
++ }
++#endif
++}
++
++void QGstreamerBufferProbe::probeCaps(GstCaps *)
++{
++}
++
++bool QGstreamerBufferProbe::probeBuffer(GstBuffer *)
++{
++ return true;
++}
++
++#if GST_CHECK_VERSION(1,0,0)
++GstPadProbeReturn QGstreamerBufferProbe::capsProbe(
++ GstPad *, GstPadProbeInfo *info, gpointer user_data)
++{
++ QGstreamerBufferProbe * const control = static_cast<QGstreamerBufferProbe *>(user_data);
++
++ if (GstEvent * const event = gst_pad_probe_info_get_event(info)) {
++ if (GST_EVENT_TYPE(event) == GST_EVENT_CAPS) {
++ GstCaps *caps;
++ gst_event_parse_caps(event, &caps);
++
++ control->probeCaps(caps);
++ }
++ }
++ return GST_PAD_PROBE_OK;
++}
++
++GstPadProbeReturn QGstreamerBufferProbe::bufferProbe(
++ GstPad *, GstPadProbeInfo *info, gpointer user_data)
++{
++ QGstreamerBufferProbe * const control = static_cast<QGstreamerBufferProbe *>(user_data);
++ if (GstBuffer * const buffer = gst_pad_probe_info_get_buffer(info))
++ return control->probeBuffer(buffer) ? GST_PAD_PROBE_OK : GST_PAD_PROBE_DROP;
++ return GST_PAD_PROBE_OK;
++}
++#else
++gboolean QGstreamerBufferProbe::bufferProbe(GstElement *, GstBuffer *buffer, gpointer user_data)
++{
++ QGstreamerBufferProbe * const control = static_cast<QGstreamerBufferProbe *>(user_data);
++
++ if (control->m_flags & ProbeCaps) {
++ GstCaps *caps = gst_buffer_get_caps(buffer);
++ if (caps && (!control->m_caps || !gst_caps_is_equal(control->m_caps, caps))) {
++ qSwap(caps, control->m_caps);
++ control->probeCaps(control->m_caps);
++ }
++ if (caps)
++ gst_caps_unref(caps);
++ }
++
++ if (control->m_flags & ProbeBuffers) {
++ return control->probeBuffer(buffer) ? TRUE : FALSE;
++ } else {
++ return TRUE;
++ }
++}
++#endif
++
++QT_END_NAMESPACE
+diff --git a/src/gsttools/qgstreamerbushelper.cpp b/src/gsttools/qgstreamerbushelper.cpp
+index 84eda46..eb1fc36 100644
+--- a/src/gsttools/qgstreamerbushelper.cpp
++++ b/src/gsttools/qgstreamerbushelper.cpp
+@@ -154,13 +154,21 @@ QGstreamerBusHelper::QGstreamerBusHelper(GstBus* bus, QObject* parent):
+ QObject(parent)
+ {
+ d = new QGstreamerBusHelperPrivate(this, bus);
++#if GST_CHECK_VERSION(1,0,0)
++ gst_bus_set_sync_handler(bus, (GstBusSyncHandler)syncGstBusFilter, d, 0);
++#else
+ gst_bus_set_sync_handler(bus, (GstBusSyncHandler)syncGstBusFilter, d);
++#endif
+ gst_object_ref(GST_OBJECT(bus));
+ }
+
+ QGstreamerBusHelper::~QGstreamerBusHelper()
+ {
++#if GST_CHECK_VERSION(1,0,0)
++ gst_bus_set_sync_handler(d->bus(), 0, 0, 0);
++#else
+ gst_bus_set_sync_handler(d->bus(),0,0);
++#endif
+ gst_object_unref(GST_OBJECT(d->bus()));
+ }
+
+diff --git a/src/gsttools/qgstreamermirtexturerenderer.cpp b/src/gsttools/qgstreamermirtexturerenderer.cpp
+new file mode 100644
+index 0000000..39e0db7
+--- /dev/null
++++ b/src/gsttools/qgstreamermirtexturerenderer.cpp
+@@ -0,0 +1,351 @@
++/****************************************************************************
++**
++** Copyright (C) 2014 Canonical Ltd.
++** Contact: http://www.qt-project.org/legal
++**
++** 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 Digia. For licensing terms and
++** conditions see http://qt.digia.com/licensing. For further information
++** use the contact form at http://qt.digia.com/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.
++**
++** In addition, as a special exception, Digia gives you certain additional
++** rights. These rights are described in the Digia Qt LGPL Exception
++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++#include "qgstreamermirtexturerenderer_p.h"
++
++#include <qgstreamerplayersession.h>
++#include <private/qvideosurfacegstsink_p.h>
++#include <private/qgstutils_p.h>
++#include <qabstractvideosurface.h>
++
++#include <QAbstractVideoBuffer>
++#include <QGuiApplication>
++#include <QDebug>
++#include <QtQuick/QQuickWindow>
++#include <QOpenGLContext>
++#include <QGLContext>
++#include <QGuiApplication>
++#include <qgl.h>
++
++#include <gst/gst.h>
++
++static QGstreamerMirTextureRenderer *rendererInstance = NULL;
++
++class QGstreamerMirTextureBuffer : public QAbstractVideoBuffer
++{
++public:
++ QGstreamerMirTextureBuffer(GLuint textureId) :
++ QAbstractVideoBuffer(QAbstractVideoBuffer::GLTextureHandle),
++ m_textureId(textureId)
++ {
++ }
++
++ MapMode mapMode() const { return NotMapped; }
++
++ uchar *map(MapMode mode, int *numBytes, int *bytesPerLine)
++ {
++ qDebug() << Q_FUNC_INFO;
++ Q_UNUSED(mode);
++ Q_UNUSED(numBytes);
++ Q_UNUSED(bytesPerLine);
++
++ return NULL;
++ }
++
++ void unmap() { qDebug() << Q_FUNC_INFO; }
++
++ QVariant handle() const { return QVariant::fromValue<unsigned int>(m_textureId); }
++
++ GLuint textureId() { return m_textureId; }
++
++private:
++ GLuint m_textureId;
++};
++
++QGstreamerMirTextureRenderer::QGstreamerMirTextureRenderer(QObject *parent
++ , const QGstreamerPlayerSession *playerSession)
++ : QVideoRendererControl(0), m_videoSink(0), m_surface(0),
++ m_glSurface(0),
++ m_context(0),
++ m_glContext(0),
++ m_textureId(0),
++ m_offscreenSurface(0),
++ m_textureBuffer(0)
++{
++ Q_UNUSED(parent);
++ setPlayerSession(playerSession);
++}
++
++QGstreamerMirTextureRenderer::~QGstreamerMirTextureRenderer()
++{
++ if (m_videoSink)
++ gst_object_unref(GST_OBJECT(m_videoSink));
++
++ delete m_glContext;
++ delete m_offscreenSurface;
++}
++
++GstElement *QGstreamerMirTextureRenderer::videoSink()
++{
++ qDebug() << Q_FUNC_INFO;
++
++ // FIXME: Ugly hack until I figure out why passing this segfaults in the g_signal handler
++ rendererInstance = const_cast<QGstreamerMirTextureRenderer*>(this);
++
++ if (!m_videoSink && m_surface) {
++ qDebug() << Q_FUNC_INFO << ": using mirsink, (this: " << this << ")";
++
++ m_videoSink = gst_element_factory_make("mirsink", "video-output");
++
++ connect(QGuiApplication::instance(), SIGNAL(focusWindowChanged(QWindow*)),
++ this, SLOT(handleFocusWindowChanged(QWindow*)), Qt::QueuedConnection);
++
++ g_signal_connect(G_OBJECT(m_videoSink), "frame-ready", G_CALLBACK(handleFrameReady),
++ (gpointer)this);
++ }
++
++ if (m_videoSink) {
++ gst_object_ref_sink(GST_OBJECT(m_videoSink));
++
++ GstPad *pad = gst_element_get_static_pad(m_videoSink, "sink");
++ gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_BUFFER,
++ padBufferProbe, this, NULL);
++ }
++
++ return m_videoSink;
++}
++
++QWindow *QGstreamerMirTextureRenderer::createOffscreenWindow(const QSurfaceFormat &format)
++{
++ QWindow *w = new QWindow();
++ w->setSurfaceType(QWindow::OpenGLSurface);
++ w->setFormat(format);
++ w->setGeometry(0, 0, 1, 1);
++ w->setFlags(w->flags() | Qt::WindowTransparentForInput);
++ w->create();
++
++ return w;
++}
++
++void QGstreamerMirTextureRenderer::handleFrameReady(gpointer userData)
++{
++ QGstreamerMirTextureRenderer *renderer = reinterpret_cast<QGstreamerMirTextureRenderer*>(userData);
++#if 1
++ QMutexLocker locker(&rendererInstance->m_mutex);
++ QMetaObject::invokeMethod(rendererInstance, "renderFrame", Qt::QueuedConnection);
++#else
++ // FIXME!
++ //QMutexLocker locker(&renderer->m_mutex);
++ QMetaObject::invokeMethod(renderer, "renderFrame", Qt::QueuedConnection);
++#endif
++}
++
++void QGstreamerMirTextureRenderer::renderFrame()
++{
++ //qDebug() << Q_FUNC_INFO;
++
++ if (m_context)
++ m_context->makeCurrent();
++
++ GstState pendingState = GST_STATE_NULL;
++ GstState newState = GST_STATE_NULL;
++ // Don't block and return immediately:
++ GstStateChangeReturn ret = gst_element_get_state(m_videoSink, &newState,
++ &pendingState, 0);
++ if (ret == GST_STATE_CHANGE_FAILURE || newState == GST_STATE_NULL||
++ pendingState == GST_STATE_NULL) {
++ qWarning() << "Invalid state change for renderer, aborting";
++ stopRenderer();
++ return;
++ }
++
++ if (!m_surface->isActive()) {
++ qDebug() << "m_surface is not active";
++ GstPad *pad = gst_element_get_static_pad(m_videoSink, "sink");
++ GstCaps *caps = gst_pad_get_current_caps(pad);
++
++ if (caps) {
++ // Get the native video size from the video sink
++ QSize newNativeSize = QGstUtils::capsCorrectedResolution(caps);
++ if (m_nativeSize != newNativeSize) {
++ m_nativeSize = newNativeSize;
++ emit nativeSizeChanged();
++ }
++ gst_caps_unref(caps);
++ }
++
++ // Start the surface
++ QVideoSurfaceFormat format(m_nativeSize, QVideoFrame::Format_RGB32, QAbstractVideoBuffer::GLTextureHandle);
++ qDebug() << "m_nativeSize: " << m_nativeSize;
++ qDebug() << "format: " << format;
++ if (!m_surface->start(format)) {
++ qWarning() << Q_FUNC_INFO << ": failed to start the video surface " << format;
++ return;
++ }
++ }
++
++ QGstreamerMirTextureBuffer *buffer = new QGstreamerMirTextureBuffer(m_textureId);
++ //qDebug() << "frameSize: " << m_surface->surfaceFormat().frameSize();
++ QVideoFrame frame(buffer, m_surface->surfaceFormat().frameSize(),
++ m_surface->surfaceFormat().pixelFormat());
++
++ frame.setMetaData("TextureId", m_textureId);
++
++ // Display the video frame on the surface:
++ m_surface->present(frame);
++}
++
++GstPadProbeReturn QGstreamerMirTextureRenderer::padBufferProbe(GstPad *pad, GstPadProbeInfo *info, gpointer userData)
++{
++ Q_UNUSED(pad);
++ Q_UNUSED(info);
++
++ QGstreamerMirTextureRenderer *control = reinterpret_cast<QGstreamerMirTextureRenderer*>(userData);
++ QMetaObject::invokeMethod(control, "updateNativeVideoSize", Qt::QueuedConnection);
++
++ return GST_PAD_PROBE_REMOVE;
++}
++
++void QGstreamerMirTextureRenderer::stopRenderer()
++{
++ if (m_surface)
++ m_surface->stop();
++}
++
++QAbstractVideoSurface *QGstreamerMirTextureRenderer::surface() const
++{
++ return m_surface;
++}
++
++void QGstreamerMirTextureRenderer::setSurface(QAbstractVideoSurface *surface)
++{
++ qDebug() << Q_FUNC_INFO;
++
++ if (m_surface != surface) {
++ qDebug() << "Saving current QGLContext";
++ m_context = const_cast<QGLContext*>(QGLContext::currentContext());
++
++ if (m_videoSink)
++ gst_object_unref(GST_OBJECT(m_videoSink));
++
++ m_videoSink = 0;
++
++ if (m_surface) {
++ disconnect(m_surface.data(), SIGNAL(supportedFormatsChanged()),
++ this, SLOT(handleFormatChange()));
++ }
++
++ bool wasReady = isReady();
++
++ m_surface = surface;
++
++ if (m_surface) {
++ connect(m_surface.data(), SIGNAL(supportedFormatsChanged()),
++ this, SLOT(handleFormatChange()));
++ }
++
++ if (wasReady != isReady())
++ emit readyChanged(isReady());
++
++ emit sinkChanged();
++ }
++}
++
++void QGstreamerMirTextureRenderer::setPlayerSession(const QGstreamerPlayerSession *playerSession)
++{
++ m_playerSession = const_cast<QGstreamerPlayerSession*>(playerSession);
++}
++
++void QGstreamerMirTextureRenderer::handleFormatChange()
++{
++ qDebug() << "Supported formats list has changed, reload video output";
++
++ if (m_videoSink)
++ gst_object_unref(GST_OBJECT(m_videoSink));
++
++ m_videoSink = 0;
++ emit sinkChanged();
++}
++
++void QGstreamerMirTextureRenderer::updateNativeVideoSize()
++{
++ //qDebug() << Q_FUNC_INFO;
++ const QSize oldSize = m_nativeSize;
++
++ 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 = gst_pad_get_current_caps(pad);
++
++ if (caps) {
++ m_nativeSize = QGstUtils::capsCorrectedResolution(caps);
++ gst_caps_unref(caps);
++ }
++ } else {
++ m_nativeSize = QSize();
++ }
++ qDebug() << Q_FUNC_INFO << oldSize << m_nativeSize << m_videoSink;
++
++ if (m_nativeSize != oldSize)
++ emit nativeSizeChanged();
++}
++
++void QGstreamerMirTextureRenderer::handleFocusWindowChanged(QWindow *window)
++{
++ qDebug() << Q_FUNC_INFO;
++
++ QOpenGLContext *currContext = QOpenGLContext::currentContext();
++
++ QQuickWindow *w = dynamic_cast<QQuickWindow*>(window);
++ // If we don't have a GL context in the current thread, create one and share it
++ // with the render thread GL context
++ if (!currContext && !m_glContext) {
++ // This emulates the new QOffscreenWindow class with Qt5.1
++ m_offscreenSurface = createOffscreenWindow(w->openglContext()->surface()->format());
++ m_offscreenSurface->setParent(window);
++
++ QOpenGLContext *shareContext = 0;
++ if (m_surface)
++ shareContext = qobject_cast<QOpenGLContext*>(m_surface->property("GLContext").value<QObject*>());
++ m_glContext = new QOpenGLContext;
++ m_glContext->setFormat(m_offscreenSurface->requestedFormat());
++
++ if (shareContext)
++ m_glContext->setShareContext(shareContext);
++
++ if (!m_glContext->create())
++ {
++ qWarning() << "Failed to create new shared context.";
++ return;
++ }
++ }
++
++ if (m_glContext)
++ m_glContext->makeCurrent(m_offscreenSurface);
++
++ if (m_textureId == 0) {
++ glGenTextures(1, &m_textureId);
++ qDebug() << "texture_id (handleFocusWindowChanged): " << m_textureId << endl;
++ g_object_set(G_OBJECT(m_videoSink), "texture-id", m_textureId, (char*)NULL);
++ }
++}
+diff --git a/src/gsttools/qgstreamervideoprobecontrol.cpp b/src/gsttools/qgstreamervideoprobecontrol.cpp
+index a78a9da..71a402d 100644
+--- a/src/gsttools/qgstreamervideoprobecontrol.cpp
++++ b/src/gsttools/qgstreamervideoprobecontrol.cpp
+@@ -32,7 +32,8 @@
+ ****************************************************************************/
+
+ #include "qgstreamervideoprobecontrol_p.h"
+-#include <private/qvideosurfacegstsink_p.h>
++
++#include "qgstutils_p.h"
+ #include <private/qgstvideobuffer_p.h>
+
+ QGstreamerVideoProbeControl::QGstreamerVideoProbeControl(QObject *parent)
+@@ -40,12 +41,10 @@ QGstreamerVideoProbeControl::QGstreamerVideoProbeControl(QObject *parent)
+ , m_flushing(false)
+ , m_frameProbed(false)
+ {
+-
+ }
+
+ QGstreamerVideoProbeControl::~QGstreamerVideoProbeControl()
+ {
+-
+ }
+
+ void QGstreamerVideoProbeControl::startFlushing()
+@@ -67,33 +66,49 @@ void QGstreamerVideoProbeControl::stopFlushing()
+ m_flushing = false;
+ }
+
+-void QGstreamerVideoProbeControl::bufferProbed(GstBuffer* buffer)
++void QGstreamerVideoProbeControl::probeCaps(GstCaps *caps)
+ {
+- if (m_flushing)
+- return;
+-
+- GstCaps* caps = gst_buffer_get_caps(buffer);
+- if (!caps)
+- return;
++#if GST_CHECK_VERSION(1,0,0)
++ GstVideoInfo videoInfo;
++ QVideoSurfaceFormat format = QGstUtils::formatForCaps(caps, &videoInfo);
+
++ QMutexLocker locker(&m_frameMutex);
++ m_videoInfo = videoInfo;
++#else
+ int bytesPerLine = 0;
+- QVideoSurfaceFormat format = QVideoSurfaceGstSink::formatForCaps(caps, &bytesPerLine);
+- gst_caps_unref(caps);
+- if (!format.isValid() || !bytesPerLine)
+- return;
++ QVideoSurfaceFormat format = QGstUtils::formatForCaps(caps, &bytesPerLine);
++
++ QMutexLocker locker(&m_frameMutex);
++ m_bytesPerLine = bytesPerLine;
++#endif
++ m_format = format;
++}
++
++bool QGstreamerVideoProbeControl::probeBuffer(GstBuffer *buffer)
++{
++ QMutexLocker locker(&m_frameMutex);
++
++ if (m_flushing || !m_format.isValid())
++ return true;
+
+- QVideoFrame frame = QVideoFrame(new QGstVideoBuffer(buffer, bytesPerLine),
+- format.frameSize(), format.pixelFormat());
++ QVideoFrame frame(
++#if GST_CHECK_VERSION(1,0,0)
++ new QGstVideoBuffer(buffer, m_videoInfo),
++#else
++ new QGstVideoBuffer(buffer, m_bytesPerLine),
++#endif
++ m_format.frameSize(),
++ m_format.pixelFormat());
+
+- QVideoSurfaceGstSink::setFrameTimeStamps(&frame, buffer);
++ QGstUtils::setFrameTimeStamps(&frame, buffer);
+
+ m_frameProbed = true;
+
+- {
+- QMutexLocker locker(&m_frameMutex);
+- m_pendingFrame = frame;
++ if (!m_pendingFrame.isValid())
+ QMetaObject::invokeMethod(this, "frameProbed", Qt::QueuedConnection);
+- }
++ m_pendingFrame = frame;
++
++ return true;
+ }
+
+ void QGstreamerVideoProbeControl::frameProbed()
+@@ -104,6 +119,7 @@ void QGstreamerVideoProbeControl::frameProbed()
+ if (!m_pendingFrame.isValid())
+ return;
+ frame = m_pendingFrame;
++ m_pendingFrame = QVideoFrame();
+ }
+ emit videoFrameProbed(frame);
+ }
+diff --git a/src/gsttools/qgstreamervideorenderer.cpp b/src/gsttools/qgstreamervideorenderer.cpp
+index 2b66f76..804dce9 100644
+--- a/src/gsttools/qgstreamervideorenderer.cpp
++++ b/src/gsttools/qgstreamervideorenderer.cpp
+@@ -35,8 +35,7 @@
+ #include <private/qvideosurfacegstsink_p.h>
+ #include <private/qgstutils_p.h>
+ #include <qabstractvideosurface.h>
+-
+-#include <QDebug>
++#include <QtCore/qdebug.h>
+
+ #include <gst/gst.h>
+
+diff --git a/src/gsttools/qgstreamervideowidget.cpp b/src/gsttools/qgstreamervideowidget.cpp
+index aa2e2a3..1ae57a0 100644
+--- a/src/gsttools/qgstreamervideowidget.cpp
++++ b/src/gsttools/qgstreamervideowidget.cpp
+@@ -40,8 +40,13 @@
+ #include <QtGui/qpainter.h>
+
+ #include <gst/gst.h>
++
++#if !GST_CHECK_VERSION(1,0,0)
+ #include <gst/interfaces/xoverlay.h>
+ #include <gst/interfaces/propertyprobe.h>
++#else
++#include <gst/video/videooverlay.h>
++#endif
+
+ QT_BEGIN_NAMESPACE
+
+@@ -130,8 +135,6 @@ void QGstreamerVideoWidgetControl::createVideoWidget()
+ m_videoSink = gst_element_factory_make ("ximagesink", NULL);
+
+ qt_gst_object_ref_sink(GST_OBJECT (m_videoSink)); //Take ownership
+-
+-
+ }
+
+ GstElement *QGstreamerVideoWidgetControl::videoSink()
+@@ -169,9 +172,13 @@ bool QGstreamerVideoWidgetControl::processSyncMessage(const QGstreamerMessage &m
+ {
+ 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;
+@@ -199,17 +206,24 @@ bool QGstreamerVideoWidgetControl::processBusMessage(const QGstreamerMessage &me
+
+ void QGstreamerVideoWidgetControl::setOverlay()
+ {
++#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);
++ }
++#endif
+ }
+
+ void QGstreamerVideoWidgetControl::updateNativeVideoSize()
+ {
+ 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 = gst_pad_get_negotiated_caps(pad);
++ 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) {
+@@ -225,8 +239,13 @@ void QGstreamerVideoWidgetControl::updateNativeVideoSize()
+
+ void QGstreamerVideoWidgetControl::windowExposed()
+ {
++#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
+ }
+
+ QWidget *QGstreamerVideoWidgetControl::videoWidget()
+diff --git a/src/gsttools/qgstreamervideowindow.cpp b/src/gsttools/qgstreamervideowindow.cpp
+index a373dcc..8011349 100644
+--- a/src/gsttools/qgstreamervideowindow.cpp
++++ b/src/gsttools/qgstreamervideowindow.cpp
+@@ -37,36 +37,49 @@
+ #include <QtCore/qdebug.h>
+
+ #include <gst/gst.h>
++
++#if !GST_CHECK_VERSION(1,0,0)
+ #include <gst/interfaces/xoverlay.h>
+ #include <gst/interfaces/propertyprobe.h>
++#else
++#include <gst/video/videooverlay.h>
++#endif
+
+
+ QGstreamerVideoWindow::QGstreamerVideoWindow(QObject *parent, const char *elementName)
+ : QVideoWindowControl(parent)
++ , QGstreamerBufferProbe(QGstreamerBufferProbe::ProbeCaps)
+ , m_videoSink(0)
+ , m_windowId(0)
+ , m_aspectRatioMode(Qt::KeepAspectRatio)
+ , m_fullScreen(false)
+ , m_colorKey(QColor::Invalid)
+ {
+- if (elementName)
++ if (elementName) {
+ m_videoSink = gst_element_factory_make(elementName, NULL);
+- else
++ } else {
+ 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");
+- m_bufferProbeId = gst_pad_add_buffer_probe(pad, G_CALLBACK(padBufferProbe), this);
++ GstPad *pad = gst_element_get_static_pad(m_videoSink, "sink");
++ addProbeToPad(pad);
+ gst_object_unref(GST_OBJECT(pad));
+ }
++ else
++ qDebug() << "No m_videoSink available!";
+ }
+
+ QGstreamerVideoWindow::~QGstreamerVideoWindow()
+ {
+- if (m_videoSink)
++ 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));
++ }
+ }
+
+ WId QGstreamerVideoWindow::winId() const
+@@ -82,11 +95,15 @@ void QGstreamerVideoWindow::setWinId(WId id)
+ WId oldId = m_windowId;
+
+ 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);
+
+@@ -97,20 +114,26 @@ 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);
+
+- GstPad *pad = gst_element_get_static_pad(m_videoSink,"sink");
+- m_bufferProbeId = gst_pad_add_buffer_probe(pad, G_CALLBACK(padBufferProbe), this);
+- gst_object_unref(GST_OBJECT(pad));
+-
+ return true;
+ }
+-
++#endif
+ return false;
+ }
+
+@@ -122,7 +145,19 @@ 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())
+@@ -136,6 +171,7 @@ void QGstreamerVideoWindow::setDisplayRect(const QRect &rect)
+ repaint();
+ #endif
+ }
++#endif
+ }
+
+ Qt::AspectRatioMode QGstreamerVideoWindow::aspectRatioMode() const
+@@ -157,6 +193,16 @@ void QGstreamerVideoWindow::setAspectRatioMode(Qt::AspectRatioMode 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;
+@@ -165,6 +211,7 @@ void QGstreamerVideoWindow::repaint()
+ gst_x_overlay_expose(GST_X_OVERLAY(m_videoSink));
+ }
+ }
++#endif
+ }
+
+ QColor QGstreamerVideoWindow::colorKey() const
+@@ -296,32 +343,22 @@ QSize QGstreamerVideoWindow::nativeSize() const
+ return m_nativeSize;
+ }
+
+-void QGstreamerVideoWindow::padBufferProbe(GstPad *pad, GstBuffer * /* buffer */, gpointer user_data)
++void QGstreamerVideoWindow::probeCaps(GstCaps *caps)
+ {
+- QGstreamerVideoWindow *control = reinterpret_cast<QGstreamerVideoWindow*>(user_data);
+- QMetaObject::invokeMethod(control, "updateNativeVideoSize", Qt::QueuedConnection);
+- gst_pad_remove_buffer_probe(pad, control->m_bufferProbeId);
++ QSize resolution = QGstUtils::capsCorrectedResolution(caps);
++ QMetaObject::invokeMethod(
++ this,
++ "updateNativeVideoSize",
++ Qt::QueuedConnection,
++ Q_ARG(QSize, resolution));
+ }
+
+-void QGstreamerVideoWindow::updateNativeVideoSize()
++void QGstreamerVideoWindow::updateNativeVideoSize(const QSize &size)
+ {
+- const QSize oldSize = m_nativeSize;
+- m_nativeSize = QSize();
+-
+- 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 = gst_pad_get_negotiated_caps(pad);
+- gst_object_unref(GST_OBJECT(pad));
+-
+- if (caps) {
+- m_nativeSize = QGstUtils::capsCorrectedResolution(caps);
+- gst_caps_unref(caps);
+- }
+- }
+-
+- if (m_nativeSize != oldSize)
++ if (m_nativeSize != size) {
++ m_nativeSize = size;
+ emit nativeSizeChanged();
++ }
+ }
+
+ GstElement *QGstreamerVideoWindow::videoSink()
+diff --git a/src/gsttools/qgstutils.cpp b/src/gsttools/qgstutils.cpp
+index 556fc03..65124c9 100644
+--- a/src/gsttools/qgstutils.cpp
++++ b/src/gsttools/qgstutils.cpp
+@@ -40,7 +40,14 @@
+ #include <QtCore/qsize.h>
+ #include <QtCore/qset.h>
+ #include <QtCore/qstringlist.h>
++#include <QtGui/qimage.h>
+ #include <qaudioformat.h>
++#include <QtMultimedia/qvideosurfaceformat.h>
++
++#include <gst/audio/audio.h>
++#include <gst/video/video.h>
++
++template<typename T, int N> static int lengthOf(const T (&)[N]) { return N; }
+
+ #ifdef USE_V4L
+ # include <private/qcore_unix_p.h>
+@@ -82,15 +89,24 @@ static void addTagToMap(const GstTagList *list,
+ map->insert(QByteArray(tag), g_value_get_boolean(&val));
+ break;
+ case G_TYPE_CHAR:
++#if GLIB_CHECK_VERSION(2,32,0)
++ map->insert(QByteArray(tag), g_value_get_schar(&val));
++#else
+ map->insert(QByteArray(tag), g_value_get_char(&val));
++#endif
+ break;
+ case G_TYPE_DOUBLE:
+ map->insert(QByteArray(tag), g_value_get_double(&val));
+ break;
+ default:
+ // GST_TYPE_DATE is a function, not a constant, so pull it out of the switch
++#if GST_CHECK_VERSION(1,0,0)
++ if (G_VALUE_TYPE(&val) == G_TYPE_DATE) {
++ const GDate *date = (const GDate *)g_value_get_boxed(&val);
++#else
+ if (G_VALUE_TYPE(&val) == GST_TYPE_DATE) {
+ const GDate *date = gst_value_get_date(&val);
++#endif
+ if (g_date_valid(date)) {
+ int year = g_date_get_year(date);
+ int month = g_date_get_month(date);
+@@ -169,6 +185,42 @@ QSize QGstUtils::capsCorrectedResolution(const GstCaps *caps)
+ return size;
+ }
+
++
++#if GST_CHECK_VERSION(1,0,0)
++namespace {
++
++struct AudioFormat
++{
++ GstAudioFormat format;
++ QAudioFormat::SampleType sampleType;
++ QAudioFormat::Endian byteOrder;
++ int sampleSize;
++};
++static const AudioFormat qt_audioLookup[] =
++{
++ { GST_AUDIO_FORMAT_S8 , QAudioFormat::SignedInt , QAudioFormat::LittleEndian, 8 },
++ { GST_AUDIO_FORMAT_U8 , QAudioFormat::UnSignedInt, QAudioFormat::LittleEndian, 8 },
++ { GST_AUDIO_FORMAT_S16LE, QAudioFormat::SignedInt , QAudioFormat::LittleEndian, 16 },
++ { GST_AUDIO_FORMAT_S16BE, QAudioFormat::SignedInt , QAudioFormat::BigEndian , 16 },
++ { GST_AUDIO_FORMAT_U16LE, QAudioFormat::UnSignedInt, QAudioFormat::LittleEndian, 16 },
++ { GST_AUDIO_FORMAT_U16BE, QAudioFormat::UnSignedInt, QAudioFormat::BigEndian , 16 },
++ { GST_AUDIO_FORMAT_S32LE, QAudioFormat::SignedInt , QAudioFormat::LittleEndian, 32 },
++ { GST_AUDIO_FORMAT_S32BE, QAudioFormat::SignedInt , QAudioFormat::BigEndian , 32 },
++ { GST_AUDIO_FORMAT_U32LE, QAudioFormat::UnSignedInt, QAudioFormat::LittleEndian, 32 },
++ { GST_AUDIO_FORMAT_U32BE, QAudioFormat::UnSignedInt, QAudioFormat::BigEndian , 32 },
++ { GST_AUDIO_FORMAT_S24LE, QAudioFormat::SignedInt , QAudioFormat::LittleEndian, 24 },
++ { GST_AUDIO_FORMAT_S24BE, QAudioFormat::SignedInt , QAudioFormat::BigEndian , 24 },
++ { GST_AUDIO_FORMAT_U24LE, QAudioFormat::UnSignedInt, QAudioFormat::LittleEndian, 24 },
++ { GST_AUDIO_FORMAT_U24BE, QAudioFormat::UnSignedInt, QAudioFormat::BigEndian , 24 },
++ { GST_AUDIO_FORMAT_F32LE, QAudioFormat::Float , QAudioFormat::LittleEndian, 32 },
++ { GST_AUDIO_FORMAT_F32BE, QAudioFormat::Float , QAudioFormat::BigEndian , 32 },
++ { GST_AUDIO_FORMAT_F64LE, QAudioFormat::Float , QAudioFormat::LittleEndian, 64 },
++ { GST_AUDIO_FORMAT_F64BE, QAudioFormat::Float , QAudioFormat::BigEndian , 64 }
++};
++
++}
++#endif
++
+ /*!
+ Returns audio format for caps.
+ If caps doesn't have a valid audio format, an empty QAudioFormat is returned.
+@@ -176,9 +228,26 @@ QSize QGstUtils::capsCorrectedResolution(const GstCaps *caps)
+
+ QAudioFormat QGstUtils::audioFormatForCaps(const GstCaps *caps)
+ {
+- const GstStructure *structure = gst_caps_get_structure(caps, 0);
+-
+ QAudioFormat format;
++#if GST_CHECK_VERSION(1,0,0)
++ GstAudioInfo info;
++ if (gst_audio_info_from_caps(&info, caps)) {
++ for (int i = 0; i < lengthOf(qt_audioLookup); ++i) {
++ if (qt_audioLookup[i].format != info.finfo->format)
++ continue;
++
++ format.setSampleType(qt_audioLookup[i].sampleType);
++ format.setByteOrder(qt_audioLookup[i].byteOrder);
++ format.setSampleSize(qt_audioLookup[i].sampleSize);
++ format.setSampleRate(info.rate);
++ format.setChannelCount(info.channels);
++ format.setCodec(QStringLiteral("audio/pcm"));
++
++ return format;
++ }
++ }
++#else
++ const GstStructure *structure = gst_caps_get_structure(caps, 0);
+
+ if (qstrcmp(gst_structure_get_name(structure), "audio/x-raw-int") == 0) {
+
+@@ -249,16 +318,28 @@ QAudioFormat QGstUtils::audioFormatForCaps(const GstCaps *caps)
+ } else {
+ return QAudioFormat();
+ }
+-
++#endif
+ return format;
+ }
+
++#if GST_CHECK_VERSION(1,0,0)
++/*!
++ Returns audio format for a sample.
++ If the buffer doesn't have a valid audio format, an empty QAudioFormat is returned.
++*/
++QAudioFormat QGstUtils::audioFormatForSample(GstSample *sample)
++{
++ GstCaps* caps = gst_sample_get_caps(sample);
++ if (!caps)
++ return QAudioFormat();
+
++ return QGstUtils::audioFormatForCaps(caps);
++}
++#else
+ /*!
+ Returns audio format for a buffer.
+ If the buffer doesn't have a valid audio format, an empty QAudioFormat is returned.
+ */
+-
+ QAudioFormat QGstUtils::audioFormatForBuffer(GstBuffer *buffer)
+ {
+ GstCaps* caps = gst_buffer_get_caps(buffer);
+@@ -269,7 +350,7 @@ QAudioFormat QGstUtils::audioFormatForBuffer(GstBuffer *buffer)
+ gst_caps_unref(caps);
+ return format;
+ }
+-
++#endif
+
+ /*!
+ Builds GstCaps for an audio format.
+@@ -277,8 +358,32 @@ QAudioFormat QGstUtils::audioFormatForBuffer(GstBuffer *buffer)
+ Caller must unref GstCaps.
+ */
+
+-GstCaps *QGstUtils::capsForAudioFormat(QAudioFormat format)
++GstCaps *QGstUtils::capsForAudioFormat(const QAudioFormat &format)
+ {
++ if (!format.isValid())
++ return 0;
++
++#if GST_CHECK_VERSION(1,0,0)
++ const QAudioFormat::SampleType sampleType = format.sampleType();
++ const QAudioFormat::Endian byteOrder = format.byteOrder();
++ const int sampleSize = format.sampleSize();
++
++ for (int i = 0; i < lengthOf(qt_audioLookup); ++i) {
++ if (qt_audioLookup[i].sampleType != sampleType
++ || qt_audioLookup[i].byteOrder != byteOrder
++ || qt_audioLookup[i].sampleSize != sampleSize) {
++ continue;
++ }
++
++ return gst_caps_new_simple(
++ "audio/x-raw",
++ "format" , G_TYPE_STRING, gst_audio_format_to_string(qt_audioLookup[i].format),
++ "rate" , G_TYPE_INT , format.sampleRate(),
++ "channels", G_TYPE_INT , format.channelCount(),
++ NULL);
++ }
++ return 0;
++#else
+ GstStructure *structure = 0;
+
+ if (format.isValid()) {
+@@ -313,6 +418,7 @@ GstCaps *QGstUtils::capsForAudioFormat(QAudioFormat format)
+ }
+
+ return caps;
++#endif
+ }
+
+ void QGstUtils::initializeGst()
+@@ -576,10 +682,629 @@ QByteArray QGstUtils::cameraDriver(const QString &device, GstElementFactory *fac
+ return QByteArray();
+ }
+
++QSet<QString> QGstUtils::supportedMimeTypes(bool (*isValidFactory)(GstElementFactory *factory))
++{
++ QSet<QString> supportedMimeTypes;
++
++ //enumerate supported mime types
++ gst_init(NULL, NULL);
++
++#if GST_CHECK_VERSION(1,0,0)
++ GstRegistry *registry = gst_registry_get();
++ GList *orig_plugins = gst_registry_get_plugin_list(registry);
++#else
++ GstRegistry *registry = gst_registry_get_default();
++ GList *orig_plugins = gst_default_registry_get_plugin_list ();
++#endif
++ for (GList *plugins = orig_plugins; plugins; plugins = g_list_next(plugins)) {
++ GstPlugin *plugin = (GstPlugin *) (plugins->data);
++#if GST_CHECK_VERSION(1,0,0)
++ if (GST_OBJECT_FLAG_IS_SET(GST_OBJECT(plugin), GST_PLUGIN_FLAG_BLACKLISTED))
++ continue;
++#else
++ if (plugin->flags & (1<<1)) //GST_PLUGIN_FLAG_BLACKLISTED
++ continue;
++#endif
++
++ GList *orig_features = gst_registry_get_feature_list_by_plugin(
++ registry, gst_plugin_get_name(plugin));
++ for (GList *features = orig_features; features; features = g_list_next(features)) {
++ if (G_UNLIKELY(features->data == NULL))
++ continue;
++
++ GstPluginFeature *feature = GST_PLUGIN_FEATURE(features->data);
++ GstElementFactory *factory;
++
++ if (GST_IS_TYPE_FIND_FACTORY(feature)) {
++ QString name(gst_plugin_feature_get_name(feature));
++ if (name.contains('/')) //filter out any string without '/' which is obviously not a mime type
++ supportedMimeTypes.insert(name.toLower());
++ continue;
++ } else if (!GST_IS_ELEMENT_FACTORY (feature)
++ || !(factory = GST_ELEMENT_FACTORY(gst_plugin_feature_load(feature)))) {
++ continue;
++ } else if (!isValidFactory(factory)) {
++ // Do nothing
++ } else for (const GList *pads = gst_element_factory_get_static_pad_templates(factory);
++ pads;
++ pads = g_list_next(pads)) {
++ GstStaticPadTemplate *padtemplate = static_cast<GstStaticPadTemplate *>(pads->data);
++
++ if (padtemplate->direction == GST_PAD_SINK && padtemplate->static_caps.string) {
++ GstCaps *caps = gst_static_caps_get(&padtemplate->static_caps);
++ if (gst_caps_is_any(caps) || gst_caps_is_empty(caps)) {
++ } else for (guint i = 0; i < gst_caps_get_size(caps); i++) {
++ GstStructure *structure = gst_caps_get_structure(caps, i);
++ QString nameLowcase = QString(gst_structure_get_name(structure)).toLower();
++
++ supportedMimeTypes.insert(nameLowcase);
++ if (nameLowcase.contains("mpeg")) {
++ //Because mpeg version number is only included in the detail
++ //description, it is necessary to manually extract this information
++ //in order to match the mime type of mpeg4.
++ const GValue *value = gst_structure_get_value(structure, "mpegversion");
++ if (value) {
++ gchar *str = gst_value_serialize(value);
++ QString versions(str);
++ QStringList elements = versions.split(QRegExp("\\D+"), QString::SkipEmptyParts);
++ foreach (const QString &e, elements)
++ supportedMimeTypes.insert(nameLowcase + e);
++ g_free(str);
++ }
++ }
++ }
++ }
++ }
++ gst_object_unref(factory);
++ }
++ gst_plugin_feature_list_free(orig_features);
++ }
++ gst_plugin_list_free (orig_plugins);
++
++#if defined QT_SUPPORTEDMIMETYPES_DEBUG
++ QStringList list = supportedMimeTypes.toList();
++ list.sort();
++ if (qgetenv("QT_DEBUG_PLUGINS").toInt() > 0) {
++ foreach (const QString &type, list)
++ qDebug() << type;
++ }
++#endif
++ return supportedMimeTypes;
++}
++
++namespace {
++
++struct ColorFormat { QImage::Format imageFormat; GstVideoFormat gstFormat; };
++static const ColorFormat qt_colorLookup[] =
++{
++ { QImage::Format_RGBX8888, GST_VIDEO_FORMAT_RGBx },
++ { QImage::Format_RGBA8888, GST_VIDEO_FORMAT_RGBA },
++ { QImage::Format_RGB888 , GST_VIDEO_FORMAT_RGB },
++ { QImage::Format_RGB16 , GST_VIDEO_FORMAT_RGB16 }
++};
++
++}
++
++#if GST_CHECK_VERSION(1,0,0)
++QImage QGstUtils::bufferToImage(GstBuffer *buffer, const GstVideoInfo &videoInfo)
++#else
++QImage QGstUtils::bufferToImage(GstBuffer *buffer)
++#endif
++{
++ QImage img;
++
++#if GST_CHECK_VERSION(1,0,0)
++ GstVideoInfo info = videoInfo;
++ GstVideoFrame frame;
++ if (!gst_video_frame_map(&frame, &info, buffer, GST_MAP_READ))
++ return img;
++#else
++ GstCaps *caps = gst_buffer_get_caps(buffer);
++ if (!caps)
++ return img;
++
++ GstStructure *structure = gst_caps_get_structure (caps, 0);
++ gint width = 0;
++ gint height = 0;
++
++ if (!structure
++ || !gst_structure_get_int(structure, "width", &width)
++ || !gst_structure_get_int(structure, "height", &height)
++ || width <= 0
++ || height <= 0) {
++ gst_caps_unref(caps);
++ return img;
++ }
++ gst_caps_unref(caps);
++#endif
++
++#if GST_CHECK_VERSION(1,0,0)
++ if (videoInfo.finfo->format == GST_VIDEO_FORMAT_I420) {
++ const int width = videoInfo.width;
++ const int height = videoInfo.height;
++
++ const int stride[] = { frame.info.stride[0], frame.info.stride[1], frame.info.stride[2] };
++ const uchar *data[] = {
++ static_cast<const uchar *>(frame.data[0]),
++ static_cast<const uchar *>(frame.data[1]),
++ static_cast<const uchar *>(frame.data[2])
++ };
++#else
++ if (qstrcmp(gst_structure_get_name(structure), "video/x-raw-yuv") == 0) {
++ const int stride[] = { width, width / 2, width / 2 };
++ const uchar *data[] = {
++ (const uchar *)buffer->data,
++ (const uchar *)buffer->data + width * height,
++ (const uchar *)buffer->data + width * height * 5 / 4
++ };
++#endif
++ img = QImage(width/2, height/2, QImage::Format_RGB32);
++
++ for (int y=0; y<height; y+=2) {
++ const uchar *yLine = data[0] + (y * stride[0]);
++ const uchar *uLine = data[1] + (y * stride[1] / 2);
++ const uchar *vLine = data[2] + (y * stride[2] / 2);
++
++ for (int x=0; x<width; x+=2) {
++ const qreal Y = 1.164*(yLine[x]-16);
++ const int U = uLine[x/2]-128;
++ const int V = vLine[x/2]-128;
++
++ int b = qBound(0, int(Y + 2.018*U), 255);
++ int g = qBound(0, int(Y - 0.813*V - 0.391*U), 255);
++ int r = qBound(0, int(Y + 1.596*V), 255);
++
++ img.setPixel(x/2,y/2,qRgb(r,g,b));
++ }
++ }
++#if GST_CHECK_VERSION(1,0,0)
++ } else for (int i = 0; i < lengthOf(qt_colorLookup); ++i) {
++ if (qt_colorLookup[i].gstFormat != videoInfo.finfo->format)
++ continue;
++
++ const QImage image(
++ static_cast<const uchar *>(frame.data[0]),
++ videoInfo.width,
++ videoInfo.height,
++ frame.info.stride[0],
++ qt_colorLookup[i].imageFormat);
++ img = image;
++ img.detach();
++
++ break;
++ }
++
++ gst_video_frame_unmap(&frame);
++#else
++ } else if (qstrcmp(gst_structure_get_name(structure), "video/x-raw-rgb") == 0) {
++ QImage::Format format = QImage::Format_Invalid;
++ int bpp = 0;
++ gst_structure_get_int(structure, "bpp", &bpp);
++
++ if (bpp == 24)
++ format = QImage::Format_RGB888;
++ else if (bpp == 32)
++ format = QImage::Format_RGB32;
++
++ if (format != QImage::Format_Invalid) {
++ img = QImage((const uchar *)buffer->data,
++ width,
++ height,
++ format);
++ img.bits(); //detach
++ }
++ }
++#endif
++ return img;
++}
++
++
++namespace {
++
++#if GST_CHECK_VERSION(1,0,0)
++
++struct VideoFormat
++{
++ QVideoFrame::PixelFormat pixelFormat;
++ GstVideoFormat gstFormat;
++};
++
++static const VideoFormat qt_videoFormatLookup[] =
++{
++ { QVideoFrame::Format_YUV420P, GST_VIDEO_FORMAT_I420 },
++ { QVideoFrame::Format_YV12 , GST_VIDEO_FORMAT_YV12 },
++ { QVideoFrame::Format_UYVY , GST_VIDEO_FORMAT_UYVY },
++ { QVideoFrame::Format_YUYV , GST_VIDEO_FORMAT_YUY2 },
++ { QVideoFrame::Format_NV12 , GST_VIDEO_FORMAT_NV12 },
++ { QVideoFrame::Format_NV21 , GST_VIDEO_FORMAT_NV21 },
++ { QVideoFrame::Format_AYUV444, GST_VIDEO_FORMAT_AYUV },
++#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
++ { QVideoFrame::Format_RGB32 , GST_VIDEO_FORMAT_BGRx },
++ { QVideoFrame::Format_BGR32 , GST_VIDEO_FORMAT_RGBx },
++ { QVideoFrame::Format_ARGB32, GST_VIDEO_FORMAT_BGRA },
++ { QVideoFrame::Format_BGRA32, GST_VIDEO_FORMAT_ARGB },
++#else
++ { QVideoFrame::Format_RGB32 , GST_VIDEO_FORMAT_xRGB },
++ { QVideoFrame::Format_BGR32 , GST_VIDEO_FORMAT_xBGR },
++ { QVideoFrame::Format_ARGB32, GST_VIDEO_FORMAT_ARGB },
++ { QVideoFrame::Format_BGRA32, GST_VIDEO_FORMAT_BGRA },
++#endif
++ { QVideoFrame::Format_RGB24 , GST_VIDEO_FORMAT_RGB },
++ { QVideoFrame::Format_BGR24 , GST_VIDEO_FORMAT_BGR },
++ { QVideoFrame::Format_RGB565, GST_VIDEO_FORMAT_RGB16 }
++};
++
++static int indexOfVideoFormat(QVideoFrame::PixelFormat format)
++{
++ for (int i = 0; i < lengthOf(qt_videoFormatLookup); ++i)
++ if (qt_videoFormatLookup[i].pixelFormat == format)
++ return i;
++
++ return -1;
++}
++
++static int indexOfVideoFormat(GstVideoFormat format)
++{
++ for (int i = 0; i < lengthOf(qt_videoFormatLookup); ++i)
++ if (qt_videoFormatLookup[i].gstFormat == format)
++ return i;
++
++ return -1;
++}
++
++#else
++
++struct YuvFormat
++{
++ QVideoFrame::PixelFormat pixelFormat;
++ guint32 fourcc;
++ int bitsPerPixel;
++};
++
++static const YuvFormat qt_yuvColorLookup[] =
++{
++ { QVideoFrame::Format_YUV420P, GST_MAKE_FOURCC('I','4','2','0'), 8 },
++ { QVideoFrame::Format_YV12, GST_MAKE_FOURCC('Y','V','1','2'), 8 },
++ { QVideoFrame::Format_UYVY, GST_MAKE_FOURCC('U','Y','V','Y'), 16 },
++ { QVideoFrame::Format_YUYV, GST_MAKE_FOURCC('Y','U','Y','2'), 16 },
++ { QVideoFrame::Format_NV12, GST_MAKE_FOURCC('N','V','1','2'), 8 },
++ { QVideoFrame::Format_NV21, GST_MAKE_FOURCC('N','V','2','1'), 8 },
++ { QVideoFrame::Format_AYUV444, GST_MAKE_FOURCC('A','Y','U','V'), 32 }
++};
++
++static int indexOfYuvColor(QVideoFrame::PixelFormat format)
++{
++ const int count = sizeof(qt_yuvColorLookup) / sizeof(YuvFormat);
++
++ for (int i = 0; i < count; ++i)
++ if (qt_yuvColorLookup[i].pixelFormat == format)
++ return i;
++
++ return -1;
++}
++
++static int indexOfYuvColor(guint32 fourcc)
++{
++ const int count = sizeof(qt_yuvColorLookup) / sizeof(YuvFormat);
++
++ for (int i = 0; i < count; ++i)
++ if (qt_yuvColorLookup[i].fourcc == fourcc)
++ return i;
++
++ return -1;
++}
++
++struct RgbFormat
++{
++ QVideoFrame::PixelFormat pixelFormat;
++ int bitsPerPixel;
++ int depth;
++ int endianness;
++ int red;
++ int green;
++ int blue;
++ int alpha;
++};
++
++static const RgbFormat qt_rgbColorLookup[] =
++{
++ { QVideoFrame::Format_RGB32 , 32, 24, 4321, 0x0000FF00, 0x00FF0000, int(0xFF000000), 0x00000000 },
++ { QVideoFrame::Format_RGB32 , 32, 24, 1234, 0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000 },
++ { QVideoFrame::Format_BGR32 , 32, 24, 4321, int(0xFF000000), 0x00FF0000, 0x0000FF00, 0x00000000 },
++ { QVideoFrame::Format_BGR32 , 32, 24, 1234, 0x000000FF, 0x0000FF00, 0x00FF0000, 0x00000000 },
++ { QVideoFrame::Format_ARGB32, 32, 24, 4321, 0x0000FF00, 0x00FF0000, int(0xFF000000), 0x000000FF },
++ { QVideoFrame::Format_ARGB32, 32, 24, 1234, 0x00FF0000, 0x0000FF00, 0x000000FF, int(0xFF000000) },
++ { QVideoFrame::Format_RGB24 , 24, 24, 4321, 0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000 },
++ { QVideoFrame::Format_BGR24 , 24, 24, 4321, 0x000000FF, 0x0000FF00, 0x00FF0000, 0x00000000 },
++ { QVideoFrame::Format_RGB565, 16, 16, 1234, 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }
++};
++
++static int indexOfRgbColor(
++ int bits, int depth, int endianness, int red, int green, int blue, int alpha)
++{
++ const int count = sizeof(qt_rgbColorLookup) / sizeof(RgbFormat);
++
++ for (int i = 0; i < count; ++i) {
++ if (qt_rgbColorLookup[i].bitsPerPixel == bits
++ && qt_rgbColorLookup[i].depth == depth
++ && qt_rgbColorLookup[i].endianness == endianness
++ && qt_rgbColorLookup[i].red == red
++ && qt_rgbColorLookup[i].green == green
++ && qt_rgbColorLookup[i].blue == blue
++ && qt_rgbColorLookup[i].alpha == alpha) {
++ return i;
++ }
++ }
++ return -1;
++}
++#endif
++
++}
++
++#if GST_CHECK_VERSION(1,0,0)
++
++QVideoSurfaceFormat QGstUtils::formatForCaps(
++ GstCaps *caps, GstVideoInfo *info, QAbstractVideoBuffer::HandleType handleType)
++{
++ if (gst_video_info_from_caps(info, caps)) {
++ int index = indexOfVideoFormat(info->finfo->format);
++
++ if (index != -1) {
++ QVideoSurfaceFormat format(
++ QSize(info->width, info->height),
++ qt_videoFormatLookup[index].pixelFormat,
++ handleType);
++
++ if (info->fps_d > 0)
++ format.setFrameRate(qreal(info->fps_d) / info->fps_n);
++
++ if (info->par_d > 0)
++ format.setPixelAspectRatio(info->par_n, info->par_d);
++
++ return format;
++ }
++ }
++ return QVideoSurfaceFormat();
++}
++
++#else
++
++QVideoSurfaceFormat QGstUtils::formatForCaps(
++ GstCaps *caps, int *bytesPerLine, QAbstractVideoBuffer::HandleType handleType)
++{
++ const GstStructure *structure = gst_caps_get_structure(caps, 0);
++
++ QVideoFrame::PixelFormat pixelFormat = QVideoFrame::Format_Invalid;
++ int bitsPerPixel = 0;
++
++ QSize size;
++ gst_structure_get_int(structure, "width", &size.rwidth());
++ gst_structure_get_int(structure, "height", &size.rheight());
++
++ if (qstrcmp(gst_structure_get_name(structure), "video/x-raw-yuv") == 0) {
++ guint32 fourcc = 0;
++ gst_structure_get_fourcc(structure, "format", &fourcc);
++
++ int index = indexOfYuvColor(fourcc);
++ if (index != -1) {
++ pixelFormat = qt_yuvColorLookup[index].pixelFormat;
++ bitsPerPixel = qt_yuvColorLookup[index].bitsPerPixel;
++ }
++ } else if (qstrcmp(gst_structure_get_name(structure), "video/x-raw-rgb") == 0) {
++ int depth = 0;
++ int endianness = 0;
++ int red = 0;
++ int green = 0;
++ int blue = 0;
++ int alpha = 0;
++
++ gst_structure_get_int(structure, "bpp", &bitsPerPixel);
++ gst_structure_get_int(structure, "depth", &depth);
++ gst_structure_get_int(structure, "endianness", &endianness);
++ gst_structure_get_int(structure, "red_mask", &red);
++ gst_structure_get_int(structure, "green_mask", &green);
++ gst_structure_get_int(structure, "blue_mask", &blue);
++ gst_structure_get_int(structure, "alpha_mask", &alpha);
++
++ int index = indexOfRgbColor(bitsPerPixel, depth, endianness, red, green, blue, alpha);
++
++ if (index != -1)
++ pixelFormat = qt_rgbColorLookup[index].pixelFormat;
++ }
++
++ if (pixelFormat != QVideoFrame::Format_Invalid) {
++ QVideoSurfaceFormat format(size, pixelFormat, handleType);
++
++ QPair<int, int> rate;
++ gst_structure_get_fraction(structure, "framerate", &rate.first, &rate.second);
++
++ if (rate.second)
++ format.setFrameRate(qreal(rate.first)/rate.second);
++
++ gint aspectNum = 0;
++ gint aspectDenum = 0;
++ if (gst_structure_get_fraction(
++ structure, "pixel-aspect-ratio", &aspectNum, &aspectDenum)) {
++ if (aspectDenum > 0)
++ format.setPixelAspectRatio(aspectNum, aspectDenum);
++ }
++
++ if (bytesPerLine)
++ *bytesPerLine = ((size.width() * bitsPerPixel / 8) + 3) & ~3;
++
++ return format;
++ }
++ return QVideoSurfaceFormat();
++}
++
++#endif
++
++GstCaps *QGstUtils::capsForFormats(const QList<QVideoFrame::PixelFormat> &formats)
++{
++ GstCaps *caps = gst_caps_new_empty();
++
++#if GST_CHECK_VERSION(1,0,0)
++ foreach (QVideoFrame::PixelFormat format, formats) {
++ int index = indexOfVideoFormat(format);
++
++ if (index != -1) {
++ gst_caps_append_structure(caps, gst_structure_new(
++ "video/x-raw",
++ "format" , G_TYPE_STRING, gst_video_format_to_string(qt_videoFormatLookup[index].gstFormat),
++ NULL));
++ }
++ }
++#else
++ foreach (QVideoFrame::PixelFormat format, formats) {
++ int index = indexOfYuvColor(format);
++
++ if (index != -1) {
++ gst_caps_append_structure(caps, gst_structure_new(
++ "video/x-raw-yuv",
++ "format", GST_TYPE_FOURCC, qt_yuvColorLookup[index].fourcc,
++ NULL));
++ continue;
++ }
++
++ const int count = sizeof(qt_rgbColorLookup) / sizeof(RgbFormat);
++
++ for (int i = 0; i < count; ++i) {
++ if (qt_rgbColorLookup[i].pixelFormat == format) {
++ GstStructure *structure = gst_structure_new(
++ "video/x-raw-rgb",
++ "bpp" , G_TYPE_INT, qt_rgbColorLookup[i].bitsPerPixel,
++ "depth" , G_TYPE_INT, qt_rgbColorLookup[i].depth,
++ "endianness", G_TYPE_INT, qt_rgbColorLookup[i].endianness,
++ "red_mask" , G_TYPE_INT, qt_rgbColorLookup[i].red,
++ "green_mask", G_TYPE_INT, qt_rgbColorLookup[i].green,
++ "blue_mask" , G_TYPE_INT, qt_rgbColorLookup[i].blue,
++ NULL);
++
++ if (qt_rgbColorLookup[i].alpha != 0) {
++ gst_structure_set(
++ structure, "alpha_mask", G_TYPE_INT, qt_rgbColorLookup[i].alpha, NULL);
++ }
++ gst_caps_append_structure(caps, structure);
++ }
++ }
++ }
++#endif
++
++ gst_caps_set_simple(
++ caps,
++ "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, INT_MAX, 1,
++ "width" , GST_TYPE_INT_RANGE, 1, INT_MAX,
++ "height" , GST_TYPE_INT_RANGE, 1, INT_MAX,
++ NULL);
++
++ return caps;
++}
++
++void QGstUtils::setFrameTimeStamps(QVideoFrame *frame, GstBuffer *buffer)
++{
++ // GStreamer uses nanoseconds, Qt uses microseconds
++ qint64 startTime = GST_BUFFER_TIMESTAMP(buffer);
++ if (startTime >= 0) {
++ frame->setStartTime(startTime/G_GINT64_CONSTANT (1000));
++
++ qint64 duration = GST_BUFFER_DURATION(buffer);
++ if (duration >= 0)
++ frame->setEndTime((startTime + duration)/G_GINT64_CONSTANT (1000));
++ }
++}
++
++void QGstUtils::setMetaData(GstElement *element, const QMap<QByteArray, QVariant> &data)
++{
++ if (!GST_IS_TAG_SETTER(element))
++ return;
++
++ gst_tag_setter_reset_tags(GST_TAG_SETTER(element));
++
++ QMapIterator<QByteArray, QVariant> it(data);
++ while (it.hasNext()) {
++ it.next();
++ const QString tagName = it.key();
++ const QVariant tagValue = it.value();
++
++ switch (tagValue.type()) {
++ case QVariant::String:
++ gst_tag_setter_add_tags(GST_TAG_SETTER(element),
++ GST_TAG_MERGE_REPLACE,
++ tagName.toUtf8().constData(),
++ tagValue.toString().toUtf8().constData(),
++ NULL);
++ break;
++ case QVariant::Int:
++ case QVariant::LongLong:
++ gst_tag_setter_add_tags(GST_TAG_SETTER(element),
++ GST_TAG_MERGE_REPLACE,
++ tagName.toUtf8().constData(),
++ tagValue.toInt(),
++ NULL);
++ break;
++ case QVariant::Double:
++ gst_tag_setter_add_tags(GST_TAG_SETTER(element),
++ GST_TAG_MERGE_REPLACE,
++ tagName.toUtf8().constData(),
++ tagValue.toDouble(),
++ NULL);
++ break;
++ case QVariant::DateTime: {
++ QDateTime date = tagValue.toDateTime().toLocalTime();
++ gst_tag_setter_add_tags(GST_TAG_SETTER(element),
++ GST_TAG_MERGE_REPLACE,
++ tagName.toUtf8().constData(),
++ gst_date_time_new_local_time(
++ date.date().year(), date.date().month(), date.date().day(),
++ date.time().hour(), date.time().minute(), date.time().second()),
++ NULL);
++ break;
++ }
++ default:
++ break;
++ }
++ }
++}
++
++void QGstUtils::setMetaData(GstBin *bin, const QMap<QByteArray, QVariant> &data)
++{
++ GstIterator *elements = gst_bin_iterate_all_by_interface(bin, GST_TYPE_TAG_SETTER);
++#if GST_CHECK_VERSION(1,0,0)
++ GValue item = G_VALUE_INIT;
++ while (gst_iterator_next(elements, &item) == GST_ITERATOR_OK) {
++ GstElement * const element = GST_ELEMENT(g_value_get_object(&item));
++#else
++ GstElement *element = 0;
++ while (gst_iterator_next(elements, (void**)&element) == GST_ITERATOR_OK) {
++#endif
++ setMetaData(element, data);
++ }
++ gst_iterator_free(elements);
++}
++
++
++GstCaps *QGstUtils::videoFilterCaps()
++{
++ static GstStaticCaps staticCaps = GST_STATIC_CAPS(
++#if GST_CHECK_VERSION(1,2,0)
++ "video/x-raw(ANY);"
++#elif GST_CHECK_VERSION(1,0,0)
++ "video/x-raw;"
++#else
++ "video/x-raw-yuv;"
++ "video/x-raw-rgb;"
++ "video/x-raw-data;"
++ "video/x-android-buffer;"
++#endif
++ "image/jpeg;"
++ "video/x-h264");
++
++ return gst_caps_make_writable(gst_static_caps_get(&staticCaps));
++}
+
+ void qt_gst_object_ref_sink(gpointer object)
+ {
+-#if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 24)
++#if GST_CHECK_VERSION(0,10,24)
+ gst_object_ref_sink(object);
+ #else
+ g_return_if_fail (GST_IS_OBJECT(object));
+@@ -595,4 +1320,50 @@ void qt_gst_object_ref_sink(gpointer object)
+ #endif
+ }
+
++GstCaps *qt_gst_pad_get_current_caps(GstPad *pad)
++{
++#if GST_CHECK_VERSION(1,0,0)
++ return gst_pad_get_current_caps(pad);
++#else
++ return gst_pad_get_negotiated_caps(pad);
++#endif
++}
++
++GstStructure *qt_gst_structure_new_empty(const char *name)
++{
++#if GST_CHECK_VERSION(1,0,0)
++ return gst_structure_new_empty(name);
++#else
++ return gst_structure_new(name, NULL);
++#endif
++}
++
++gboolean qt_gst_element_query_position(GstElement *element, GstFormat format, gint64 *cur)
++{
++#if GST_CHECK_VERSION(1,0,0)
++ return gst_element_query_position(element, format, cur);
++#else
++ return gst_element_query_position(element, &format, cur);
++#endif
++}
++
++gboolean qt_gst_element_query_duration(GstElement *element, GstFormat format, gint64 *cur)
++{
++#if GST_CHECK_VERSION(1,0,0)
++ return gst_element_query_duration(element, format, cur);
++#else
++ return gst_element_query_duration(element, &format, cur);
++#endif
++}
++
++QDebug operator <<(QDebug debug, GstCaps *caps)
++{
++ if (caps) {
++ gchar *string = gst_caps_to_string(caps);
++ debug = debug << string;
++ g_free(string);
++ }
++ return debug;
++}
++
+ QT_END_NAMESPACE
+diff --git a/src/gsttools/qgstvideobuffer.cpp b/src/gsttools/qgstvideobuffer.cpp
+index 18702ec..1ce07ca 100644
+--- a/src/gsttools/qgstvideobuffer.cpp
++++ b/src/gsttools/qgstvideobuffer.cpp
+@@ -35,21 +35,35 @@
+
+ QT_BEGIN_NAMESPACE
+
++#if GST_CHECK_VERSION(1,0,0)
++QGstVideoBuffer::QGstVideoBuffer(GstBuffer *buffer, const GstVideoInfo &info)
++ : QAbstractPlanarVideoBuffer(NoHandle)
++ , m_videoInfo(info)
++#else
+ QGstVideoBuffer::QGstVideoBuffer(GstBuffer *buffer, int bytesPerLine)
+ : QAbstractVideoBuffer(NoHandle)
+- , m_buffer(buffer)
+ , m_bytesPerLine(bytesPerLine)
++#endif
++ , m_buffer(buffer)
+ , m_mode(NotMapped)
+ {
+ gst_buffer_ref(m_buffer);
+ }
+
++#if GST_CHECK_VERSION(1,0,0)
++QGstVideoBuffer::QGstVideoBuffer(GstBuffer *buffer, const GstVideoInfo &info,
++ QGstVideoBuffer::HandleType handleType,
++ const QVariant &handle)
++ : QAbstractPlanarVideoBuffer(handleType)
++ , m_videoInfo(info)
++#else
+ QGstVideoBuffer::QGstVideoBuffer(GstBuffer *buffer, int bytesPerLine,
+ QGstVideoBuffer::HandleType handleType,
+ const QVariant &handle)
+ : QAbstractVideoBuffer(handleType)
+- , m_buffer(buffer)
+ , m_bytesPerLine(bytesPerLine)
++#endif
++ , m_buffer(buffer)
+ , m_mode(NotMapped)
+ , m_handle(handle)
+ {
+@@ -58,6 +72,8 @@ QGstVideoBuffer::QGstVideoBuffer(GstBuffer *buffer, int bytesPerLine,
+
+ QGstVideoBuffer::~QGstVideoBuffer()
+ {
++ unmap();
++
+ gst_buffer_unref(m_buffer);
+ }
+
+@@ -67,12 +83,49 @@ QAbstractVideoBuffer::MapMode QGstVideoBuffer::mapMode() const
+ return m_mode;
+ }
+
++#if GST_CHECK_VERSION(1,0,0)
++
++int QGstVideoBuffer::map(MapMode mode, int *numBytes, int bytesPerLine[4], uchar *data[4])
++{
++ const GstMapFlags flags = GstMapFlags(((mode & ReadOnly) ? GST_MAP_READ : 0)
++ | ((mode & WriteOnly) ? GST_MAP_WRITE : 0));
++
++ if (mode == NotMapped || m_mode != NotMapped) {
++ return 0;
++ } else if (m_videoInfo.finfo->n_planes == 0) { // Encoded
++ if (gst_buffer_map(m_buffer, &m_frame.map[0], flags)) {
++ if (numBytes)
++ *numBytes = m_frame.map[0].size;
++ bytesPerLine[0] = -1;
++ data[0] = static_cast<uchar *>(m_frame.map[0].data);
++
++ m_mode = mode;
++
++ return 1;
++ }
++ } else if (gst_video_frame_map(&m_frame, &m_videoInfo, m_buffer, flags)) {
++ if (numBytes)
++ *numBytes = m_frame.info.size;
++
++ for (guint i = 0; i < m_frame.info.finfo->n_planes; ++i) {
++ bytesPerLine[i] = m_frame.info.stride[i];
++ data[i] = static_cast<uchar *>(m_frame.data[i]);
++ }
++
++ m_mode = mode;
++
++ return m_frame.info.finfo->n_planes;
++ }
++ return 0;
++}
++
++#else
++
+ uchar *QGstVideoBuffer::map(MapMode mode, int *numBytes, int *bytesPerLine)
+ {
+ if (mode != NotMapped && m_mode == NotMapped) {
+ if (numBytes)
+ *numBytes = m_buffer->size;
+-
+ if (bytesPerLine)
+ *bytesPerLine = m_bytesPerLine;
+
+@@ -83,8 +136,19 @@ uchar *QGstVideoBuffer::map(MapMode mode, int *numBytes, int *bytesPerLine)
+ return 0;
+ }
+ }
++
++#endif
++
+ void QGstVideoBuffer::unmap()
+ {
++#if GST_CHECK_VERSION(1,0,0)
++ if (m_mode != NotMapped) {
++ if (m_videoInfo.finfo->n_planes == 0)
++ gst_buffer_unmap(m_buffer, &m_frame.map[0]);
++ else
++ gst_video_frame_unmap(&m_frame);
++ }
++#endif
+ m_mode = NotMapped;
+ }
+
+diff --git a/src/gsttools/qgstvideorendererplugin.cpp b/src/gsttools/qgstvideorendererplugin.cpp
+new file mode 100644
+index 0000000..5eda85a
+--- /dev/null
++++ b/src/gsttools/qgstvideorendererplugin.cpp
+@@ -0,0 +1,53 @@
++/****************************************************************************
++**
++** Copyright (C) 2014 Jolla Ltd.
++** Contact: http://www.qt-project.org/legal
++**
++** This file is part of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:LGPL$
++** 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 Digia. For licensing terms and
++** conditions see http://qt.digia.com/licensing. For further information
++** use the contact form at http://qt.digia.com/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 as published by the Free Software
++** Foundation and appearing in the file LICENSE.LGPL included in the
++** packaging of this file. Please review the following information to
++** ensure the GNU Lesser General Public License version 2.1 requirements
++** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
++**
++** In addition, as a special exception, Digia gives you certain additional
++** rights. These rights are described in the Digia Qt LGPL Exception
++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
++**
++** GNU General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU
++** General Public License version 3.0 as published by the Free Software
++** Foundation and appearing in the file LICENSE.GPL included in the
++** packaging of this file. Please review the following information to
++** ensure the GNU General Public License version 3.0 requirements will be
++** met: http://www.gnu.org/copyleft/gpl.html.
++**
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++#include "qgstvideorendererplugin_p.h"
++
++QT_BEGIN_NAMESPACE
++
++QGstVideoRendererPlugin::QGstVideoRendererPlugin(QObject *parent) :
++ QObject(parent)
++{
++}
++
++QT_END_NAMESPACE
++
++#include "moc_qgstvideorendererplugin_p.cpp"
+diff --git a/src/gsttools/qgstvideorenderersink.cpp b/src/gsttools/qgstvideorenderersink.cpp
+new file mode 100644
+index 0000000..1102c2a
+--- /dev/null
++++ b/src/gsttools/qgstvideorenderersink.cpp
+@@ -0,0 +1,605 @@
++/****************************************************************************
++**
++** Copyright (C) 2014 Jolla Ltd.
++** Contact: http://www.qt-project.org/legal
++**
++** This file is part of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:LGPL$
++** 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 Digia. For licensing terms and
++** conditions see http://qt.digia.com/licensing. For further information
++** use the contact form at http://qt.digia.com/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 as published by the Free Software
++** Foundation and appearing in the file LICENSE.LGPL included in the
++** packaging of this file. Please review the following information to
++** ensure the GNU Lesser General Public License version 2.1 requirements
++** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
++**
++** In addition, as a special exception, Digia gives you certain additional
++** rights. These rights are described in the Digia Qt LGPL Exception
++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
++**
++** GNU General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU
++** General Public License version 3.0 as published by the Free Software
++** Foundation and appearing in the file LICENSE.GPL included in the
++** packaging of this file. Please review the following information to
++** ensure the GNU General Public License version 3.0 requirements will be
++** met: http://www.gnu.org/copyleft/gpl.html.
++**
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++#include <qabstractvideosurface.h>
++#include <qvideoframe.h>
++#include <QDebug>
++#include <QMap>
++#include <QThread>
++#include <QEvent>
++#include <QCoreApplication>
++
++#include <private/qmediapluginloader_p.h>
++#include "qgstvideobuffer_p.h"
++
++#include "qgstvideorenderersink_p.h"
++
++#include <gst/video/video.h>
++
++#include "qgstutils_p.h"
++
++//#define DEBUG_VIDEO_SURFACE_SINK
++
++QT_BEGIN_NAMESPACE
++
++QGstDefaultVideoRenderer::QGstDefaultVideoRenderer()
++ : m_flushed(true)
++{
++}
++
++QGstDefaultVideoRenderer::~QGstDefaultVideoRenderer()
++{
++}
++
++GstCaps *QGstDefaultVideoRenderer::getCaps(QAbstractVideoSurface *surface)
++{
++ return QGstUtils::capsForFormats(surface->supportedPixelFormats());
++}
++
++bool QGstDefaultVideoRenderer::start(QAbstractVideoSurface *surface, GstCaps *caps)
++{
++ m_flushed = true;
++ m_format = QGstUtils::formatForCaps(caps, &m_videoInfo);
++
++ return m_format.isValid() && surface->start(m_format);
++}
++
++void QGstDefaultVideoRenderer::stop(QAbstractVideoSurface *surface)
++{
++ m_flushed = true;
++ if (surface)
++ surface->stop();
++}
++
++bool QGstDefaultVideoRenderer::present(QAbstractVideoSurface *surface, GstBuffer *buffer)
++{
++ m_flushed = false;
++ QVideoFrame frame(
++ new QGstVideoBuffer(buffer, m_videoInfo),
++ m_format.frameSize(),
++ m_format.pixelFormat());
++ QGstUtils::setFrameTimeStamps(&frame, buffer);
++
++ return surface->present(frame);
++}
++
++void QGstDefaultVideoRenderer::flush(QAbstractVideoSurface *surface)
++{
++ if (surface && !m_flushed)
++ surface->present(QVideoFrame());
++ m_flushed = true;
++}
++
++bool QGstDefaultVideoRenderer::proposeAllocation(GstQuery *)
++{
++ return true;
++}
++
++Q_GLOBAL_STATIC_WITH_ARGS(QMediaPluginLoader, rendererLoader,
++ (QGstVideoRendererInterface_iid, QLatin1String("video/gstvideorenderer"), Qt::CaseInsensitive))
++
++QVideoSurfaceGstDelegate::QVideoSurfaceGstDelegate(QAbstractVideoSurface *surface)
++ : m_surface(surface)
++ , m_renderer(0)
++ , m_activeRenderer(0)
++ , m_surfaceCaps(0)
++ , m_startCaps(0)
++ , m_lastBuffer(0)
++ , m_notified(false)
++ , m_stop(false)
++ , m_render(false)
++ , m_flush(false)
++{
++ foreach (QObject *instance, rendererLoader()->instances(QGstVideoRendererPluginKey)) {
++ QGstVideoRendererInterface* plugin = qobject_cast<QGstVideoRendererInterface*>(instance);
++ if (QGstVideoRenderer *renderer = plugin ? plugin->createRenderer() : 0)
++ m_renderers.append(renderer);
++ }
++
++ m_renderers.append(new QGstDefaultVideoRenderer);
++ updateSupportedFormats();
++ connect(m_surface, SIGNAL(supportedFormatsChanged()), this, SLOT(updateSupportedFormats()));
++}
++
++QVideoSurfaceGstDelegate::~QVideoSurfaceGstDelegate()
++{
++ qDeleteAll(m_renderers);
++
++ if (m_surfaceCaps)
++ gst_caps_unref(m_surfaceCaps);
++}
++
++GstCaps *QVideoSurfaceGstDelegate::caps()
++{
++ QMutexLocker locker(&m_mutex);
++
++ gst_caps_ref(m_surfaceCaps);
++
++ return m_surfaceCaps;
++}
++
++bool QVideoSurfaceGstDelegate::start(GstCaps *caps)
++{
++ QMutexLocker locker(&m_mutex);
++
++ if (m_activeRenderer) {
++ m_flush = true;
++ m_stop = true;
++ }
++
++ m_render = false;
++
++ if (m_lastBuffer) {
++ gst_buffer_unref(m_lastBuffer);
++ m_lastBuffer = 0;
++ }
++
++ if (m_startCaps)
++ gst_caps_unref(m_startCaps);
++ m_startCaps = caps;
++ gst_caps_ref(m_startCaps);
++
++ /*
++ Waiting for start() to be invoked in the main thread may block
++ if gstreamer blocks the main thread until this call is finished.
++ This situation is rare and usually caused by setState(Null)
++ while pipeline is being prerolled.
++
++ The proper solution to this involves controlling gstreamer pipeline from
++ other thread than video surface.
++
++ Currently start() fails if wait() timed out.
++ */
++ if (!waitForAsyncEvent(&locker, &m_setupCondition, 1000) && m_startCaps) {
++ qWarning() << "Failed to start video surface due to main thread blocked.";
++ gst_caps_unref(m_startCaps);
++ m_startCaps = 0;
++ }
++
++ return m_activeRenderer != 0;
++}
++
++void QVideoSurfaceGstDelegate::stop()
++{
++ QMutexLocker locker(&m_mutex);
++
++ if (!m_activeRenderer)
++ return;
++
++ m_flush = true;
++ m_stop = true;
++
++ if (m_startCaps) {
++ gst_caps_unref(m_startCaps);
++ m_startCaps = 0;
++ }
++
++ if (m_lastBuffer) {
++ gst_buffer_unref(m_lastBuffer);
++ m_lastBuffer = 0;
++ }
++
++ waitForAsyncEvent(&locker, &m_setupCondition, 500);
++}
++
++bool QVideoSurfaceGstDelegate::proposeAllocation(GstQuery *query)
++{
++ QMutexLocker locker(&m_mutex);
++
++ if (QGstVideoRenderer *pool = m_activeRenderer) {
++ locker.unlock();
++
++ return pool->proposeAllocation(query);
++ } else {
++ return false;
++ }
++}
++
++void QVideoSurfaceGstDelegate::flush()
++{
++ QMutexLocker locker(&m_mutex);
++
++ m_flush = true;
++ m_render = false;
++
++ if (m_lastBuffer) {
++ gst_buffer_unref(m_lastBuffer);
++ m_lastBuffer = 0;
++ }
++
++ notify();
++}
++
++GstFlowReturn QVideoSurfaceGstDelegate::render(GstBuffer *buffer, bool show)
++{
++ QMutexLocker locker(&m_mutex);
++
++ if (m_lastBuffer)
++ gst_buffer_unref(m_lastBuffer);
++ m_lastBuffer = buffer;
++ gst_buffer_ref(m_lastBuffer);
++
++ if (show) {
++ m_render = true;
++
++ return waitForAsyncEvent(&locker, &m_renderCondition, 300)
++ ? m_renderReturn
++ : GST_FLOW_ERROR;
++ } else {
++ return GST_FLOW_OK;
++ }
++}
++
++void QVideoSurfaceGstDelegate::handleShowPrerollChange(GObject *object, GParamSpec *, gpointer d)
++{
++ QVideoSurfaceGstDelegate * const delegate = static_cast<QVideoSurfaceGstDelegate *>(d);
++
++ gboolean showPreroll = true; // "show-preroll-frame" property is true by default
++ g_object_get(object, "show-preroll-frame", &showPreroll, NULL);
++
++ GstState state = GST_STATE_NULL;
++ GstState pendingState = GST_STATE_NULL;
++ gst_element_get_state(GST_ELEMENT(object), &state, &pendingState, 0);
++
++ const bool paused
++ = (pendingState == GST_STATE_VOID_PENDING && state == GST_STATE_PAUSED)
++ || pendingState == GST_STATE_PAUSED;
++
++ if (paused) {
++ QMutexLocker locker(&delegate->m_mutex);
++
++ if (!showPreroll && delegate->m_lastBuffer) {
++ delegate->m_render = false;
++ delegate->m_flush = true;
++ delegate->notify();
++ } else if (delegate->m_lastBuffer) {
++ delegate->m_render = true;
++ delegate->notify();
++ }
++ }
++}
++
++bool QVideoSurfaceGstDelegate::event(QEvent *event)
++{
++ if (event->type() == QEvent::UpdateRequest) {
++ QMutexLocker locker(&m_mutex);
++
++ if (m_notified) {
++ while (handleEvent(&locker)) {}
++ m_notified = false;
++ }
++ return true;
++ } else {
++ return QObject::event(event);
++ }
++}
++
++bool QVideoSurfaceGstDelegate::handleEvent(QMutexLocker *locker)
++{
++ if (m_flush) {
++ m_flush = false;
++ if (m_activeRenderer) {
++ locker->unlock();
++
++ m_activeRenderer->flush(m_surface);
++ }
++ } else if (m_stop) {
++ m_stop = false;
++
++ if (QGstVideoRenderer * const activePool = m_activeRenderer) {
++ m_activeRenderer = 0;
++ locker->unlock();
++
++ activePool->stop(m_surface);
++
++ locker->relock();
++ }
++ } else if (m_startCaps) {
++ Q_ASSERT(!m_activeRenderer);
++
++ GstCaps * const startCaps = m_startCaps;
++ m_startCaps = 0;
++
++ if (m_renderer && m_surface) {
++ locker->unlock();
++
++ const bool started = m_renderer->start(m_surface, startCaps);
++
++ locker->relock();
++
++ m_activeRenderer = started
++ ? m_renderer
++ : 0;
++ } else if (QGstVideoRenderer * const activePool = m_activeRenderer) {
++ m_activeRenderer = 0;
++ locker->unlock();
++
++ activePool->stop(m_surface);
++
++ locker->relock();
++ }
++
++ gst_caps_unref(startCaps);
++ } else if (m_render) {
++ m_render = false;
++
++ if (m_activeRenderer && m_surface && m_lastBuffer) {
++ GstBuffer *buffer = m_lastBuffer;
++ gst_buffer_ref(buffer);
++
++ locker->unlock();
++
++ const bool rendered = m_activeRenderer->present(m_surface, buffer);
++
++ gst_buffer_unref(buffer);
++
++ locker->relock();
++
++ m_renderReturn = rendered
++ ? GST_FLOW_OK
++ : GST_FLOW_ERROR;
++
++ m_renderCondition.wakeAll();
++ } else {
++ m_renderReturn = GST_FLOW_ERROR;
++ m_renderCondition.wakeAll();
++ }
++ } else {
++ m_setupCondition.wakeAll();
++
++ return false;
++ }
++ return true;
++}
++
++void QVideoSurfaceGstDelegate::notify()
++{
++ if (!m_notified) {
++ m_notified = true;
++ QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
++ }
++}
++
++bool QVideoSurfaceGstDelegate::waitForAsyncEvent(
++ QMutexLocker *locker, QWaitCondition *condition, unsigned long time)
++{
++ if (QThread::currentThread() == thread()) {
++ while (handleEvent(locker)) {}
++ m_notified = false;
++
++ return true;
++ } else {
++ notify();
++
++ return condition->wait(&m_mutex, time);
++ }
++}
++
++void QVideoSurfaceGstDelegate::updateSupportedFormats()
++{
++ if (m_surfaceCaps) {
++ gst_caps_unref(m_surfaceCaps);
++ m_surfaceCaps = 0;
++ }
++
++ foreach (QGstVideoRenderer *pool, m_renderers) {
++ if (GstCaps *caps = pool->getCaps(m_surface)) {
++ if (gst_caps_is_empty(caps)) {
++ gst_caps_unref(caps);
++ continue;
++ }
++
++ if (m_surfaceCaps)
++ gst_caps_unref(m_surfaceCaps);
++
++ m_renderer = pool;
++ m_surfaceCaps = caps;
++ break;
++ } else {
++ gst_caps_unref(caps);
++ }
++ }
++}
++
++static GstVideoSinkClass *sink_parent_class;
++
++#define VO_SINK(s) QGstVideoRendererSink *sink(reinterpret_cast<QGstVideoRendererSink *>(s))
++
++QGstVideoRendererSink *QGstVideoRendererSink::createSink(QAbstractVideoSurface *surface)
++{
++ QGstVideoRendererSink *sink = reinterpret_cast<QGstVideoRendererSink *>(
++ g_object_new(QGstVideoRendererSink::get_type(), 0));
++
++ sink->delegate = new QVideoSurfaceGstDelegate(surface);
++
++ g_signal_connect(
++ G_OBJECT(sink),
++ "notify::show-preroll-frame",
++ G_CALLBACK(QVideoSurfaceGstDelegate::handleShowPrerollChange),
++ sink->delegate);
++
++ return sink;
++}
++
++GType QGstVideoRendererSink::get_type()
++{
++ static GType type = 0;
++
++ if (type == 0) {
++ static const GTypeInfo info =
++ {
++ sizeof(QGstVideoRendererSinkClass), // class_size
++ base_init, // base_init
++ NULL, // base_finalize
++ class_init, // class_init
++ NULL, // class_finalize
++ NULL, // class_data
++ sizeof(QGstVideoRendererSink), // instance_size
++ 0, // n_preallocs
++ instance_init, // instance_init
++ 0 // value_table
++ };
++
++ type = g_type_register_static(
++ GST_TYPE_VIDEO_SINK, "QGstVideoRendererSink", &info, GTypeFlags(0));
++ }
++
++ return type;
++}
++
++void QGstVideoRendererSink::class_init(gpointer g_class, gpointer class_data)
++{
++ Q_UNUSED(class_data);
++
++ sink_parent_class = reinterpret_cast<GstVideoSinkClass *>(g_type_class_peek_parent(g_class));
++
++ GstBaseSinkClass *base_sink_class = reinterpret_cast<GstBaseSinkClass *>(g_class);
++ base_sink_class->get_caps = QGstVideoRendererSink::get_caps;
++ base_sink_class->set_caps = QGstVideoRendererSink::set_caps;
++ base_sink_class->propose_allocation = QGstVideoRendererSink::propose_allocation;
++ base_sink_class->preroll = QGstVideoRendererSink::preroll;
++ base_sink_class->render = QGstVideoRendererSink::render;
++
++ GstElementClass *element_class = reinterpret_cast<GstElementClass *>(g_class);
++ element_class->change_state = QGstVideoRendererSink::change_state;
++
++ GObjectClass *object_class = reinterpret_cast<GObjectClass *>(g_class);
++ object_class->finalize = QGstVideoRendererSink::finalize;
++}
++
++void QGstVideoRendererSink::base_init(gpointer g_class)
++{
++ static GstStaticPadTemplate sink_pad_template = GST_STATIC_PAD_TEMPLATE(
++ "sink", GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS(
++ "video/x-raw, "
++ "framerate = (fraction) [ 0, MAX ], "
++ "width = (int) [ 1, MAX ], "
++ "height = (int) [ 1, MAX ]"));
++
++ gst_element_class_add_pad_template(
++ GST_ELEMENT_CLASS(g_class), gst_static_pad_template_get(&sink_pad_template));
++}
++
++void QGstVideoRendererSink::instance_init(GTypeInstance *instance, gpointer g_class)
++{
++ VO_SINK(instance);
++
++ Q_UNUSED(g_class);
++
++ sink->delegate = 0;
++}
++
++void QGstVideoRendererSink::finalize(GObject *object)
++{
++ VO_SINK(object);
++
++ delete sink->delegate;
++
++ // Chain up
++ G_OBJECT_CLASS(sink_parent_class)->finalize(object);
++}
++
++GstStateChangeReturn QGstVideoRendererSink::change_state(
++ GstElement *element, GstStateChange transition)
++{
++ Q_UNUSED(element);
++
++ return GST_ELEMENT_CLASS(sink_parent_class)->change_state(
++ element, transition);
++}
++
++GstCaps *QGstVideoRendererSink::get_caps(GstBaseSink *base, GstCaps *filter)
++{
++ VO_SINK(base);
++
++ GstCaps *caps = sink->delegate->caps();
++ GstCaps *unfiltered = caps;
++ if (filter) {
++ caps = gst_caps_intersect(unfiltered, filter);
++ gst_caps_unref(unfiltered);
++ }
++
++ return caps;
++}
++
++gboolean QGstVideoRendererSink::set_caps(GstBaseSink *base, GstCaps *caps)
++{
++ VO_SINK(base);
++
++#ifdef DEBUG_VIDEO_SURFACE_SINK
++ qDebug() << "set_caps:";
++ qDebug() << caps;
++#endif
++
++ if (!caps) {
++ sink->delegate->stop();
++
++ return TRUE;
++ } else if (sink->delegate->start(caps)) {
++ return TRUE;
++ } else {
++ return FALSE;
++ }
++}
++
++gboolean QGstVideoRendererSink::propose_allocation(GstBaseSink *base, GstQuery *query)
++{
++ VO_SINK(base);
++ return sink->delegate->proposeAllocation(query);
++}
++
++GstFlowReturn QGstVideoRendererSink::preroll(GstBaseSink *base, GstBuffer *buffer)
++{
++ VO_SINK(base);
++
++ gboolean showPreroll = true; // "show-preroll-frame" property is true by default
++ g_object_get(G_OBJECT(base), "show-preroll-frame", &showPreroll, NULL);
++
++ return sink->delegate->render(buffer, showPreroll); // display frame
++}
++
++GstFlowReturn QGstVideoRendererSink::render(GstBaseSink *base, GstBuffer *buffer)
++{
++ VO_SINK(base);
++ return sink->delegate->render(buffer, true);
++}
++
++QT_END_NAMESPACE
+diff --git a/src/gsttools/qvideosurfacegstsink.cpp b/src/gsttools/qvideosurfacegstsink.cpp
+index f3e2d88..147db66 100644
+--- a/src/gsttools/qvideosurfacegstsink.cpp
++++ b/src/gsttools/qvideosurfacegstsink.cpp
+@@ -41,8 +41,13 @@
+ #include <private/qmediapluginloader_p.h>
+ #include "qgstvideobuffer_p.h"
+
++#include "qgstutils_p.h"
+ #include "qvideosurfacegstsink_p.h"
+
++#if GST_VERSION_MAJOR >=1
++#include <gst/video/video.h>
++#endif
++
+ //#define DEBUG_VIDEO_SURFACE_SINK
+
+ QT_BEGIN_NAMESPACE
+@@ -62,10 +67,12 @@ QVideoSurfaceGstDelegate::QVideoSurfaceGstDelegate(
+ if (m_surface) {
+ foreach (QObject *instance, bufferPoolLoader()->instances(QGstBufferPoolPluginKey)) {
+ QGstBufferPoolInterface* plugin = qobject_cast<QGstBufferPoolInterface*>(instance);
++
+ if (plugin) {
+ m_pools.append(plugin);
+ }
+ }
++
+ updateSupportedFormats();
+ connect(m_surface, SIGNAL(supportedFormatsChanged()), this, SLOT(updateSupportedFormats()));
+ }
+@@ -191,13 +198,15 @@ GstFlowReturn QVideoSurfaceGstDelegate::render(GstBuffer *buffer)
+ m_format.frameSize(),
+ m_format.pixelFormat());
+
+- QVideoSurfaceGstSink::setFrameTimeStamps(&m_frame, buffer);
++ QGstUtils::setFrameTimeStamps(&m_frame, buffer);
+
+ m_renderReturn = GST_FLOW_OK;
+
+ if (QThread::currentThread() == thread()) {
+ if (!m_surface.isNull())
+ m_surface->present(m_frame);
++ else
++ qWarning() << "m_surface.isNull().";
+ } else {
+ QMetaObject::invokeMethod(this, "queuedRender", Qt::QueuedConnection);
+ m_renderCondition.wait(&m_mutex, 300);
+@@ -283,90 +292,6 @@ void QVideoSurfaceGstDelegate::updateSupportedFormats()
+ }
+ }
+
+-struct YuvFormat
+-{
+- QVideoFrame::PixelFormat pixelFormat;
+- guint32 fourcc;
+- int bitsPerPixel;
+-};
+-
+-static const YuvFormat qt_yuvColorLookup[] =
+-{
+- { QVideoFrame::Format_YUV420P, GST_MAKE_FOURCC('I','4','2','0'), 8 },
+- { QVideoFrame::Format_YV12, GST_MAKE_FOURCC('Y','V','1','2'), 8 },
+- { QVideoFrame::Format_UYVY, GST_MAKE_FOURCC('U','Y','V','Y'), 16 },
+- { QVideoFrame::Format_YUYV, GST_MAKE_FOURCC('Y','U','Y','2'), 16 },
+- { QVideoFrame::Format_NV12, GST_MAKE_FOURCC('N','V','1','2'), 8 },
+- { QVideoFrame::Format_NV21, GST_MAKE_FOURCC('N','V','2','1'), 8 },
+- { QVideoFrame::Format_AYUV444, GST_MAKE_FOURCC('A','Y','U','V'), 32 }
+-};
+-
+-static int indexOfYuvColor(QVideoFrame::PixelFormat format)
+-{
+- const int count = sizeof(qt_yuvColorLookup) / sizeof(YuvFormat);
+-
+- for (int i = 0; i < count; ++i)
+- if (qt_yuvColorLookup[i].pixelFormat == format)
+- return i;
+-
+- return -1;
+-}
+-
+-static int indexOfYuvColor(guint32 fourcc)
+-{
+- const int count = sizeof(qt_yuvColorLookup) / sizeof(YuvFormat);
+-
+- for (int i = 0; i < count; ++i)
+- if (qt_yuvColorLookup[i].fourcc == fourcc)
+- return i;
+-
+- return -1;
+-}
+-
+-struct RgbFormat
+-{
+- QVideoFrame::PixelFormat pixelFormat;
+- int bitsPerPixel;
+- int depth;
+- int endianness;
+- int red;
+- int green;
+- int blue;
+- int alpha;
+-};
+-
+-static const RgbFormat qt_rgbColorLookup[] =
+-{
+- { QVideoFrame::Format_RGB32 , 32, 24, 4321, 0x0000FF00, 0x00FF0000, int(0xFF000000), 0x00000000 },
+- { QVideoFrame::Format_RGB32 , 32, 24, 1234, 0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000 },
+- { QVideoFrame::Format_BGR32 , 32, 24, 4321, int(0xFF000000), 0x00FF0000, 0x0000FF00, 0x00000000 },
+- { QVideoFrame::Format_BGR32 , 32, 24, 1234, 0x000000FF, 0x0000FF00, 0x00FF0000, 0x00000000 },
+- { QVideoFrame::Format_ARGB32, 32, 24, 4321, 0x0000FF00, 0x00FF0000, int(0xFF000000), 0x000000FF },
+- { QVideoFrame::Format_ARGB32, 32, 24, 1234, 0x00FF0000, 0x0000FF00, 0x000000FF, int(0xFF000000) },
+- { QVideoFrame::Format_RGB24 , 24, 24, 4321, 0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000 },
+- { QVideoFrame::Format_BGR24 , 24, 24, 4321, 0x000000FF, 0x0000FF00, 0x00FF0000, 0x00000000 },
+- { QVideoFrame::Format_RGB565, 16, 16, 1234, 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }
+-};
+-
+-static int indexOfRgbColor(
+- int bits, int depth, int endianness, int red, int green, int blue, int alpha)
+-{
+- const int count = sizeof(qt_rgbColorLookup) / sizeof(RgbFormat);
+-
+- for (int i = 0; i < count; ++i) {
+- if (qt_rgbColorLookup[i].bitsPerPixel == bits
+- && qt_rgbColorLookup[i].depth == depth
+- && qt_rgbColorLookup[i].endianness == endianness
+- && qt_rgbColorLookup[i].red == red
+- && qt_rgbColorLookup[i].green == green
+- && qt_rgbColorLookup[i].blue == blue
+- && qt_rgbColorLookup[i].alpha == alpha) {
+- return i;
+- }
+- }
+- return -1;
+-}
+-
+ static GstVideoSinkClass *sink_parent_class;
+
+ #define VO_SINK(s) QVideoSurfaceGstSink *sink(reinterpret_cast<QVideoSurfaceGstSink *>(s))
+@@ -494,8 +419,6 @@ GstCaps *QVideoSurfaceGstSink::get_caps(GstBaseSink *base)
+ {
+ VO_SINK(base);
+
+- GstCaps *caps = gst_caps_new_empty();
+-
+ // Find the supported pixel formats
+ // with buffer pool specific formats listed first
+ QList<QVideoFrame::PixelFormat> supportedFormats;
+@@ -503,6 +426,7 @@ GstCaps *QVideoSurfaceGstSink::get_caps(GstBaseSink *base)
+ QList<QVideoFrame::PixelFormat> poolHandleFormats;
+ sink->delegate->poolMutex()->lock();
+ QGstBufferPoolInterface *pool = sink->delegate->pool();
++
+ if (pool)
+ poolHandleFormats = sink->delegate->supportedPixelFormats(pool->handleType());
+ sink->delegate->poolMutex()->unlock();
+@@ -513,47 +437,7 @@ GstCaps *QVideoSurfaceGstSink::get_caps(GstBaseSink *base)
+ supportedFormats.append(format);
+ }
+
+- foreach (QVideoFrame::PixelFormat format, supportedFormats) {
+- int index = indexOfYuvColor(format);
+-
+- if (index != -1) {
+- gst_caps_append_structure(caps, gst_structure_new(
+- "video/x-raw-yuv",
+- "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, INT_MAX, 1,
+- "width" , GST_TYPE_INT_RANGE, 1, INT_MAX,
+- "height" , GST_TYPE_INT_RANGE, 1, INT_MAX,
+- "format" , GST_TYPE_FOURCC, qt_yuvColorLookup[index].fourcc,
+- NULL));
+- continue;
+- }
+-
+- const int count = sizeof(qt_rgbColorLookup) / sizeof(RgbFormat);
+-
+- for (int i = 0; i < count; ++i) {
+- if (qt_rgbColorLookup[i].pixelFormat == format) {
+- GstStructure *structure = gst_structure_new(
+- "video/x-raw-rgb",
+- "framerate" , GST_TYPE_FRACTION_RANGE, 0, 1, INT_MAX, 1,
+- "width" , GST_TYPE_INT_RANGE, 1, INT_MAX,
+- "height" , GST_TYPE_INT_RANGE, 1, INT_MAX,
+- "bpp" , G_TYPE_INT, qt_rgbColorLookup[i].bitsPerPixel,
+- "depth" , G_TYPE_INT, qt_rgbColorLookup[i].depth,
+- "endianness", G_TYPE_INT, qt_rgbColorLookup[i].endianness,
+- "red_mask" , G_TYPE_INT, qt_rgbColorLookup[i].red,
+- "green_mask", G_TYPE_INT, qt_rgbColorLookup[i].green,
+- "blue_mask" , G_TYPE_INT, qt_rgbColorLookup[i].blue,
+- NULL);
+-
+- if (qt_rgbColorLookup[i].alpha != 0) {
+- gst_structure_set(
+- structure, "alpha_mask", G_TYPE_INT, qt_rgbColorLookup[i].alpha, NULL);
+- }
+- gst_caps_append_structure(caps, structure);
+- }
+- }
+- }
+-
+- return caps;
++ return QGstUtils::capsForFormats(supportedFormats);
+ }
+
+ gboolean QVideoSurfaceGstSink::set_caps(GstBaseSink *base, GstCaps *caps)
+@@ -575,7 +459,7 @@ gboolean QVideoSurfaceGstSink::set_caps(GstBaseSink *base, GstCaps *caps)
+ QAbstractVideoBuffer::HandleType handleType =
+ pool ? pool->handleType() : QAbstractVideoBuffer::NoHandle;
+
+- QVideoSurfaceFormat format = formatForCaps(caps, &bytesPerLine, handleType);
++ QVideoSurfaceFormat format = QGstUtils::formatForCaps(caps, &bytesPerLine, handleType);
+
+ if (sink->delegate->isActive()) {
+ QVideoSurfaceFormat surfaceFormst = sink->delegate->surfaceFormat();
+@@ -592,7 +476,7 @@ gboolean QVideoSurfaceGstSink::set_caps(GstBaseSink *base, GstCaps *caps)
+ sink->lastRequestedCaps = 0;
+
+ #ifdef DEBUG_VIDEO_SURFACE_SINK
+- qDebug() << "Staring video surface, format:";
++ qDebug() << "Starting video surface, format:";
+ qDebug() << format;
+ qDebug() << "bytesPerLine:" << bytesPerLine;
+ #endif
+@@ -606,87 +490,6 @@ gboolean QVideoSurfaceGstSink::set_caps(GstBaseSink *base, GstCaps *caps)
+ return FALSE;
+ }
+
+-QVideoSurfaceFormat QVideoSurfaceGstSink::formatForCaps(GstCaps *caps, int *bytesPerLine, QAbstractVideoBuffer::HandleType handleType)
+-{
+- const GstStructure *structure = gst_caps_get_structure(caps, 0);
+-
+- QVideoFrame::PixelFormat pixelFormat = QVideoFrame::Format_Invalid;
+- int bitsPerPixel = 0;
+-
+- QSize size;
+- gst_structure_get_int(structure, "width", &size.rwidth());
+- gst_structure_get_int(structure, "height", &size.rheight());
+-
+- if (qstrcmp(gst_structure_get_name(structure), "video/x-raw-yuv") == 0) {
+- guint32 fourcc = 0;
+- gst_structure_get_fourcc(structure, "format", &fourcc);
+-
+- int index = indexOfYuvColor(fourcc);
+- if (index != -1) {
+- pixelFormat = qt_yuvColorLookup[index].pixelFormat;
+- bitsPerPixel = qt_yuvColorLookup[index].bitsPerPixel;
+- }
+- } else if (qstrcmp(gst_structure_get_name(structure), "video/x-raw-rgb") == 0) {
+- int depth = 0;
+- int endianness = 0;
+- int red = 0;
+- int green = 0;
+- int blue = 0;
+- int alpha = 0;
+-
+- gst_structure_get_int(structure, "bpp", &bitsPerPixel);
+- gst_structure_get_int(structure, "depth", &depth);
+- gst_structure_get_int(structure, "endianness", &endianness);
+- gst_structure_get_int(structure, "red_mask", &red);
+- gst_structure_get_int(structure, "green_mask", &green);
+- gst_structure_get_int(structure, "blue_mask", &blue);
+- gst_structure_get_int(structure, "alpha_mask", &alpha);
+-
+- int index = indexOfRgbColor(bitsPerPixel, depth, endianness, red, green, blue, alpha);
+-
+- if (index != -1)
+- pixelFormat = qt_rgbColorLookup[index].pixelFormat;
+- }
+-
+- if (pixelFormat != QVideoFrame::Format_Invalid) {
+- QVideoSurfaceFormat format(size, pixelFormat, handleType);
+-
+- QPair<int, int> rate;
+- gst_structure_get_fraction(structure, "framerate", &rate.first, &rate.second);
+-
+- if (rate.second)
+- format.setFrameRate(qreal(rate.first)/rate.second);
+-
+- gint aspectNum = 0;
+- gint aspectDenum = 0;
+- if (gst_structure_get_fraction(
+- structure, "pixel-aspect-ratio", &aspectNum, &aspectDenum)) {
+- if (aspectDenum > 0)
+- format.setPixelAspectRatio(aspectNum, aspectDenum);
+- }
+-
+- if (bytesPerLine)
+- *bytesPerLine = ((size.width() * bitsPerPixel / 8) + 3) & ~3;
+-
+- return format;
+- }
+-
+- return QVideoSurfaceFormat();
+-}
+-
+-void QVideoSurfaceGstSink::setFrameTimeStamps(QVideoFrame *frame, GstBuffer *buffer)
+-{
+- // GStreamer uses nanoseconds, Qt uses microseconds
+- qint64 startTime = GST_BUFFER_TIMESTAMP(buffer);
+- if (startTime >= 0) {
+- frame->setStartTime(startTime/G_GINT64_CONSTANT (1000));
+-
+- qint64 duration = GST_BUFFER_DURATION(buffer);
+- if (duration >= 0)
+- frame->setEndTime((startTime + duration)/G_GINT64_CONSTANT (1000));
+- }
+-}
+-
+ GstFlowReturn QVideoSurfaceGstSink::buffer_alloc(
+ GstBaseSink *base, guint64 offset, guint size, GstCaps *caps, GstBuffer **buffer)
+ {
+@@ -731,7 +534,7 @@ GstFlowReturn QVideoSurfaceGstSink::buffer_alloc(
+
+ if (sink->delegate->isActive()) {
+ //if format was changed, restart the surface
+- QVideoSurfaceFormat format = formatForCaps(intersection);
++ QVideoSurfaceFormat format = QGstUtils::formatForCaps(intersection);
+ QVideoSurfaceFormat surfaceFormat = sink->delegate->surfaceFormat();
+
+ if (format.pixelFormat() != surfaceFormat.pixelFormat() ||
+@@ -749,7 +552,7 @@ GstFlowReturn QVideoSurfaceGstSink::buffer_alloc(
+ QAbstractVideoBuffer::HandleType handleType =
+ pool ? pool->handleType() : QAbstractVideoBuffer::NoHandle;
+
+- QVideoSurfaceFormat format = formatForCaps(intersection, &bytesPerLine, handleType);
++ QVideoSurfaceFormat format = QGstUtils::formatForCaps(intersection, &bytesPerLine, handleType);
+
+ if (!sink->delegate->start(format, bytesPerLine)) {
+ qWarning() << "failed to start video surface";
+@@ -763,7 +566,7 @@ GstFlowReturn QVideoSurfaceGstSink::buffer_alloc(
+ QVideoSurfaceFormat surfaceFormat = sink->delegate->surfaceFormat();
+
+ if (!pool->isFormatSupported(surfaceFormat)) {
+- //qDebug() << "sink doesn't support native pool format, skip custom buffers allocation";
++ qDebug() << "sink doesn't support native pool format, skip custom buffers allocation";
+ return GST_FLOW_OK;
+ }
+
+@@ -787,7 +590,6 @@ GstFlowReturn QVideoSurfaceGstSink::buffer_alloc(
+ gboolean QVideoSurfaceGstSink::start(GstBaseSink *base)
+ {
+ Q_UNUSED(base);
+-
+ return TRUE;
+ }
+
+diff --git a/src/multimedia/gsttools_headers/qgstappsrc_p.h b/src/multimedia/gsttools_headers/qgstappsrc_p.h
+index 4af9252..0e0fc0a 100644
+--- a/src/multimedia/gsttools_headers/qgstappsrc_p.h
++++ b/src/multimedia/gsttools_headers/qgstappsrc_p.h
+@@ -39,7 +39,10 @@
+
+ #include <gst/gst.h>
+ #include <gst/app/gstappsrc.h>
++
++#if GST_VERSION_MAJOR < 1
+ #include <gst/app/gstappbuffer.h>
++#endif
+
+ QT_BEGIN_NAMESPACE
+
+diff --git a/src/multimedia/gsttools_headers/qgstreameraudioprobecontrol_p.h b/src/multimedia/gsttools_headers/qgstreameraudioprobecontrol_p.h
+index 34669b8..571a7ce 100644
+--- a/src/multimedia/gsttools_headers/qgstreameraudioprobecontrol_p.h
++++ b/src/multimedia/gsttools_headers/qgstreameraudioprobecontrol_p.h
+@@ -38,23 +38,32 @@
+ #include <qmediaaudioprobecontrol.h>
+ #include <QtCore/qmutex.h>
+ #include <qaudiobuffer.h>
++#include <qshareddata.h>
++
++#include <private/qgstreamerbufferprobe_p.h>
+
+ QT_BEGIN_NAMESPACE
+
+-class QGstreamerAudioProbeControl : public QMediaAudioProbeControl
++class QGstreamerAudioProbeControl
++ : public QMediaAudioProbeControl
++ , public QGstreamerBufferProbe
++ , public QSharedData
+ {
+ Q_OBJECT
+ public:
+ explicit QGstreamerAudioProbeControl(QObject *parent);
+ virtual ~QGstreamerAudioProbeControl();
+
+- void bufferProbed(GstBuffer* buffer);
++protected:
++ void probeCaps(GstCaps *caps);
++ bool probeBuffer(GstBuffer *buffer);
+
+ private slots:
+ void bufferProbed();
+
+ private:
+ QAudioBuffer m_pendingBuffer;
++ QAudioFormat m_format;
+ QMutex m_bufferMutex;
+ };
+
+diff --git a/src/multimedia/gsttools_headers/qgstreamerbufferprobe_p.h b/src/multimedia/gsttools_headers/qgstreamerbufferprobe_p.h
+new file mode 100644
+index 0000000..9240742
+--- /dev/null
++++ b/src/multimedia/gsttools_headers/qgstreamerbufferprobe_p.h
+@@ -0,0 +1,86 @@
++/****************************************************************************
++**
++** Copyright (C) 2014 Jolla Ltd.
++** Contact: http://www.qt-project.org/legal
++**
++** This file is part of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:LGPL$
++** 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 Digia. For licensing terms and
++** conditions see http://qt.digia.com/licensing. For further information
++** use the contact form at http://qt.digia.com/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 as published by the Free Software
++** Foundation and appearing in the file LICENSE.LGPL included in the
++** packaging of this file. Please review the following information to
++** ensure the GNU Lesser General Public License version 2.1 requirements
++** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
++**
++** In addition, as a special exception, Digia gives you certain additional
++** rights. These rights are described in the Digia Qt LGPL Exception
++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
++**
++** GNU General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU
++** General Public License version 3.0 as published by the Free Software
++** Foundation and appearing in the file LICENSE.GPL included in the
++** packaging of this file. Please review the following information to
++** ensure the GNU General Public License version 3.0 requirements will be
++** met: http://www.gnu.org/copyleft/gpl.html.
++**
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++#ifndef QGSTREAMERBUFFERPROBE_H
++#define QGSTREAMERBUFFERPROBE_H
++
++#include <gst/gst.h>
++
++#include <QtCore/qglobal.h>
++
++QT_BEGIN_NAMESPACE
++
++class QGstreamerBufferProbe
++{
++public:
++ enum Flags
++ {
++ ProbeCaps = 0x01,
++ ProbeBuffers = 0x02,
++ ProbeAll = ProbeCaps | ProbeBuffers
++ };
++
++ explicit QGstreamerBufferProbe(Flags flags = ProbeAll);
++ virtual ~QGstreamerBufferProbe();
++
++ void addProbeToPad(GstPad *pad, bool downstream = true);
++ void removeProbeFromPad(GstPad *pad);
++
++protected:
++ virtual void probeCaps(GstCaps *caps);
++ virtual bool probeBuffer(GstBuffer *buffer);
++
++private:
++#if GST_CHECK_VERSION(1,0,0)
++ static GstPadProbeReturn capsProbe(GstPad *pad, GstPadProbeInfo *info, gpointer user_data);
++ static GstPadProbeReturn bufferProbe(GstPad *pad, GstPadProbeInfo *info, gpointer user_data);
++ int m_capsProbeId;
++#else
++ static gboolean bufferProbe(GstElement *element, GstBuffer *buffer, gpointer user_data);
++ GstCaps *m_caps;
++#endif
++ int m_bufferProbeId;
++ const Flags m_flags;
++};
++
++QT_END_NAMESPACE
++
++#endif // QGSTREAMERAUDIOPROBECONTROL_H
+diff --git a/src/multimedia/gsttools_headers/qgstreamermirtexturerenderer_p.h b/src/multimedia/gsttools_headers/qgstreamermirtexturerenderer_p.h
+new file mode 100644
+index 0000000..25b8d60
+--- /dev/null
++++ b/src/multimedia/gsttools_headers/qgstreamermirtexturerenderer_p.h
+@@ -0,0 +1,102 @@
++/****************************************************************************
++**
++** Copyright (C) 2014 Canonical Ltd.
++** Contact: http://www.qt-project.org/legal
++**
++** 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 Digia. For licensing terms and
++** conditions see http://qt.digia.com/licensing. For further information
++** use the contact form at http://qt.digia.com/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.
++**
++** In addition, as a special exception, Digia gives you certain additional
++** rights. These rights are described in the Digia Qt LGPL Exception
++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++#ifndef QGSTREAMERMIRTEXTURERENDERER_H
++#define QGSTREAMERMIRTEXTURERENDERER_H
++
++#include <qmediaplayer.h>
++#include <qvideorenderercontrol.h>
++#include <private/qvideosurfacegstsink_p.h>
++#include <qabstractvideosurface.h>
++
++#include "qgstreamervideorendererinterface_p.h"
++
++QT_BEGIN_NAMESPACE
++
++class QGstreamerMirTextureBuffer;
++class QGstreamerPlayerSession;
++class QGLContext;
++class QOpenGLContext;
++class QSurfaceFormat;
++
++class QGstreamerMirTextureRenderer : public QVideoRendererControl, public QGstreamerVideoRendererInterface
++{
++ Q_OBJECT
++ Q_INTERFACES(QGstreamerVideoRendererInterface)
++public:
++ QGstreamerMirTextureRenderer(QObject *parent = 0, const QGstreamerPlayerSession *playerSession = 0);
++ virtual ~QGstreamerMirTextureRenderer();
++
++ QAbstractVideoSurface *surface() const;
++ void setSurface(QAbstractVideoSurface *surface);
++
++ void setPlayerSession(const QGstreamerPlayerSession *playerSession);
++
++ GstElement *videoSink();
++
++ void stopRenderer();
++ bool isReady() const { return m_surface != 0; }
++
++signals:
++ void sinkChanged();
++ void readyChanged(bool);
++ void nativeSizeChanged();
++
++private slots:
++ void handleFormatChange();
++ void updateNativeVideoSize();
++ void handleFocusWindowChanged(QWindow *window);
++ void renderFrame();
++
++private:
++ QWindow *createOffscreenWindow(const QSurfaceFormat &format);
++ static void handleFrameReady(gpointer userData);
++ static GstPadProbeReturn padBufferProbe(GstPad *pad, GstPadProbeInfo *info, gpointer userData);
++
++ GstElement *m_videoSink;
++ QPointer<QAbstractVideoSurface> m_surface;
++ QPointer<QAbstractVideoSurface> m_glSurface;
++ QGLContext *m_context;
++ QOpenGLContext *m_glContext;
++ unsigned int m_textureId;
++ QWindow *m_offscreenSurface;
++ QGstreamerPlayerSession *m_playerSession;
++ QGstreamerMirTextureBuffer *m_textureBuffer;
++ QSize m_nativeSize;
++
++ QMutex m_mutex;
++};
++
++QT_END_NAMESPACE
++
++#endif // QGSTREAMERMIRTEXTURERENDRER_H
+diff --git a/src/multimedia/gsttools_headers/qgstreamervideoprobecontrol_p.h b/src/multimedia/gsttools_headers/qgstreamervideoprobecontrol_p.h
+index 49064f9..f035f65 100644
+--- a/src/multimedia/gsttools_headers/qgstreamervideoprobecontrol_p.h
++++ b/src/multimedia/gsttools_headers/qgstreamervideoprobecontrol_p.h
+@@ -35,20 +35,29 @@
+ #define QGSTREAMERVIDEOPROBECONTROL_H
+
+ #include <gst/gst.h>
++#include <gst/video/video.h>
+ #include <qmediavideoprobecontrol.h>
+ #include <QtCore/qmutex.h>
+ #include <qvideoframe.h>
++#include <qvideosurfaceformat.h>
++
++#include <private/qgstreamerbufferprobe_p.h>
+
+ QT_BEGIN_NAMESPACE
+
+-class QGstreamerVideoProbeControl : public QMediaVideoProbeControl
++class QGstreamerVideoProbeControl
++ : public QMediaVideoProbeControl
++ , public QGstreamerBufferProbe
++ , public QSharedData
+ {
+ Q_OBJECT
+ public:
+ explicit QGstreamerVideoProbeControl(QObject *parent);
+ virtual ~QGstreamerVideoProbeControl();
+
+- void bufferProbed(GstBuffer* buffer);
++ void probeCaps(GstCaps *caps);
++ bool probeBuffer(GstBuffer *buffer);
++
+ void startFlushing();
+ void stopFlushing();
+
+@@ -56,10 +65,16 @@ private slots:
+ void frameProbed();
+
+ private:
+- bool m_flushing;
+- bool m_frameProbed; // true if at least one frame was probed
++ QVideoSurfaceFormat m_format;
+ QVideoFrame m_pendingFrame;
+ QMutex m_frameMutex;
++#if GST_CHECK_VERSION(1,0,0)
++ GstVideoInfo m_videoInfo;
++#else
++ int m_bytesPerLine;
++#endif
++ bool m_flushing;
++ bool m_frameProbed; // true if at least one frame was probed
+ };
+
+ QT_END_NAMESPACE
+diff --git a/src/multimedia/gsttools_headers/qgstreamervideowindow_p.h b/src/multimedia/gsttools_headers/qgstreamervideowindow_p.h
+index 81e5764..d38156c 100644
+--- a/src/multimedia/gsttools_headers/qgstreamervideowindow_p.h
++++ b/src/multimedia/gsttools_headers/qgstreamervideowindow_p.h
+@@ -38,6 +38,7 @@
+
+ #include "qgstreamervideorendererinterface_p.h"
+ #include <private/qgstreamerbushelper_p.h>
++#include <private/qgstreamerbufferprobe_p.h>
+ #include <QtGui/qcolor.h>
+
+ QT_BEGIN_NAMESPACE
+@@ -45,7 +46,8 @@ class QAbstractVideoSurface;
+
+ class QGstreamerVideoWindow : public QVideoWindowControl,
+ public QGstreamerVideoRendererInterface,
+- public QGstreamerSyncMessageFilter
++ public QGstreamerSyncMessageFilter,
++ private QGstreamerBufferProbe
+ {
+ Q_OBJECT
+ Q_INTERFACES(QGstreamerVideoRendererInterface QGstreamerSyncMessageFilter)
+@@ -101,10 +103,10 @@ signals:
+ void readyChanged(bool);
+
+ private slots:
+- void updateNativeVideoSize();
++ void updateNativeVideoSize(const QSize &size);
+
+ private:
+- static void padBufferProbe(GstPad *pad, GstBuffer *buffer, gpointer user_data);
++ void probeCaps(GstCaps *caps);
+
+ GstElement *m_videoSink;
+ WId m_windowId;
+@@ -113,7 +115,6 @@ private:
+ bool m_fullScreen;
+ QSize m_nativeSize;
+ mutable QColor m_colorKey;
+- int m_bufferProbeId;
+ };
+
+ QT_END_NAMESPACE
+diff --git a/src/multimedia/gsttools_headers/qgstutils_p.h b/src/multimedia/gsttools_headers/qgstutils_p.h
+index 65ff759..71a0a57 100644
+--- a/src/multimedia/gsttools_headers/qgstutils_p.h
++++ b/src/multimedia/gsttools_headers/qgstutils_p.h
+@@ -49,14 +49,32 @@
+ #include <QtCore/qset.h>
+ #include <QtCore/qvector.h>
+ #include <gst/gst.h>
++#include <gst/video/video.h>
+ #include <qaudioformat.h>
+ #include <qcamera.h>
++#include <qabstractvideobuffer.h>
++#include <qvideoframe.h>
++#include <QDebug>
++
++#if GST_CHECK_VERSION(1,0,0)
++# define QT_GSTREAMER_PLAYBIN_ELEMENT_NAME "playbin"
++# define QT_GSTREAMER_CAMERABIN_ELEMENT_NAME "camerabin"
++# define QT_GSTREAMER_COLORCONVERSION_ELEMENT_NAME "videoconvert"
++# define QT_GSTREAMER_RAW_AUDIO_MIME "audio/x-raw"
++#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"
++#endif
+
+ QT_BEGIN_NAMESPACE
+
+ class QSize;
+ class QVariant;
+ class QByteArray;
++class QImage;
++class QVideoSurfaceFormat;
+
+ namespace QGstUtils {
+ struct CameraInfo
+@@ -73,8 +91,12 @@ namespace QGstUtils {
+ QSize capsResolution(const GstCaps *caps);
+ QSize capsCorrectedResolution(const GstCaps *caps);
+ QAudioFormat audioFormatForCaps(const GstCaps *caps);
++#if GST_CHECK_VERSION(1,0,0)
++ QAudioFormat audioFormatForSample(GstSample *sample);
++#else
+ QAudioFormat audioFormatForBuffer(GstBuffer *buffer);
+- GstCaps *capsForAudioFormat(QAudioFormat format);
++#endif
++ GstCaps *capsForAudioFormat(const QAudioFormat &format);
+ void initializeGst();
+ QMultimedia::SupportEstimate hasSupport(const QString &mimeType,
+ const QStringList &codecs,
+@@ -86,9 +108,40 @@ namespace QGstUtils {
+ QCamera::Position cameraPosition(const QString &device, GstElementFactory * factory = 0);
+ int cameraOrientation(const QString &device, GstElementFactory * factory = 0);
+ QByteArray cameraDriver(const QString &device, GstElementFactory * factory = 0);
++
++ QSet<QString> supportedMimeTypes(bool (*isValidFactory)(GstElementFactory *factory));
++
++#if GST_CHECK_VERSION(1,0,0)
++ QImage bufferToImage(GstBuffer *buffer, const GstVideoInfo &info);
++ QVideoSurfaceFormat formatForCaps(
++ GstCaps *caps,
++ GstVideoInfo *info,
++ QAbstractVideoBuffer::HandleType handleType = QAbstractVideoBuffer::NoHandle);
++#else
++ QImage bufferToImage(GstBuffer *buffer);
++ QVideoSurfaceFormat formatForCaps(
++ GstCaps *caps,
++ int *bytesPerLine = 0,
++ QAbstractVideoBuffer::HandleType handleType = QAbstractVideoBuffer::NoHandle);
++#endif
++
++ GstCaps *capsForFormats(const QList<QVideoFrame::PixelFormat> &formats);
++ void setFrameTimeStamps(QVideoFrame *frame, GstBuffer *buffer);
++
++ void setMetaData(GstElement *element, const QMap<QByteArray, QVariant> &data);
++ void setMetaData(GstBin *bin, const QMap<QByteArray, QVariant> &data);
++
++ GstCaps *videoFilterCaps();
++
+ }
+
+ void qt_gst_object_ref_sink(gpointer object);
++GstCaps *qt_gst_pad_get_current_caps(GstPad *pad);
++GstStructure *qt_gst_structure_new_empty(const char *name);
++gboolean qt_gst_element_query_position(GstElement *element, GstFormat format, gint64 *cur);
++gboolean qt_gst_element_query_duration(GstElement *element, GstFormat format, gint64 *cur);
++
++QDebug operator <<(QDebug debug, GstCaps *caps);
+
+ QT_END_NAMESPACE
+
+diff --git a/src/multimedia/gsttools_headers/qgstvideobuffer_p.h b/src/multimedia/gsttools_headers/qgstvideobuffer_p.h
+index 1e0fda8..00aca48 100644
+--- a/src/multimedia/gsttools_headers/qgstvideobuffer_p.h
++++ b/src/multimedia/gsttools_headers/qgstvideobuffer_p.h
+@@ -49,26 +49,47 @@
+ #include <QtCore/qvariant.h>
+
+ #include <gst/gst.h>
++#include <gst/video/video.h>
+
+ QT_BEGIN_NAMESPACE
+
++#if GST_CHECK_VERSION(1,0,0)
++class QGstVideoBuffer : public QAbstractPlanarVideoBuffer
++{
++public:
++ QGstVideoBuffer(GstBuffer *buffer, const GstVideoInfo &info);
++ QGstVideoBuffer(GstBuffer *buffer, const GstVideoInfo &info,
++ HandleType handleType, const QVariant &handle);
++#else
+ class QGstVideoBuffer : public QAbstractVideoBuffer
+ {
+ public:
+ QGstVideoBuffer(GstBuffer *buffer, int bytesPerLine);
+ QGstVideoBuffer(GstBuffer *buffer, int bytesPerLine,
+ HandleType handleType, const QVariant &handle);
++#endif
++
+ ~QGstVideoBuffer();
+
+ MapMode mapMode() const;
+
++#if GST_CHECK_VERSION(1,0,0)
++ int map(MapMode mode, int *numBytes, int bytesPerLine[4], uchar *data[4]);
++#else
+ uchar *map(MapMode mode, int *numBytes, int *bytesPerLine);
++#endif
++
+ void unmap();
+
+ QVariant handle() const { return m_handle; }
+ private:
+- GstBuffer *m_buffer;
++#if GST_CHECK_VERSION(1,0,0)
++ GstVideoInfo m_videoInfo;
++ GstVideoFrame m_frame;
++#else
+ int m_bytesPerLine;
++#endif
++ GstBuffer *m_buffer;
+ MapMode m_mode;
+ QVariant m_handle;
+ };
+diff --git a/src/multimedia/gsttools_headers/qgstvideorendererplugin_p.h b/src/multimedia/gsttools_headers/qgstvideorendererplugin_p.h
+new file mode 100644
+index 0000000..616677a
+--- /dev/null
++++ b/src/multimedia/gsttools_headers/qgstvideorendererplugin_p.h
+@@ -0,0 +1,111 @@
++/****************************************************************************
++**
++** Copyright (C) 2014 Jolla Ltd.
++** Contact: http://www.qt-project.org/legal
++**
++** This file is part of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:LGPL$
++** 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 Digia. For licensing terms and
++** conditions see http://qt.digia.com/licensing. For further information
++** use the contact form at http://qt.digia.com/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 as published by the Free Software
++** Foundation and appearing in the file LICENSE.LGPL included in the
++** packaging of this file. Please review the following information to
++** ensure the GNU Lesser General Public License version 2.1 requirements
++** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
++**
++** In addition, as a special exception, Digia gives you certain additional
++** rights. These rights are described in the Digia Qt LGPL Exception
++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
++**
++** GNU General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU
++** General Public License version 3.0 as published by the Free Software
++** Foundation and appearing in the file LICENSE.GPL included in the
++** packaging of this file. Please review the following information to
++** ensure the GNU General Public License version 3.0 requirements will be
++** met: http://www.gnu.org/copyleft/gpl.html.
++**
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++#ifndef QGSTVIDEORENDERERPLUGIN_P_H
++#define QGSTVIDEORENDERERPLUGIN_P_H
++
++//
++// W A R N I N G
++// -------------
++//
++// This file is not part of the Qt API. It exists purely as an
++// implementation detail. This header file may change from version to
++// version without notice, or even be removed.
++//
++// We mean it.
++//
++
++#include <qabstractvideobuffer.h>
++#include <qvideosurfaceformat.h>
++#include <QtCore/qobject.h>
++#include <QtCore/qplugin.h>
++
++#include <gst/gst.h>
++
++QT_BEGIN_NAMESPACE
++
++class QAbstractVideoSurface;
++
++const QLatin1String QGstVideoRendererPluginKey("gstvideorenderer");
++
++class QGstVideoRenderer
++{
++public:
++ virtual ~QGstVideoRenderer() {}
++
++ virtual GstCaps *getCaps(QAbstractVideoSurface *surface) = 0;
++ virtual bool start(QAbstractVideoSurface *surface, GstCaps *caps) = 0;
++ virtual void stop(QAbstractVideoSurface *surface) = 0; // surface may be null if unexpectedly deleted.
++ virtual bool proposeAllocation(GstQuery *query) = 0; // may be called from a thread.
++
++ virtual bool present(QAbstractVideoSurface *surface, GstBuffer *buffer) = 0;
++ virtual void flush(QAbstractVideoSurface *surface) = 0; // surface may be null if unexpectedly deleted.
++};
++
++/*
++ Abstract interface for video buffers allocation.
++*/
++class QGstVideoRendererInterface
++{
++public:
++ virtual ~QGstVideoRendererInterface() {}
++
++ virtual QGstVideoRenderer *createRenderer() = 0;
++};
++
++#define QGstVideoRendererInterface_iid "org.qt-project.qt.gstvideorenderer/5.4"
++Q_DECLARE_INTERFACE(QGstVideoRendererInterface, QGstVideoRendererInterface_iid)
++
++class QGstVideoRendererPlugin : public QObject, public QGstVideoRendererInterface
++{
++ Q_OBJECT
++ Q_INTERFACES(QGstVideoRendererInterface)
++public:
++ explicit QGstVideoRendererPlugin(QObject *parent = 0);
++ virtual ~QGstVideoRendererPlugin() {}
++
++ virtual QGstVideoRenderer *createRenderer() = 0;
++
++};
++
++QT_END_NAMESPACE
++
++#endif
+diff --git a/src/multimedia/gsttools_headers/qgstvideorenderersink_p.h b/src/multimedia/gsttools_headers/qgstvideorenderersink_p.h
+new file mode 100644
+index 0000000..6feb371
+--- /dev/null
++++ b/src/multimedia/gsttools_headers/qgstvideorenderersink_p.h
+@@ -0,0 +1,183 @@
++/****************************************************************************
++**
++** Copyright (C) 2014 Jolla Ltd.
++** Contact: http://www.qt-project.org/legal
++**
++** This file is part of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:LGPL$
++** 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 Digia. For licensing terms and
++** conditions see http://qt.digia.com/licensing. For further information
++** use the contact form at http://qt.digia.com/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 as published by the Free Software
++** Foundation and appearing in the file LICENSE.LGPL included in the
++** packaging of this file. Please review the following information to
++** ensure the GNU Lesser General Public License version 2.1 requirements
++** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
++**
++** In addition, as a special exception, Digia gives you certain additional
++** rights. These rights are described in the Digia Qt LGPL Exception
++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
++**
++** GNU General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU
++** General Public License version 3.0 as published by the Free Software
++** Foundation and appearing in the file LICENSE.GPL included in the
++** packaging of this file. Please review the following information to
++** ensure the GNU General Public License version 3.0 requirements will be
++** met: http://www.gnu.org/copyleft/gpl.html.
++**
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++#ifndef QGSTVIDEORENDERERSINK_P_H
++#define QGSTVIDEORENDERERSINK_P_H
++
++//
++// W A R N I N G
++// -------------
++//
++// This file is not part of the Qt API. It exists purely as an
++// implementation detail. This header file may change from version to
++// version without notice, or even be removed.
++//
++// We mean it.
++//
++
++#include <gst/video/gstvideosink.h>
++#include <gst/video/video.h>
++
++#include <QtCore/qlist.h>
++#include <QtCore/qmutex.h>
++#include <QtCore/qqueue.h>
++#include <QtCore/qpointer.h>
++#include <QtCore/qwaitcondition.h>
++#include <qvideosurfaceformat.h>
++#include <qvideoframe.h>
++#include <qabstractvideobuffer.h>
++
++#include "qgstvideorendererplugin_p.h"
++
++#include "qgstvideorendererplugin_p.h"
++
++QT_BEGIN_NAMESPACE
++class QAbstractVideoSurface;
++
++class QGstDefaultVideoRenderer : public QGstVideoRenderer
++{
++public:
++ QGstDefaultVideoRenderer();
++ ~QGstDefaultVideoRenderer();
++
++ GstCaps *getCaps(QAbstractVideoSurface *surface);
++ bool start(QAbstractVideoSurface *surface, GstCaps *caps);
++ void stop(QAbstractVideoSurface *surface);
++
++ bool proposeAllocation(GstQuery *query);
++
++ bool present(QAbstractVideoSurface *surface, GstBuffer *buffer);
++ void flush(QAbstractVideoSurface *surface);
++
++private:
++ QVideoSurfaceFormat m_format;
++ GstVideoInfo m_videoInfo;
++ bool m_flushed;
++};
++
++class QVideoSurfaceGstDelegate : public QObject
++{
++ Q_OBJECT
++public:
++ QVideoSurfaceGstDelegate(QAbstractVideoSurface *surface);
++ ~QVideoSurfaceGstDelegate();
++
++ GstCaps *caps();
++
++ bool start(GstCaps *caps);
++ void stop();
++ bool proposeAllocation(GstQuery *query);
++
++ void flush();
++
++ GstFlowReturn render(GstBuffer *buffer, bool show);
++
++ bool event(QEvent *event);
++
++ static void handleShowPrerollChange(GObject *o, GParamSpec *p, gpointer d);
++
++private slots:
++ bool handleEvent(QMutexLocker *locker);
++ void updateSupportedFormats();
++
++private:
++ void notify();
++ bool waitForAsyncEvent(QMutexLocker *locker, QWaitCondition *condition, unsigned long time);
++
++ QPointer<QAbstractVideoSurface> m_surface;
++
++ QMutex m_mutex;
++ QWaitCondition m_setupCondition;
++ QWaitCondition m_renderCondition;
++ GstFlowReturn m_renderReturn;
++ QList<QGstVideoRenderer *> m_renderers;
++ QGstVideoRenderer *m_renderer;
++ QGstVideoRenderer *m_activeRenderer;
++
++ GstCaps *m_surfaceCaps;
++ GstCaps *m_startCaps;
++ GstBuffer *m_lastBuffer;
++
++ bool m_notified;
++ bool m_stop;
++ bool m_render;
++ bool m_flush;
++};
++
++class QGstVideoRendererSink
++{
++public:
++ GstVideoSink parent;
++
++ static QGstVideoRendererSink *createSink(QAbstractVideoSurface *surface);
++
++private:
++ static GType get_type();
++ static void class_init(gpointer g_class, gpointer class_data);
++ static void base_init(gpointer g_class);
++ static void instance_init(GTypeInstance *instance, gpointer g_class);
++
++ static void finalize(GObject *object);
++
++ static GstStateChangeReturn change_state(GstElement *element, GstStateChange transition);
++
++ static GstCaps *get_caps(GstBaseSink *sink, GstCaps *filter);
++ static gboolean set_caps(GstBaseSink *sink, GstCaps *caps);
++
++ static gboolean propose_allocation(GstBaseSink *sink, GstQuery *query);
++
++ static GstFlowReturn preroll(GstBaseSink *sink, GstBuffer *buffer);
++ static GstFlowReturn render(GstBaseSink *sink, GstBuffer *buffer);
++
++private:
++ QVideoSurfaceGstDelegate *delegate;
++};
++
++
++class QGstVideoRendererSinkClass
++{
++public:
++ GstVideoSinkClass parent_class;
++};
++
++QT_END_NAMESPACE
++
++#endif
+diff --git a/src/multimedia/gsttools_headers/qvideosurfacegstsink_p.h b/src/multimedia/gsttools_headers/qvideosurfacegstsink_p.h
+index 11b305d..0ea18c0 100644
+--- a/src/multimedia/gsttools_headers/qvideosurfacegstsink_p.h
++++ b/src/multimedia/gsttools_headers/qvideosurfacegstsink_p.h
+@@ -45,6 +45,18 @@
+ // We mean it.
+ //
+
++#include <gst/gst.h>
++
++#if GST_CHECK_VERSION(1,0,0)
++
++#include "qgstvideorenderersink_p.h"
++
++QT_BEGIN_NAMESPACE
++typedef QGstVideoRendererSink QVideoSurfaceGstSink;
++QT_END_NAMESPACE
++
++#else
++
+ #include <gst/video/gstvideosink.h>
+
+ #include <QtCore/qlist.h>
+@@ -116,10 +128,6 @@ public:
+ GstVideoSink parent;
+
+ static QVideoSurfaceGstSink *createSink(QAbstractVideoSurface *surface);
+- static QVideoSurfaceFormat formatForCaps(GstCaps *caps,
+- int *bytesPerLine = 0,
+- QAbstractVideoBuffer::HandleType handleType = QAbstractVideoBuffer::NoHandle);
+- static void setFrameTimeStamps(QVideoFrame *frame, GstBuffer *buffer);
+
+ private:
+ static GType get_type();
+@@ -150,7 +158,6 @@ private:
+ QVideoSurfaceFormat *lastSurfaceFormat;
+ };
+
+-
+ class QVideoSurfaceGstSinkClass
+ {
+ public:
+@@ -160,3 +167,5 @@ public:
+ QT_END_NAMESPACE
+
+ #endif
++
++#endif
+diff --git a/src/multimedia/multimedia.pro b/src/multimedia/multimedia.pro
+index b3bdaa8..ff47768 100644
+--- a/src/multimedia/multimedia.pro
++++ b/src/multimedia/multimedia.pro
+@@ -4,6 +4,8 @@ QT = core-private network gui-private
+ MODULE_PLUGIN_TYPES = \
+ mediaservice \
+ audio \
++ video/bufferpool \
++ video/gstvideorenderer \
+ video/videonode \
+ playlistformats
+
+diff --git a/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderserviceplugin.cpp b/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderserviceplugin.cpp
+index 3098aab..befbb9a 100644
+--- a/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderserviceplugin.cpp
++++ b/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderserviceplugin.cpp
+@@ -68,89 +68,16 @@ QMultimedia::SupportEstimate QGstreamerAudioDecoderServicePlugin::hasSupport(con
+ return QGstUtils::hasSupport(mimeType, codecs, m_supportedMimeTypeSet);
+ }
+
+-void QGstreamerAudioDecoderServicePlugin::updateSupportedMimeTypes() const
++static bool isDecoderOrDemuxer(GstElementFactory *factory)
+ {
+- //enumerate supported mime types
+- gst_init(NULL, NULL);
+-
+- GList *plugins, *orig_plugins;
+- orig_plugins = plugins = gst_default_registry_get_plugin_list ();
+-
+- while (plugins) {
+- GList *features, *orig_features;
+-
+- GstPlugin *plugin = (GstPlugin *) (plugins->data);
+- plugins = g_list_next (plugins);
+-
+- if (plugin->flags & (1<<1)) //GST_PLUGIN_FLAG_BLACKLISTED
+- continue;
+-
+- orig_features = features = gst_registry_get_feature_list_by_plugin(gst_registry_get_default (),
+- plugin->desc.name);
+- while (features) {
+- if (!G_UNLIKELY(features->data == NULL)) {
+- GstPluginFeature *feature = GST_PLUGIN_FEATURE(features->data);
+- if (GST_IS_ELEMENT_FACTORY (feature)) {
+- GstElementFactory *factory = GST_ELEMENT_FACTORY(gst_plugin_feature_load(feature));
+- if (factory
+- && factory->numpadtemplates > 0
+- && (qstrcmp(factory->details.klass, "Codec/Decoder/Audio") == 0
+- || qstrcmp(factory->details.klass, "Codec/Demux") == 0 )) {
+- const GList *pads = factory->staticpadtemplates;
+- while (pads) {
+- GstStaticPadTemplate *padtemplate = (GstStaticPadTemplate*)(pads->data);
+- pads = g_list_next (pads);
+- if (padtemplate->direction != GST_PAD_SINK)
+- continue;
+- if (padtemplate->static_caps.string) {
+- GstCaps *caps = gst_static_caps_get(&padtemplate->static_caps);
+- if (!gst_caps_is_any (caps) && ! gst_caps_is_empty (caps)) {
+- for (guint i = 0; i < gst_caps_get_size(caps); i++) {
+- GstStructure *structure = gst_caps_get_structure(caps, i);
+- QString nameLowcase = QString(gst_structure_get_name (structure)).toLower();
+-
+- m_supportedMimeTypeSet.insert(nameLowcase);
+- if (nameLowcase.contains("mpeg")) {
+- //Because mpeg version number is only included in the detail
+- //description, it is necessary to manually extract this information
+- //in order to match the mime type of mpeg4.
+- const GValue *value = gst_structure_get_value(structure, "mpegversion");
+- if (value) {
+- gchar *str = gst_value_serialize (value);
+- QString versions(str);
+- QStringList elements = versions.split(QRegExp("\\D+"), QString::SkipEmptyParts);
+- foreach (const QString &e, elements)
+- m_supportedMimeTypeSet.insert(nameLowcase + e);
+- g_free (str);
+- }
+- }
+- }
+- }
+- gst_caps_unref(caps);
+- }
+- }
+- gst_object_unref (factory);
+- }
+- } else if (GST_IS_TYPE_FIND_FACTORY(feature)) {
+- QString name(gst_plugin_feature_get_name(feature));
+- if (name.contains('/')) //filter out any string without '/' which is obviously not a mime type
+- m_supportedMimeTypeSet.insert(name.toLower());
+- }
+- }
+- features = g_list_next (features);
+- }
+- gst_plugin_feature_list_free (orig_features);
+- }
+- gst_plugin_list_free (orig_plugins);
++ return gst_element_factory_list_is_type(factory, GST_ELEMENT_FACTORY_TYPE_DEMUXER)
++ || gst_element_factory_list_is_type(factory, GST_ELEMENT_FACTORY_TYPE_DECODER
++ | GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO);
++}
+
+-#if defined QT_SUPPORTEDMIMETYPES_DEBUG
+- QStringList list = m_supportedMimeTypeSet.toList();
+- list.sort();
+- if (qgetenv("QT_DEBUG_PLUGINS").toInt() > 0) {
+- foreach (const QString &type, list)
+- qDebug() << type;
+- }
+-#endif
++void QGstreamerAudioDecoderServicePlugin::updateSupportedMimeTypes() const
++{
++ m_supportedMimeTypeSet = QGstUtils::supportedMimeTypes(isDecoderOrDemuxer);
+ }
+
+ QStringList QGstreamerAudioDecoderServicePlugin::supportedMimeTypes() const
+diff --git a/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodersession.cpp b/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodersession.cpp
+index f944a60..69876b9 100644
+--- a/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodersession.cpp
++++ b/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodersession.cpp
+@@ -85,7 +85,7 @@ QGstreamerAudioDecoderSession::QGstreamerAudioDecoderSession(QObject *parent)
+ m_durationQueries(0)
+ {
+ // Create pipeline here
+- m_playbin = gst_element_factory_make("playbin2", NULL);
++ m_playbin = gst_element_factory_make(QT_GSTREAMER_PLAYBIN_ELEMENT_NAME, NULL);
+
+ if (m_playbin != 0) {
+ // Sort out messages
+@@ -446,21 +446,40 @@ QAudioBuffer QGstreamerAudioDecoderSession::read()
+ if (buffersAvailable == 1)
+ emit bufferAvailableChanged(false);
+
++ const char* bufferData = 0;
++ int bufferSize = 0;
++
++#if GST_CHECK_VERSION(1,0,0)
++ GstSample *sample = gst_app_sink_pull_sample(m_appSink);
++ GstBuffer *buffer = gst_sample_get_buffer(sample);
++ GstMapInfo mapInfo;
++ gst_buffer_map(buffer, &mapInfo, GST_MAP_READ);
++ bufferData = (const char*)mapInfo.data;
++ bufferSize = mapInfo.size;
++ QAudioFormat format = QGstUtils::audioFormatForSample(sample);
++#else
+ GstBuffer *buffer = gst_app_sink_pull_buffer(m_appSink);
+-
++ bufferData = (const char*)buffer->data;
++ bufferSize = buffer->size;
+ QAudioFormat format = QGstUtils::audioFormatForBuffer(buffer);
++#endif
++
+ if (format.isValid()) {
+ // XXX At the moment we have to copy data from GstBuffer into QAudioBuffer.
+ // We could improve performance by implementing QAbstractAudioBuffer for GstBuffer.
+ qint64 position = getPositionFromBuffer(buffer);
+- audioBuffer = QAudioBuffer(QByteArray((const char*)buffer->data, buffer->size), format, position);
++ audioBuffer = QAudioBuffer(QByteArray((const char*)bufferData, bufferSize), format, position);
+ position /= 1000; // convert to milliseconds
+ if (position != m_position) {
+ m_position = position;
+ emit positionChanged(m_position);
+ }
+ }
++#if GST_CHECK_VERSION(1,0,0)
++ gst_sample_unref(sample);
++#else
+ gst_buffer_unref(buffer);
++#endif
+ }
+
+ return audioBuffer;
+@@ -488,7 +507,7 @@ void QGstreamerAudioDecoderSession::processInvalidMedia(QAudioDecoder::Error err
+ emit error(int(errorCode), errorString);
+ }
+
+-GstFlowReturn QGstreamerAudioDecoderSession::new_buffer(GstAppSink *, gpointer user_data)
++GstFlowReturn QGstreamerAudioDecoderSession::new_sample(GstAppSink *, gpointer user_data)
+ {
+ // "Note that the preroll buffer will also be returned as the first buffer when calling gst_app_sink_pull_buffer()."
+ QGstreamerAudioDecoderSession *session = reinterpret_cast<QGstreamerAudioDecoderSession*>(user_data);
+@@ -531,7 +550,11 @@ void QGstreamerAudioDecoderSession::addAppSink()
+
+ GstAppSinkCallbacks callbacks;
+ memset(&callbacks, 0, sizeof(callbacks));
+- callbacks.new_buffer = &new_buffer;
++#if GST_CHECK_VERSION(1,0,0)
++ callbacks.new_sample = &new_sample;
++#else
++ callbacks.new_buffer = &new_sample;
++#endif
+ gst_app_sink_set_callbacks(m_appSink, &callbacks, this, NULL);
+ gst_app_sink_set_max_buffers(m_appSink, MAX_BUFFERS_IN_QUEUE);
+ gst_base_sink_set_sync(GST_BASE_SINK(m_appSink), FALSE);
+@@ -553,11 +576,10 @@ void QGstreamerAudioDecoderSession::removeAppSink()
+
+ void QGstreamerAudioDecoderSession::updateDuration()
+ {
+- GstFormat format = GST_FORMAT_TIME;
+ gint64 gstDuration = 0;
+ int duration = -1;
+
+- if (m_playbin && gst_element_query_duration(m_playbin, &format, &gstDuration))
++ if (m_playbin && qt_gst_element_query_duration(m_playbin, GST_FORMAT_TIME, &gstDuration))
+ duration = gstDuration / 1000000;
+
+ if (m_duration != duration) {
+diff --git a/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodersession.h b/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodersession.h
+index 0912196..068221c 100644
+--- a/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodersession.h
++++ b/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodersession.h
+@@ -92,7 +92,7 @@ public:
+ qint64 position() const;
+ qint64 duration() const;
+
+- static GstFlowReturn new_buffer(GstAppSink *sink, gpointer user_data);
++ static GstFlowReturn new_sample(GstAppSink *sink, gpointer user_data);
+
+ signals:
+ void stateChanged(QAudioDecoder::State newState);
+diff --git a/src/plugins/gstreamer/camerabin/camerabin.pro b/src/plugins/gstreamer/camerabin/camerabin.pro
+index bba797f..64fee3e 100644
+--- a/src/plugins/gstreamer/camerabin/camerabin.pro
++++ b/src/plugins/gstreamer/camerabin/camerabin.pro
+@@ -79,7 +79,7 @@ config_gstreamer_photography {
+ $$PWD/camerabinlocks.cpp \
+ $$PWD/camerabinzoom.cpp
+
+- LIBS += -lgstphotography-0.10
++ LIBS += -lgstphotography-$$GST_VERSION
+ DEFINES += GST_USE_UNSTABLE_API #prevents warnings because of unstable photography API
+ }
+
+diff --git a/src/plugins/gstreamer/camerabin/camerabincontainer.cpp b/src/plugins/gstreamer/camerabin/camerabincontainer.cpp
+index ebb914b..9531f01 100644
+--- a/src/plugins/gstreamer/camerabin/camerabincontainer.cpp
++++ b/src/plugins/gstreamer/camerabin/camerabincontainer.cpp
+@@ -96,7 +96,7 @@ GstEncodingContainerProfile *CameraBinContainer::createProfile()
+ GstCaps *caps;
+
+ if (m_actualFormat.isEmpty()) {
+- caps = gst_caps_new_any();
++ return 0;
+ } else {
+ QString format = m_actualFormat;
+ QStringList supportedFormats = m_supportedContainers.supportedCodecs();
+diff --git a/src/plugins/gstreamer/camerabin/camerabincontrol.cpp b/src/plugins/gstreamer/camerabin/camerabincontrol.cpp
+index 3ec9927..8c6b8b0 100644
+--- a/src/plugins/gstreamer/camerabin/camerabincontrol.cpp
++++ b/src/plugins/gstreamer/camerabin/camerabincontrol.cpp
+@@ -95,11 +95,6 @@ void CameraBinControl::setCaptureMode(QCamera::CaptureModes mode)
+ captureMode() == QCamera::CaptureStillImage ?
+ CamerabinResourcePolicy::ImageCaptureResources :
+ CamerabinResourcePolicy::VideoCaptureResources);
+-#if (GST_VERSION_MAJOR == 0) && ((GST_VERSION_MINOR < 10) || (GST_VERSION_MICRO < 23))
+- //due to bug in v4l2src, it's necessary to reload camera on video caps changes
+- //https://bugzilla.gnome.org/show_bug.cgi?id=649832
+- reloadLater();
+-#endif
+ }
+ emit captureModeChanged(mode);
+ }
+@@ -299,6 +294,8 @@ bool CameraBinControl::canChangeProperty(PropertyChangeType changeType, QCamera:
+
+ switch (changeType) {
+ case QCameraControl::CaptureMode:
++ return status != QCamera::ActiveStatus;
++ break;
+ case QCameraControl::ImageEncodingSettings:
+ case QCameraControl::VideoEncodingSettings:
+ case QCameraControl::Viewfinder:
+diff --git a/src/plugins/gstreamer/camerabin/camerabinexposure.cpp b/src/plugins/gstreamer/camerabin/camerabinexposure.cpp
+index a235de2..795fd42 100644
+--- a/src/plugins/gstreamer/camerabin/camerabinexposure.cpp
++++ b/src/plugins/gstreamer/camerabin/camerabinexposure.cpp
+@@ -37,6 +37,10 @@
+
+ #include <QDebug>
+
++#if !GST_CHECK_VERSION(1,0,0)
++typedef GstSceneMode GstPhotographySceneMode;
++#endif
++
+ QT_BEGIN_NAMESPACE
+
+ CameraBinExposure::CameraBinExposure(CameraBinSession *session)
+@@ -119,7 +123,7 @@ QVariant CameraBinExposure::actualValue(ExposureParameter parameter) const
+ }
+ case QCameraExposureControl::ExposureMode:
+ {
+- GstSceneMode sceneMode;
++ GstPhotographySceneMode sceneMode;
+ gst_photography_get_scene_mode(m_session->photography(), &sceneMode);
+
+ switch (sceneMode) {
+@@ -167,7 +171,7 @@ bool CameraBinExposure::setValue(ExposureParameter parameter, const QVariant& va
+ case QCameraExposureControl::ExposureMode:
+ {
+ QCameraExposure::ExposureMode mode = QCameraExposure::ExposureMode(value.toInt());
+- GstSceneMode sceneMode;
++ GstPhotographySceneMode sceneMode;
+ gst_photography_get_scene_mode(m_session->photography(), &sceneMode);
+
+ switch (mode) {
+diff --git a/src/plugins/gstreamer/camerabin/camerabinflash.cpp b/src/plugins/gstreamer/camerabin/camerabinflash.cpp
+index 2140f66..51bb9a2 100644
+--- a/src/plugins/gstreamer/camerabin/camerabinflash.cpp
++++ b/src/plugins/gstreamer/camerabin/camerabinflash.cpp
+@@ -37,6 +37,10 @@
+
+ #include <QDebug>
+
++#if !GST_CHECK_VERSION(1,0,0)
++typedef GstFlashMode GstPhotographyFlashMode;
++#endif
++
+ QT_BEGIN_NAMESPACE
+
+ CameraBinFlash::CameraBinFlash(CameraBinSession *session)
+@@ -51,7 +55,7 @@ CameraBinFlash::~CameraBinFlash()
+
+ QCameraExposure::FlashModes CameraBinFlash::flashMode() const
+ {
+- GstFlashMode flashMode;
++ GstPhotographyFlashMode flashMode;
+ gst_photography_get_flash_mode(m_session->photography(), &flashMode);
+
+ QCameraExposure::FlashModes modes;
+@@ -70,7 +74,7 @@ QCameraExposure::FlashModes CameraBinFlash::flashMode() const
+
+ void CameraBinFlash::setFlashMode(QCameraExposure::FlashModes mode)
+ {
+- GstFlashMode flashMode;
++ GstPhotographyFlashMode flashMode;
+ gst_photography_get_flash_mode(m_session->photography(), &flashMode);
+
+ if (mode.testFlag(QCameraExposure::FlashAuto)) flashMode = GST_PHOTOGRAPHY_FLASH_MODE_AUTO;
+diff --git a/src/plugins/gstreamer/camerabin/camerabinfocus.cpp b/src/plugins/gstreamer/camerabin/camerabinfocus.cpp
+index 665e204..061c680 100644
+--- a/src/plugins/gstreamer/camerabin/camerabinfocus.cpp
++++ b/src/plugins/gstreamer/camerabin/camerabinfocus.cpp
+@@ -39,6 +39,12 @@
+ #include <QDebug>
+ #include <QtCore/qmetaobject.h>
+
++#include <private/qgstutils_p.h>
++
++#if !GST_CHECK_VERSION(1,0,0)
++typedef GstFocusMode GstPhotographyFocusMode;
++#endif
++
+ //#define CAMERABIN_DEBUG 1
+
+ QT_BEGIN_NAMESPACE
+@@ -73,7 +79,7 @@ QCameraFocus::FocusModes CameraBinFocus::focusMode() const
+
+ void CameraBinFocus::setFocusMode(QCameraFocus::FocusModes mode)
+ {
+- GstFocusMode photographyMode;
++ GstPhotographyFocusMode photographyMode;
+
+ switch (mode) {
+ case QCameraFocus::AutoFocus:
+@@ -181,9 +187,10 @@ QCameraFocusZoneList CameraBinFocus::focusZones() const
+ void CameraBinFocus::handleFocusMessage(GstMessage *gm)
+ {
+ //it's a sync message, so it's called from non main thread
+- if (gst_structure_has_name(gm->structure, GST_PHOTOGRAPHY_AUTOFOCUS_DONE)) {
++ const GstStructure *structure = gst_message_get_structure(gm);
++ if (gst_structure_has_name(structure, GST_PHOTOGRAPHY_AUTOFOCUS_DONE)) {
+ gint status = GST_PHOTOGRAPHY_FOCUS_STATUS_NONE;
+- gst_structure_get_int (gm->structure, "status", &status);
++ gst_structure_get_int (structure, "status", &status);
+ QCamera::LockStatus focusStatus = m_focusStatus;
+ QCamera::LockChangeReason reason = QCamera::UserRequest;
+
+@@ -243,7 +250,7 @@ void CameraBinFocus::_q_handleCameraStateChange(QCamera::State state)
+ m_cameraState = state;
+ if (state == QCamera::ActiveState) {
+ if (GstPad *pad = gst_element_get_static_pad(m_session->cameraSource(), "vfsrc")) {
+- if (GstCaps *caps = gst_pad_get_negotiated_caps(pad)) {
++ if (GstCaps *caps = qt_gst_pad_get_current_caps(pad)) {
+ if (GstStructure *structure = gst_caps_get_structure(caps, 0)) {
+ int width = 0;
+ int height = 0;
+diff --git a/src/plugins/gstreamer/camerabin/camerabinimagecapture.cpp b/src/plugins/gstreamer/camerabin/camerabinimagecapture.cpp
+index 6952155..8b51306 100644
+--- a/src/plugins/gstreamer/camerabin/camerabinimagecapture.cpp
++++ b/src/plugins/gstreamer/camerabin/camerabinimagecapture.cpp
+@@ -53,11 +53,13 @@ QT_BEGIN_NAMESPACE
+
+ CameraBinImageCapture::CameraBinImageCapture(CameraBinSession *session)
+ :QCameraImageCaptureControl(session)
++ , m_encoderProbe(this)
++ , m_muxerProbe(this)
+ , m_session(session)
+- , m_ready(false)
+- , m_requestId(0)
+ , m_jpegEncoderElement(0)
+ , m_metadataMuxerElement(0)
++ , m_requestId(0)
++ , m_ready(false)
+ {
+ connect(m_session, SIGNAL(stateChanged(QCamera::State)), SLOT(updateState()));
+ connect(m_session, SIGNAL(imageExposed(int)), this, SIGNAL(imageExposed(int)));
+@@ -108,11 +110,18 @@ void CameraBinImageCapture::updateState()
+ }
+ }
+
+-gboolean CameraBinImageCapture::metadataEventProbe(GstPad *pad, GstEvent *event, CameraBinImageCapture *self)
++#if GST_CHECK_VERSION(1,0,0)
++GstPadProbeReturn CameraBinImageCapture::encoderEventProbe(
++ GstPad *, GstPadProbeInfo *info, gpointer user_data)
+ {
+- Q_UNUSED(pad);
+-
+- if (GST_EVENT_TYPE(event) == GST_EVENT_TAG) {
++ GstEvent * const event = gst_pad_probe_info_get_event(info);
++#else
++gboolean CameraBinImageCapture::encoderEventProbe(
++ GstElement *, GstEvent *event, gpointer user_data)
++{
++#endif
++ CameraBinImageCapture * const self = static_cast<CameraBinImageCapture *>(user_data);
++ if (event && GST_EVENT_TYPE(event) == GST_EVENT_TAG) {
+ GstTagList *gstTags;
+ gst_event_parse_tag(event, &gstTags);
+ QMap<QByteArray, QVariant> extendedTags = QGstUtils::gstTagListToMap(gstTags);
+@@ -146,17 +155,31 @@ gboolean CameraBinImageCapture::metadataEventProbe(GstPad *pad, GstEvent *event,
+ }
+ }
+ }
++#if GST_CHECK_VERSION(1,0,0)
++ return GST_PAD_PROBE_OK;
++#else
++ return TRUE;
++#endif
++}
+
+- return true;
++void CameraBinImageCapture::EncoderProbe::probeCaps(GstCaps *caps)
++{
++#if GST_CHECK_VERSION(1,0,0)
++ capture->m_bufferFormat = QGstUtils::formatForCaps(caps, &capture->m_videoInfo);
++#else
++ int bytesPerLine = 0;
++ QVideoSurfaceFormat format = QGstUtils::formatForCaps(caps, &bytesPerLine);
++ capture->m_bytesPerLine = bytesPerLine;
++ capture->m_bufferFormat = format;
++#endif
+ }
+
+-gboolean CameraBinImageCapture::uncompressedBufferProbe(GstPad *pad, GstBuffer *buffer, CameraBinImageCapture *self)
++bool CameraBinImageCapture::EncoderProbe::probeBuffer(GstBuffer *buffer)
+ {
+- Q_UNUSED(pad);
+- CameraBinSession *session = self->m_session;
++ CameraBinSession * const session = capture->m_session;
+
+ #ifdef DEBUG_CAPTURE
+- qDebug() << "Uncompressed buffer probe" << gst_caps_to_string(GST_BUFFER_CAPS(buffer));
++ qDebug() << "Uncompressed buffer probe";
+ #endif
+
+ QCameraImageCapture::CaptureDestinations destination =
+@@ -165,21 +188,23 @@ gboolean CameraBinImageCapture::uncompressedBufferProbe(GstPad *pad, GstBuffer *
+
+ if (destination & QCameraImageCapture::CaptureToBuffer) {
+ if (format != QVideoFrame::Format_Jpeg) {
+- GstCaps *caps = GST_BUFFER_CAPS(buffer);
+- int bytesPerLine = -1;
+- QVideoSurfaceFormat format = QVideoSurfaceGstSink::formatForCaps(caps, &bytesPerLine);
+ #ifdef DEBUG_CAPTURE
+ qDebug() << "imageAvailable(uncompressed):" << format;
+ #endif
+- QGstVideoBuffer *videoBuffer = new QGstVideoBuffer(buffer, bytesPerLine);
++#if GST_CHECK_VERSION(1,0,0)
++ QGstVideoBuffer *videoBuffer = new QGstVideoBuffer(buffer, capture->m_videoInfo);
++#else
++ QGstVideoBuffer *videoBuffer = new QGstVideoBuffer(buffer, capture->m_bytesPerLine);
++#endif
+
+- QVideoFrame frame(videoBuffer,
+- format.frameSize(),
+- format.pixelFormat());
++ QVideoFrame frame(
++ videoBuffer,
++ capture->m_bufferFormat.frameSize(),
++ capture->m_bufferFormat.pixelFormat());
+
+- QMetaObject::invokeMethod(self, "imageAvailable",
++ QMetaObject::invokeMethod(capture, "imageAvailable",
+ Qt::QueuedConnection,
+- Q_ARG(int, self->m_requestId),
++ Q_ARG(int, capture->m_requestId),
+ Q_ARG(QVideoFrame, frame));
+ }
+ }
+@@ -192,25 +217,40 @@ gboolean CameraBinImageCapture::uncompressedBufferProbe(GstPad *pad, GstBuffer *
+ return keepBuffer;
+ }
+
+-gboolean CameraBinImageCapture::jpegBufferProbe(GstPad *pad, GstBuffer *buffer, CameraBinImageCapture *self)
++void CameraBinImageCapture::MuxerProbe::probeCaps(GstCaps *caps)
+ {
+- Q_UNUSED(pad);
+- CameraBinSession *session = self->m_session;
++ capture->m_jpegResolution = QGstUtils::capsCorrectedResolution(caps);
++}
+
+-#ifdef DEBUG_CAPTURE
+- qDebug() << "Jpeg buffer probe" << gst_caps_to_string(GST_BUFFER_CAPS(buffer));
+-#endif
++bool CameraBinImageCapture::MuxerProbe::probeBuffer(GstBuffer *buffer)
++{
++ CameraBinSession * const session = capture->m_session;
+
+ QCameraImageCapture::CaptureDestinations destination =
+ session->captureDestinationControl()->captureDestination();
+
+ if ((destination & QCameraImageCapture::CaptureToBuffer) &&
+ session->captureBufferFormatControl()->bufferFormat() == QVideoFrame::Format_Jpeg) {
+- QGstVideoBuffer *videoBuffer = new QGstVideoBuffer(buffer,
+- -1); //bytesPerLine is not available for jpegs
+
+- QSize resolution = QGstUtils::capsCorrectedResolution(GST_BUFFER_CAPS(buffer));
++ QSize resolution = capture->m_jpegResolution;
+ //if resolution is not presented in caps, try to find it from encoded jpeg data:
++#if GST_CHECK_VERSION(1,0,0)
++ GstMapInfo mapInfo;
++ if (resolution.isEmpty() && gst_buffer_map(buffer, &mapInfo, GST_MAP_READ)) {
++ QBuffer data;
++ data.setData(reinterpret_cast<const char*>(mapInfo.data), mapInfo.size);
++
++ QImageReader reader(&data, "JPEG");
++ resolution = reader.size();
++
++ gst_buffer_unmap(buffer, &mapInfo);
++ }
++
++ GstVideoInfo info;
++ gst_video_info_set_format(
++ &info, GST_VIDEO_FORMAT_ENCODED, resolution.width(), resolution.height());
++ QGstVideoBuffer *videoBuffer = new QGstVideoBuffer(buffer, info);
++#else
+ if (resolution.isEmpty()) {
+ QBuffer data;
+ data.setData(reinterpret_cast<const char*>(GST_BUFFER_DATA(buffer)), GST_BUFFER_SIZE(buffer));
+@@ -218,20 +258,28 @@ gboolean CameraBinImageCapture::jpegBufferProbe(GstPad *pad, GstBuffer *buffer,
+ resolution = reader.size();
+ }
+
++ QGstVideoBuffer *videoBuffer = new QGstVideoBuffer(buffer,
++ -1); //bytesPerLine is not available for jpegs
++#endif
++
++
+ QVideoFrame frame(videoBuffer,
+ resolution,
+ QVideoFrame::Format_Jpeg);
+-
+- QMetaObject::invokeMethod(self, "imageAvailable",
++ QMetaObject::invokeMethod(capture, "imageAvailable",
+ Qt::QueuedConnection,
+- Q_ARG(int, self->m_requestId),
++ Q_ARG(int, capture->m_requestId),
+ Q_ARG(QVideoFrame, frame));
+ }
+
+- //drop the buffer if capture to file was disabled
+- return destination & QCameraImageCapture::CaptureToFile;
++
++ // Theoretically we could drop the buffer here when don't want to capture to file but that
++ // prevents camerabin from recognizing that capture has been completed and returning
++ // to its idle state.
++ return true;
+ }
+
++
+ bool CameraBinImageCapture::processBusMessage(const QGstreamerMessage &message)
+ {
+ //Install metadata event and buffer probes
+@@ -252,9 +300,10 @@ bool CameraBinImageCapture::processBusMessage(const QGstreamerMessage &message)
+ return false;
+
+ QString elementName = QString::fromLatin1(gst_element_get_name(element));
++#if !GST_CHECK_VERSION(1,0,0)
+ GstElementClass *elementClass = GST_ELEMENT_GET_CLASS(element);
+ QString elementLongName = elementClass->details.longname;
+-
++#endif
+ if (elementName.contains("jpegenc") && element != m_jpegEncoderElement) {
+ m_jpegEncoderElement = element;
+ GstPad *sinkpad = gst_element_get_static_pad(element, "sink");
+@@ -264,21 +313,23 @@ bool CameraBinImageCapture::processBusMessage(const QGstreamerMessage &message)
+ #ifdef DEBUG_CAPTURE
+ qDebug() << "install metadata probe";
+ #endif
+- gst_pad_add_event_probe(sinkpad,
+- G_CALLBACK(CameraBinImageCapture::metadataEventProbe),
+- this);
+-
++#if GST_CHECK_VERSION(1,0,0)
++ gst_pad_add_probe(
++ sinkpad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, encoderEventProbe, this, NULL);
++#else
++ gst_pad_add_event_probe(sinkpad, G_CALLBACK(encoderEventProbe), this);
++#endif
+ #ifdef DEBUG_CAPTURE
+ qDebug() << "install uncompressed buffer probe";
+ #endif
+- gst_pad_add_buffer_probe(sinkpad,
+- G_CALLBACK(CameraBinImageCapture::uncompressedBufferProbe),
+- this);
++ m_encoderProbe.addProbeToPad(sinkpad, true);
+
+ gst_object_unref(sinkpad);
+- } else if ((elementName.contains("jifmux") ||
+- elementName.startsWith("metadatamux") ||
+- elementLongName == QLatin1String("JPEG stream muxer"))
++ } else if ((elementName.contains("jifmux")
++#if !GST_CHECK_VERSION(1,0,0)
++ || elementLongName == QLatin1String("JPEG stream muxer")
++#endif
++ || elementName.startsWith("metadatamux"))
+ && element != m_metadataMuxerElement) {
+ //Jpeg encoded buffer probe is added after jifmux/metadatamux
+ //element to ensure the resulting jpeg buffer contains capture metadata
+@@ -288,9 +339,8 @@ bool CameraBinImageCapture::processBusMessage(const QGstreamerMessage &message)
+ #ifdef DEBUG_CAPTURE
+ qDebug() << "install jpeg buffer probe";
+ #endif
+- gst_pad_add_buffer_probe(srcpad,
+- G_CALLBACK(CameraBinImageCapture::jpegBufferProbe),
+- this);
++ m_muxerProbe.addProbeToPad(srcpad);
++
+ gst_object_unref(srcpad);
+ }
+ }
+diff --git a/src/plugins/gstreamer/camerabin/camerabinimagecapture.h b/src/plugins/gstreamer/camerabin/camerabinimagecapture.h
+index c2e26f5..9a52dd9 100644
+--- a/src/plugins/gstreamer/camerabin/camerabinimagecapture.h
++++ b/src/plugins/gstreamer/camerabin/camerabinimagecapture.h
+@@ -38,6 +38,14 @@
+ #include <qcameraimagecapturecontrol.h>
+ #include "camerabinsession.h"
+
++#include <qvideosurfaceformat.h>
++
++#include <private/qgstreamerbufferprobe_p.h>
++
++#if GST_CHECK_VERSION(1,0,0)
++#include <gst/video/video.h>
++#endif
++
+ QT_BEGIN_NAMESPACE
+
+ class CameraBinImageCapture : public QCameraImageCaptureControl, public QGstreamerBusMessageFilter
+@@ -61,15 +69,47 @@ private slots:
+ void updateState();
+
+ private:
+- static gboolean metadataEventProbe(GstPad *pad, GstEvent *event, CameraBinImageCapture *);
+- static gboolean uncompressedBufferProbe(GstPad *pad, GstBuffer *buffer, CameraBinImageCapture *);
+- static gboolean jpegBufferProbe(GstPad *pad, GstBuffer *buffer, CameraBinImageCapture *);
++#if GST_CHECK_VERSION(1,0,0)
++ static GstPadProbeReturn encoderEventProbe(GstPad *, GstPadProbeInfo *info, gpointer user_data);
++#else
++ static gboolean encoderEventProbe(GstElement *, GstEvent *event, gpointer user_data);
++#endif
++
++ class EncoderProbe : public QGstreamerBufferProbe
++ {
++ public:
++ EncoderProbe(CameraBinImageCapture *capture) : capture(capture) {}
++ void probeCaps(GstCaps *caps);
++ bool probeBuffer(GstBuffer *buffer);
++
++ private:
++ CameraBinImageCapture * const capture;
++ } m_encoderProbe;
++
++ class MuxerProbe : public QGstreamerBufferProbe
++ {
++ public:
++ MuxerProbe(CameraBinImageCapture *capture) : capture(capture) {}
++ void probeCaps(GstCaps *caps);
++ bool probeBuffer(GstBuffer *buffer);
+
++ private:
++ CameraBinImageCapture * const capture;
++
++ } m_muxerProbe;
++
++ QVideoSurfaceFormat m_bufferFormat;
++ QSize m_jpegResolution;
+ CameraBinSession *m_session;
+- bool m_ready;
+- int m_requestId;
+ GstElement *m_jpegEncoderElement;
+ GstElement *m_metadataMuxerElement;
++#if GST_CHECK_VERSION(1,0,0)
++ GstVideoInfo m_videoInfo;
++#else
++ int m_bytesPerLine;
++#endif
++ int m_requestId;
++ bool m_ready;
+ };
+
+ QT_END_NAMESPACE
+diff --git a/src/plugins/gstreamer/camerabin/camerabinimageencoder.cpp b/src/plugins/gstreamer/camerabin/camerabinimageencoder.cpp
+index 824f996..739364f 100644
+--- a/src/plugins/gstreamer/camerabin/camerabinimageencoder.cpp
++++ b/src/plugins/gstreamer/camerabin/camerabinimageencoder.cpp
+@@ -49,7 +49,6 @@ CameraBinImageEncoder::~CameraBinImageEncoder()
+
+ QList<QSize> CameraBinImageEncoder::supportedResolutions(const QImageEncoderSettings &, bool *continuous) const
+ {
+- qDebug() << "CameraBinImageEncoder::supportedResolutions()";
+ if (continuous)
+ *continuous = false;
+
+diff --git a/src/plugins/gstreamer/camerabin/camerabinimageprocessing.cpp b/src/plugins/gstreamer/camerabin/camerabinimageprocessing.cpp
+index ebfb087..811225f 100644
+--- a/src/plugins/gstreamer/camerabin/camerabinimageprocessing.cpp
++++ b/src/plugins/gstreamer/camerabin/camerabinimageprocessing.cpp
+@@ -34,7 +34,11 @@
+ #include "camerabinimageprocessing.h"
+ #include "camerabinsession.h"
+
+-#include <gst/interfaces/colorbalance.h>
++#if GST_CHECK_VERSION(1,0,0)
++# include <gst/video/colorbalance.h>
++#else
++# include <gst/interfaces/colorbalance.h>
++#endif
+
+ QT_BEGIN_NAMESPACE
+
+@@ -126,7 +130,7 @@ bool CameraBinImageProcessing::setColorBalanceValue(const QString& channel, qrea
+ QCameraImageProcessing::WhiteBalanceMode CameraBinImageProcessing::whiteBalanceMode() const
+ {
+ #ifdef HAVE_GST_PHOTOGRAPHY
+- GstWhiteBalanceMode wbMode;
++ GstPhotographyWhiteBalanceMode wbMode;
+ gst_photography_get_white_balance_mode(m_session->photography(), &wbMode);
+ return m_mappedWbValues[wbMode];
+ #else
+diff --git a/src/plugins/gstreamer/camerabin/camerabinimageprocessing.h b/src/plugins/gstreamer/camerabin/camerabinimageprocessing.h
+index dcefcd0..2c6347f 100644
+--- a/src/plugins/gstreamer/camerabin/camerabinimageprocessing.h
++++ b/src/plugins/gstreamer/camerabin/camerabinimageprocessing.h
+@@ -41,7 +41,10 @@
+ #include <glib.h>
+
+ #ifdef HAVE_GST_PHOTOGRAPHY
+-#include <gst/interfaces/photography.h>
++# include <gst/interfaces/photography.h>
++# if !GST_CHECK_VERSION(1,0,0)
++typedef GstWhiteBalanceMode GstPhotographyWhiteBalanceMode;
++# endif
+ #endif
+
+ QT_BEGIN_NAMESPACE
+@@ -73,7 +76,7 @@ private:
+ CameraBinSession *m_session;
+ QMap<QCameraImageProcessingControl::ProcessingParameter, int> m_values;
+ #ifdef HAVE_GST_PHOTOGRAPHY
+- QMap<GstWhiteBalanceMode, QCameraImageProcessing::WhiteBalanceMode> m_mappedWbValues;
++ QMap<GstPhotographyWhiteBalanceMode, QCameraImageProcessing::WhiteBalanceMode> m_mappedWbValues;
+ #endif
+ };
+
+diff --git a/src/plugins/gstreamer/camerabin/camerabinmetadata.cpp b/src/plugins/gstreamer/camerabin/camerabinmetadata.cpp
+index 5148135..bc1b260 100644
+--- a/src/plugins/gstreamer/camerabin/camerabinmetadata.cpp
++++ b/src/plugins/gstreamer/camerabin/camerabinmetadata.cpp
+@@ -126,7 +126,7 @@ static const QGStreamerMetaDataKeys *qt_gstreamerMetaDataKeys()
+ metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::AlbumTitle, GST_TAG_ALBUM, QVariant::String));
+ metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::AlbumArtist, GST_TAG_ARTIST, QVariant::String));
+ metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::ContributingArtist, GST_TAG_PERFORMER, QVariant::String));
+-#if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 19)
++#if GST_CHECK_VERSION(0,10,19)
+ metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Composer, GST_TAG_COMPOSER, QVariant::String));
+ #endif
+ //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Conductor, 0, QVariant::String));
+@@ -153,8 +153,7 @@ static const QGStreamerMetaDataKeys *qt_gstreamerMetaDataKeys()
+ //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Director, 0, QVariant::String));
+ metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::LeadPerformer, GST_TAG_PERFORMER, QVariant::String));
+ //metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Writer, 0, QVariant::String));
+-
+-#if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 30)
++#if GST_CHECK_VERSION(0,10,30)
+ // Photos
+ metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::CameraManufacturer, GST_TAG_DEVICE_MANUFACTURER, QVariant::String));
+ metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::CameraModel, GST_TAG_DEVICE_MODEL, QVariant::String));
+diff --git a/src/plugins/gstreamer/camerabin/camerabinrecorder.cpp b/src/plugins/gstreamer/camerabin/camerabinrecorder.cpp
+index 3a04c2f..801c7ab 100644
+--- a/src/plugins/gstreamer/camerabin/camerabinrecorder.cpp
++++ b/src/plugins/gstreamer/camerabin/camerabinrecorder.cpp
+@@ -110,9 +110,10 @@ void CameraBinRecorder::updateStatus()
+ m_state = QMediaRecorder::StoppedState;
+ m_session->stopVideoRecording();
+ }
+- m_status = m_session->pendingState() == QCamera::ActiveState ?
+- QMediaRecorder::LoadingStatus :
+- QMediaRecorder::UnloadedStatus;
++ m_status = m_session->pendingState() == QCamera::ActiveState
++ && m_session->captureMode().testFlag(QCamera::CaptureVideo)
++ ? QMediaRecorder::LoadingStatus
++ : QMediaRecorder::UnloadedStatus;
+ }
+
+ if (m_state != oldState)
+@@ -161,8 +162,6 @@ void CameraBinRecorder::applySettings()
+
+ QVideoEncoderSettings videoSettings = videoEncoderControl->videoSettings();
+ videoSettings.setCodec(candidate[1]);
+- if (videoSettings.resolution().isEmpty())
+- videoSettings.setResolution(640, 480);
+ videoEncoderControl->setActualVideoSettings(videoSettings);
+
+ QAudioEncoderSettings audioSettings = audioEncoderControl->audioSettings();
+diff --git a/src/plugins/gstreamer/camerabin/camerabinservice.cpp b/src/plugins/gstreamer/camerabin/camerabinservice.cpp
+index 969955f..388f2fd 100644
+--- a/src/plugins/gstreamer/camerabin/camerabinservice.cpp
++++ b/src/plugins/gstreamer/camerabin/camerabinservice.cpp
+@@ -56,11 +56,11 @@
+ #include "camerabincapturedestination.h"
+ #include "camerabinviewfindersettings.h"
+ #include <private/qgstreamerbushelper_p.h>
++#include <private/qgstutils_p.h>
+
+ #include <private/qgstreameraudioinputselector_p.h>
+ #include <private/qgstreamervideoinputdevicecontrol_p.h>
+
+-
+ #if defined(HAVE_WIDGETS)
+ #include <private/qgstreamervideowidget_p.h>
+ #endif
+@@ -121,7 +121,6 @@ CameraBinService::CameraBinService(GstElementFactory *sourceFactory, QObject *pa
+ #else
+ m_videoWindow = new QGstreamerVideoWindow(this);
+ #endif
+-
+ #if defined(HAVE_WIDGETS)
+ m_videoWidgetControl = new QGstreamerVideoWidgetControl(this);
+ #endif
+@@ -150,8 +149,6 @@ QMediaControl *CameraBinService::requestControl(const char *name)
+ if (!m_captureSession)
+ return 0;
+
+- //qDebug() << "Request control" << name;
+-
+ if (!m_videoOutput) {
+ if (qstrcmp(name, QVideoRendererControl_iid) == 0) {
+ m_videoOutput = m_videoRenderer;
+@@ -249,7 +246,7 @@ void CameraBinService::releaseControl(QMediaControl *control)
+
+ bool CameraBinService::isCameraBinAvailable()
+ {
+- GstElementFactory *factory = gst_element_factory_find("camerabin2");
++ GstElementFactory *factory = gst_element_factory_find(QT_GSTREAMER_CAMERABIN_ELEMENT_NAME);
+ if (factory) {
+ gst_object_unref(GST_OBJECT(factory));
+ return true;
+diff --git a/src/plugins/gstreamer/camerabin/camerabinsession.cpp b/src/plugins/gstreamer/camerabin/camerabinsession.cpp
+index a4038c5..f916b58 100644
+--- a/src/plugins/gstreamer/camerabin/camerabinsession.cpp
++++ b/src/plugins/gstreamer/camerabin/camerabinsession.cpp
+@@ -140,8 +140,8 @@ CameraBinSession::CameraBinSession(GstElementFactory *sourceFactory, QObject *pa
+ {
+ if (m_sourceFactory)
+ gst_object_ref(GST_OBJECT(m_sourceFactory));
++ m_camerabin = gst_element_factory_make(QT_GSTREAMER_CAMERABIN_ELEMENT_NAME, "camerabin");
+
+- m_camerabin = gst_element_factory_make("camerabin2", "camerabin2");
+ g_signal_connect(G_OBJECT(m_camerabin), "notify::idle", G_CALLBACK(updateBusyStatus), this);
+ g_signal_connect(G_OBJECT(m_camerabin), "element-added", G_CALLBACK(elementAdded), this);
+ g_signal_connect(G_OBJECT(m_camerabin), "element-removed", G_CALLBACK(elementRemoved), this);
+@@ -178,7 +178,15 @@ CameraBinSession::CameraBinSession(GstElementFactory *sourceFactory, QObject *pa
+ //post image preview in RGB format
+ g_object_set(G_OBJECT(m_camerabin), POST_PREVIEWS_PROPERTY, TRUE, NULL);
+
++#if GST_CHECK_VERSION(1,0,0)
++ GstCaps *previewCaps = gst_caps_new_simple(
++ "video/x-raw",
++ "format", G_TYPE_STRING, "RGBx",
++ NULL);
++#else
+ GstCaps *previewCaps = gst_caps_from_string("video/x-raw-rgb");
++#endif
++
+ g_object_set(G_OBJECT(m_camerabin), PREVIEW_CAPS_PROPERTY, previewCaps, NULL);
+ gst_caps_unref(previewCaps);
+ }
+@@ -243,6 +251,7 @@ bool CameraBinSession::setupCameraBin()
+ qWarning() << "Staring camera without viewfinder available";
+ m_viewfinderElement = gst_element_factory_make("fakesink", NULL);
+ }
++ g_object_set(G_OBJECT(m_viewfinderElement), "sync", FALSE, NULL);
+ qt_gst_object_ref_sink(GST_OBJECT(m_viewfinderElement));
+ gst_element_set_state(m_camerabin, GST_STATE_NULL);
+ g_object_set(G_OBJECT(m_camerabin), VIEWFINDER_SINK_PROPERTY, m_viewfinderElement, NULL);
+@@ -251,61 +260,27 @@ bool CameraBinSession::setupCameraBin()
+ return true;
+ }
+
+-static GstCaps *resolutionToCaps(const QSize &resolution, const QPair<int, int> &rate = qMakePair<int,int>(0,0))
++static GstCaps *resolutionToCaps(const QSize &resolution, qreal frameRate = 0.0)
+ {
+- if (resolution.isEmpty())
+- return gst_caps_new_any();
++ GstCaps *caps = QGstUtils::videoFilterCaps();
+
+- GstCaps *caps = 0;
+- if (rate.second > 0) {
+- caps = gst_caps_new_full(gst_structure_new("video/x-raw-yuv",
+- "width", G_TYPE_INT, resolution.width(),
+- "height", G_TYPE_INT, resolution.height(),
+- "framerate", GST_TYPE_FRACTION, rate.first, rate.second,
+- NULL),
+- gst_structure_new("video/x-raw-rgb",
+- "width", G_TYPE_INT, resolution.width(),
+- "height", G_TYPE_INT, resolution.height(),
+- "framerate", GST_TYPE_FRACTION, rate.first, rate.second,
+- NULL),
+- gst_structure_new("video/x-raw-data",
+- "width", G_TYPE_INT, resolution.width(),
+- "height", G_TYPE_INT, resolution.height(),
+- "framerate", GST_TYPE_FRACTION, rate.first, rate.second,
+- NULL),
+- gst_structure_new("video/x-android-buffer",
+- "width", G_TYPE_INT, resolution.width(),
+- "height", G_TYPE_INT, resolution.height(),
+- "framerate", GST_TYPE_FRACTION, rate.first, rate.second,
+- NULL),
+- gst_structure_new("image/jpeg",
+- "width", G_TYPE_INT, resolution.width(),
+- "height", G_TYPE_INT, resolution.height(),
+- "framerate", GST_TYPE_FRACTION, rate.first, rate.second,
+- NULL),
+- NULL);
+- } else {
+- caps = gst_caps_new_full (gst_structure_new ("video/x-raw-yuv",
+- "width", G_TYPE_INT, resolution.width(),
+- "height", G_TYPE_INT, resolution.height(),
+- NULL),
+- gst_structure_new ("video/x-raw-rgb",
+- "width", G_TYPE_INT, resolution.width(),
+- "height", G_TYPE_INT, resolution.height(),
+- NULL),
+- gst_structure_new("video/x-raw-data",
+- "width", G_TYPE_INT, resolution.width(),
+- "height", G_TYPE_INT, resolution.height(),
+- NULL),
+- gst_structure_new ("video/x-android-buffer",
+- "width", G_TYPE_INT, resolution.width(),
+- "height", G_TYPE_INT, resolution.height(),
+- NULL),
+- gst_structure_new ("image/jpeg",
+- "width", G_TYPE_INT, resolution.width(),
+- "height", G_TYPE_INT, resolution.height(),
+- NULL),
+- NULL);
++ if (!resolution.isEmpty()) {
++ gst_caps_set_simple(
++ caps,
++ "width", G_TYPE_INT, resolution.width(),
++ "height", G_TYPE_INT, resolution.height(),
++ NULL);
++ }
++
++ if (frameRate > 0.0) {
++ gint numerator;
++ gint denominator;
++ gst_util_double_to_fraction(frameRate, &numerator, &denominator);
++
++ gst_caps_set_simple(
++ caps,
++ "framerate", GST_TYPE_FRACTION, numerator, denominator,
++ NULL);
+ }
+
+ return caps;
+@@ -314,40 +289,40 @@ static GstCaps *resolutionToCaps(const QSize &resolution, const QPair<int, int>
+ void CameraBinSession::setupCaptureResolution()
+ {
+ QSize resolution = m_imageEncodeControl->imageSettings().resolution();
+- if (!resolution.isEmpty()) {
++ {
+ GstCaps *caps = resolutionToCaps(resolution);
+ #if CAMERABIN_DEBUG
+- qDebug() << Q_FUNC_INFO << "set image resolution" << resolution << gst_caps_to_string(caps);
++ qDebug() << Q_FUNC_INFO << "set image resolution" << resolution << caps;
+ #endif
+ g_object_set(m_camerabin, IMAGE_CAPTURE_CAPS_PROPERTY, caps, NULL);
+- gst_caps_unref(caps);
+- } else {
+- g_object_set(m_camerabin, IMAGE_CAPTURE_CAPS_PROPERTY, NULL, NULL);
++ if (caps)
++ gst_caps_unref(caps);
+ }
+
++ const QSize viewfinderResolution = m_viewfinderSettingsControl->resolution();
+ resolution = m_videoEncodeControl->actualVideoSettings().resolution();
+- //qreal framerate = m_videoEncodeControl->videoSettings().frameRate();
+- if (!resolution.isEmpty()) {
+- GstCaps *caps = resolutionToCaps(resolution /*, framerate*/); //convert to rational
++ qreal framerate = m_videoEncodeControl->videoSettings().frameRate();
++ {
++ GstCaps *caps = resolutionToCaps(
++ !resolution.isEmpty() ? resolution : viewfinderResolution, framerate);
+ #if CAMERABIN_DEBUG
+- qDebug() << Q_FUNC_INFO << "set video resolution" << resolution << gst_caps_to_string(caps);
++ qDebug() << Q_FUNC_INFO << "set video resolution" << resolution << caps;
+ #endif
+ g_object_set(m_camerabin, VIDEO_CAPTURE_CAPS_PROPERTY, caps, NULL);
+- gst_caps_unref(caps);
+- } else {
+- g_object_set(m_camerabin, VIDEO_CAPTURE_CAPS_PROPERTY, NULL, NULL);
++ if (caps)
++ gst_caps_unref(caps);
+ }
+
+- resolution = m_viewfinderSettingsControl->resolution();
+- if (!resolution.isEmpty()) {
++ if (!viewfinderResolution.isEmpty())
++ resolution = viewfinderResolution;
++ {
+ GstCaps *caps = resolutionToCaps(resolution);
+ #if CAMERABIN_DEBUG
+- qDebug() << Q_FUNC_INFO << "set viewfinder resolution" << resolution << gst_caps_to_string(caps);
++ qDebug() << Q_FUNC_INFO << "set viewfinder resolution" << resolution << caps;
+ #endif
+ g_object_set(m_camerabin, VIEWFINDER_CAPS_PROPERTY, caps, NULL);
+- gst_caps_unref(caps);
+- } else {
+- g_object_set(m_camerabin, VIEWFINDER_CAPS_PROPERTY, NULL, NULL);
++ if (caps)
++ gst_caps_unref(caps);
+ }
+
+ if (m_videoEncoder)
+@@ -363,13 +338,17 @@ void CameraBinSession::setAudioCaptureCaps()
+ if (sampleRate == -1 && channelCount == -1)
+ return;
+
++#if GST_CHECK_VERSION(1,0,0)
++ GstStructure *structure = gst_structure_new_empty(QT_GSTREAMER_RAW_AUDIO_MIME);
++#else
+ GstStructure *structure = gst_structure_new(
+- "audio/x-raw-int",
++ QT_GSTREAMER_RAW_AUDIO_MIME,
+ "endianness", G_TYPE_INT, 1234,
+ "signed", G_TYPE_BOOLEAN, TRUE,
+ "width", G_TYPE_INT, 16,
+ "depth", G_TYPE_INT, 16,
+ NULL);
++#endif
+ if (sampleRate != -1)
+ gst_structure_set(structure, "rate", G_TYPE_INT, sampleRate, NULL);
+ if (channelCount != -1)
+@@ -760,7 +739,7 @@ qint64 CameraBinSession::duration() const
+ if (fileSink) {
+ GstFormat format = GST_FORMAT_TIME;
+ gint64 duration = 0;
+- bool ret = gst_element_query_position(fileSink, &format, &duration);
++ bool ret = qt_gst_element_query_position(fileSink, format, &duration);
+ gst_object_unref(GST_OBJECT(fileSink));
+ if (ret)
+ return duration / 1000000;
+@@ -795,129 +774,57 @@ void CameraBinSession::setMetaData(const QMap<QByteArray, QVariant> &data)
+ {
+ m_metaData = data;
+
+- if (m_camerabin) {
+- GstIterator *elements = gst_bin_iterate_all_by_interface(GST_BIN(m_camerabin), GST_TYPE_TAG_SETTER);
+- GstElement *element = 0;
+- while (gst_iterator_next(elements, (void**)&element) == GST_ITERATOR_OK) {
+- gst_tag_setter_reset_tags(GST_TAG_SETTER(element));
+-
+- QMapIterator<QByteArray, QVariant> it(data);
+- while (it.hasNext()) {
+- it.next();
+- const QString tagName = it.key();
+- const QVariant tagValue = it.value();
+-
+- switch(tagValue.type()) {
+- case QVariant::String:
+- gst_tag_setter_add_tags(GST_TAG_SETTER(element),
+- GST_TAG_MERGE_REPLACE,
+- tagName.toUtf8().constData(),
+- tagValue.toString().toUtf8().constData(),
+- NULL);
+- break;
+- case QVariant::Int:
+- case QVariant::LongLong:
+- gst_tag_setter_add_tags(GST_TAG_SETTER(element),
+- GST_TAG_MERGE_REPLACE,
+- tagName.toUtf8().constData(),
+- tagValue.toInt(),
+- NULL);
+- break;
+- case QVariant::Double:
+- gst_tag_setter_add_tags(GST_TAG_SETTER(element),
+- GST_TAG_MERGE_REPLACE,
+- tagName.toUtf8().constData(),
+- tagValue.toDouble(),
+- NULL);
+- break;
+- case QVariant::DateTime: {
+- QDateTime date = tagValue.toDateTime().toLocalTime();
+- gst_tag_setter_add_tags(GST_TAG_SETTER(element),
+- GST_TAG_MERGE_REPLACE,
+- tagName.toUtf8().constData(),
+- gst_date_time_new_local_time(
+- date.date().year(), date.date().month(), date.date().day(),
+- date.time().hour(), date.time().minute(), date.time().second()),
+- NULL);
+- break;
+- }
+- default:
+- break;
+- }
+- }
+- }
+- gst_iterator_free(elements);
+- }
++ if (m_camerabin)
++ QGstUtils::setMetaData(m_camerabin, data);
+ }
+
+ bool CameraBinSession::processSyncMessage(const QGstreamerMessage &message)
+ {
+ GstMessage* gm = message.rawMessage();
+- const GstStructure *st;
+- const GValue *image;
+- GstBuffer *buffer = NULL;
+
+ if (gm && GST_MESSAGE_TYPE(gm) == GST_MESSAGE_ELEMENT) {
+- if (m_captureMode == QCamera::CaptureStillImage &&
+- gst_structure_has_name(gm->structure, "preview-image")) {
+- st = gst_message_get_structure(gm);
+-
+- if (gst_structure_has_field_typed(st, "buffer", GST_TYPE_BUFFER)) {
+- image = gst_structure_get_value(st, "buffer");
+- if (image) {
+- buffer = gst_value_get_buffer(image);
+-
+- QImage img;
+-
+- GstCaps *caps = gst_buffer_get_caps(buffer);
+- if (caps) {
+- GstStructure *structure = gst_caps_get_structure(caps, 0);
+- gint width = 0;
+- gint height = 0;
+-#if CAMERABIN_DEBUG
+- qDebug() << "Preview caps:" << gst_structure_to_string(structure);
++ const GstStructure *st = gst_message_get_structure(gm);
++ const GValue *sampleValue = 0;
++ if (m_captureMode == QCamera::CaptureStillImage
++ && gst_structure_has_name(st, "preview-image")
++#if GST_CHECK_VERSION(1,0,0)
++ && gst_structure_has_field_typed(st, "sample", GST_TYPE_SAMPLE)
++ && (sampleValue = gst_structure_get_value(st, "sample"))) {
++ GstSample * const sample = gst_value_get_sample(sampleValue);
++ GstCaps * const previewCaps = gst_sample_get_caps(sample);
++ GstBuffer * const buffer = gst_sample_get_buffer(sample);
++#else
++ && gst_structure_has_field_typed(st, "buffer", GST_TYPE_BUFFER)
++ && (sampleValue = gst_structure_get_value(st, "buffer"))) {
++ GstBuffer * const buffer = gst_value_get_buffer(sampleValue);
+ #endif
+
+- if (structure &&
+- gst_structure_get_int(structure, "width", &width) &&
+- gst_structure_get_int(structure, "height", &height) &&
+- width > 0 && height > 0) {
+- if (qstrcmp(gst_structure_get_name(structure), "video/x-raw-rgb") == 0) {
+- QImage::Format format = QImage::Format_Invalid;
+- int bpp = 0;
+- gst_structure_get_int(structure, "bpp", &bpp);
+-
+- if (bpp == 24)
+- format = QImage::Format_RGB888;
+- else if (bpp == 32)
+- format = QImage::Format_RGB32;
+-
+- if (format != QImage::Format_Invalid) {
+- img = QImage((const uchar *)buffer->data, width, height, format);
+- img.bits(); //detach
+- }
+- }
+- }
+- gst_caps_unref(caps);
+-
+- static QMetaMethod exposedSignal = QMetaMethod::fromSignal(&CameraBinSession::imageExposed);
+- exposedSignal.invoke(this,
+- Qt::QueuedConnection,
+- Q_ARG(int,m_requestId));
+-
+- static QMetaMethod capturedSignal = QMetaMethod::fromSignal(&CameraBinSession::imageCaptured);
+- capturedSignal.invoke(this,
+- Qt::QueuedConnection,
+- Q_ARG(int,m_requestId),
+- Q_ARG(QImage,img));
+- }
+-
+- }
+- return true;
++ QImage image;
++#if GST_CHECK_VERSION(1,0,0)
++ GstVideoInfo previewInfo;
++ if (gst_video_info_from_caps(&previewInfo, previewCaps))
++ image = QGstUtils::bufferToImage(buffer, previewInfo);
++ gst_sample_unref(sample);
++#else
++ image = QGstUtils::bufferToImage(buffer);
++ gst_buffer_unref(buffer);
++#endif
++ if (!image.isNull()) {
++ static QMetaMethod exposedSignal = QMetaMethod::fromSignal(&CameraBinSession::imageExposed);
++ exposedSignal.invoke(this,
++ Qt::QueuedConnection,
++ Q_ARG(int,m_requestId));
++
++ static QMetaMethod capturedSignal = QMetaMethod::fromSignal(&CameraBinSession::imageCaptured);
++ capturedSignal.invoke(this,
++ Qt::QueuedConnection,
++ Q_ARG(int,m_requestId),
++ Q_ARG(QImage,image));
+ }
++ return true;
+ }
+ #ifdef HAVE_GST_PHOTOGRAPHY
+- if (gst_structure_has_name(gm->structure, GST_PHOTOGRAPHY_AUTOFOCUS_DONE))
++ if (gst_structure_has_name(st, GST_PHOTOGRAPHY_AUTOFOCUS_DONE))
+ m_cameraFocusControl->handleFocusMessage(gm);
+ #endif
+ }
+@@ -1109,20 +1016,12 @@ QList< QPair<int,int> > CameraBinSession::supportedFrameRates(const QSize &frame
+ if (frameSize.isEmpty()) {
+ caps = gst_caps_copy(supportedCaps);
+ } else {
+- GstCaps *filter = gst_caps_new_full(
+- gst_structure_new(
+- "video/x-raw-rgb",
+- "width" , G_TYPE_INT , frameSize.width(),
+- "height" , G_TYPE_INT, frameSize.height(), NULL),
+- gst_structure_new(
+- "video/x-raw-yuv",
+- "width" , G_TYPE_INT, frameSize.width(),
+- "height" , G_TYPE_INT, frameSize.height(), NULL),
+- gst_structure_new(
+- "image/jpeg",
+- "width" , G_TYPE_INT, frameSize.width(),
+- "height" , G_TYPE_INT, frameSize.height(), NULL),
+- NULL);
++ GstCaps *filter = QGstUtils::videoFilterCaps();
++ gst_caps_set_simple(
++ filter,
++ "width", G_TYPE_INT, frameSize.width(),
++ "height", G_TYPE_INT, frameSize.height(),
++ NULL);
+
+ caps = gst_caps_intersect(supportedCaps, filter);
+ gst_caps_unref(filter);
+@@ -1133,7 +1032,7 @@ QList< QPair<int,int> > CameraBinSession::supportedFrameRates(const QSize &frame
+ caps = gst_caps_make_writable(caps);
+ for (uint i=0; i<gst_caps_get_size(caps); i++) {
+ GstStructure *structure = gst_caps_get_structure(caps, i);
+- gst_structure_set_name(structure, "video/x-raw-yuv");
++ gst_structure_set_name(structure, "video/x-raw");
+ const GValue *oldRate = gst_structure_get_value(structure, "framerate");
+ GValue rate;
+ memset(&rate, 0, sizeof(rate));
+@@ -1142,8 +1041,11 @@ QList< QPair<int,int> > CameraBinSession::supportedFrameRates(const QSize &frame
+ gst_structure_remove_all_fields(structure);
+ gst_structure_set_value(structure, "framerate", &rate);
+ }
++#if GST_CHECK_VERSION(1,0,0)
++ caps = gst_caps_simplify(caps);
++#else
+ gst_caps_do_simplify(caps);
+-
++#endif
+
+ for (uint i=0; i<gst_caps_get_size(caps); i++) {
+ GstStructure *structure = gst_caps_get_structure(caps, i);
+@@ -1154,7 +1056,7 @@ QList< QPair<int,int> > CameraBinSession::supportedFrameRates(const QSize &frame
+ qSort(res.begin(), res.end(), rateLessThan);
+
+ #if CAMERABIN_DEBUG
+- qDebug() << "Supported rates:" << gst_caps_to_string(caps);
++ qDebug() << "Supported rates:" << caps;
+ qDebug() << res;
+ #endif
+
+@@ -1213,31 +1115,24 @@ QList<QSize> CameraBinSession::supportedResolutions(QPair<int,int> rate,
+ SUPPORTED_IMAGE_CAPTURE_CAPS_PROPERTY : SUPPORTED_VIDEO_CAPTURE_CAPS_PROPERTY,
+ &supportedCaps, NULL);
+
+- if (!supportedCaps)
+- return res;
+-
+ #if CAMERABIN_DEBUG
+- qDebug() << "Source caps:" << gst_caps_to_string(supportedCaps);
++ qDebug() << "Source caps:" << supportedCaps;
+ #endif
+
++ if (!supportedCaps)
++ return res;
++
+ GstCaps *caps = 0;
+ bool isContinuous = false;
+
+ if (rate.first <= 0 || rate.second <= 0) {
+ caps = gst_caps_copy(supportedCaps);
+ } else {
+- GstCaps *filter = gst_caps_new_full(
+- gst_structure_new(
+- "video/x-raw-rgb",
+- "framerate" , GST_TYPE_FRACTION , rate.first, rate.second, NULL),
+- gst_structure_new(
+- "video/x-raw-yuv",
+- "framerate" , GST_TYPE_FRACTION , rate.first, rate.second, NULL),
+- gst_structure_new(
+- "image/jpeg",
+- "framerate" , GST_TYPE_FRACTION , rate.first, rate.second, NULL),
+- NULL);
+-
++ GstCaps *filter = QGstUtils::videoFilterCaps();
++ gst_caps_set_simple(
++ filter,
++ "framerate" , GST_TYPE_FRACTION , rate.first, rate.second,
++ NULL);
+ caps = gst_caps_intersect(supportedCaps, filter);
+ gst_caps_unref(filter);
+ }
+@@ -1247,7 +1142,7 @@ QList<QSize> CameraBinSession::supportedResolutions(QPair<int,int> rate,
+ caps = gst_caps_make_writable(caps);
+ for (uint i=0; i<gst_caps_get_size(caps); i++) {
+ GstStructure *structure = gst_caps_get_structure(caps, i);
+- gst_structure_set_name(structure, "video/x-raw-yuv");
++ gst_structure_set_name(structure, "video/x-raw");
+ const GValue *oldW = gst_structure_get_value(structure, "width");
+ const GValue *oldH = gst_structure_get_value(structure, "height");
+ GValue w;
+@@ -1262,7 +1157,13 @@ QList<QSize> CameraBinSession::supportedResolutions(QPair<int,int> rate,
+ gst_structure_set_value(structure, "width", &w);
+ gst_structure_set_value(structure, "height", &h);
+ }
++
++#if GST_CHECK_VERSION(1,0,0)
++ caps = gst_caps_simplify(caps);
++#else
+ gst_caps_do_simplify(caps);
++#endif
++
+
+ for (uint i=0; i<gst_caps_get_size(caps); i++) {
+ GstStructure *structure = gst_caps_get_structure(caps, i);
+diff --git a/src/plugins/gstreamer/common.pri b/src/plugins/gstreamer/common.pri
+index 8b421b8..eb6a299 100644
+--- a/src/plugins/gstreamer/common.pri
++++ b/src/plugins/gstreamer/common.pri
+@@ -12,14 +12,18 @@ LIBS += -lqgsttools_p
+ CONFIG += link_pkgconfig
+
+ PKGCONFIG += \
+- gstreamer-0.10 \
+- gstreamer-base-0.10 \
+- gstreamer-interfaces-0.10 \
+- gstreamer-audio-0.10 \
+- gstreamer-video-0.10 \
+- gstreamer-pbutils-0.10
++ gstreamer-$$GST_VERSION \
++ gstreamer-base-$$GST_VERSION \
++ gstreamer-audio-$$GST_VERSION \
++ gstreamer-video-$$GST_VERSION \
++ gstreamer-pbutils-$$GST_VERSION
++
++maemo*:PKGCONFIG +=gstreamer-plugins-bad-$$GST_VERSION
++
++mir: {
++ DEFINES += HAVE_MIR
++}
+
+-maemo*:PKGCONFIG +=gstreamer-plugins-bad-0.10
+
+ config_resourcepolicy {
+ DEFINES += HAVE_RESOURCE_POLICY
+@@ -27,8 +31,8 @@ config_resourcepolicy {
+ }
+
+ config_gstreamer_appsrc {
+- PKGCONFIG += gstreamer-app-0.10
++ PKGCONFIG += gstreamer-app-$$GST_VERSION
+ DEFINES += HAVE_GST_APPSRC
+- LIBS += -lgstapp-0.10
++ LIBS += -lgstapp-$$GST_VERSION
+ }
+
+diff --git a/src/plugins/gstreamer/gstreamer.pro b/src/plugins/gstreamer/gstreamer.pro
+index 7649010..0ff3510 100644
+--- a/src/plugins/gstreamer/gstreamer.pro
++++ b/src/plugins/gstreamer/gstreamer.pro
+@@ -2,8 +2,8 @@ TEMPLATE = subdirs
+
+ SUBDIRS += \
+ audiodecoder \
+- mediacapture \
+- mediaplayer
++ mediaplayer \
++ mediacapture
+
+ config_gstreamer_encodingprofiles {
+ SUBDIRS += camerabin
+diff --git a/src/plugins/gstreamer/mediacapture/mediacapturecamera.json b/src/plugins/gstreamer/mediacapture/mediacapturecamera.json
+index af9f357..f5fba17 100644
+--- a/src/plugins/gstreamer/mediacapture/mediacapturecamera.json
++++ b/src/plugins/gstreamer/mediacapture/mediacapturecamera.json
+@@ -1,4 +1,4 @@
+ {
+- "Keys": ["gstreamermediacapture"]
++ "Keys": ["gstreamermediacapture"],
+ "Services": ["org.qt-project.qt.audiosource", "org.qt-project.qt.camera"]
+ }
+diff --git a/src/plugins/gstreamer/mediacapture/qgstreameraudioencode.cpp b/src/plugins/gstreamer/mediacapture/qgstreameraudioencode.cpp
+index d05df49..8881445 100644
+--- a/src/plugins/gstreamer/mediacapture/qgstreameraudioencode.cpp
++++ b/src/plugins/gstreamer/mediacapture/qgstreameraudioencode.cpp
+@@ -34,6 +34,7 @@
+ #include "qgstreameraudioencode.h"
+ #include "qgstreamercapturesession.h"
+ #include "qgstreamermediacontainercontrol.h"
++#include <private/qgstutils_p.h>
+
+ #include <QtCore/qdebug.h>
+
+@@ -175,7 +176,7 @@ GstElement *QGstreamerAudioEncode::createEncoder()
+
+ if (m_audioSettings.sampleRate() > 0 || m_audioSettings.channelCount() > 0) {
+ GstCaps *caps = gst_caps_new_empty();
+- GstStructure *structure = gst_structure_new("audio/x-raw-int", NULL);
++ GstStructure *structure = qt_gst_structure_new_empty(QT_GSTREAMER_RAW_AUDIO_MIME);
+
+ if (m_audioSettings.sampleRate() > 0)
+ gst_structure_set(structure, "rate", G_TYPE_INT, m_audioSettings.sampleRate(), NULL );
+diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.cpp b/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.cpp
+index 97a165d..1ab98cd 100644
+--- a/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.cpp
++++ b/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.cpp
+@@ -62,27 +62,25 @@
+
+ QT_BEGIN_NAMESPACE
+
+-QGstreamerCaptureService::QGstreamerCaptureService(const QString &service, QObject *parent):
+- QMediaService(parent)
+-{
+- m_captureSession = 0;
+- m_cameraControl = 0;
+- m_metaDataControl = 0;
+-
++QGstreamerCaptureService::QGstreamerCaptureService(const QString &service, QObject *parent)
++ : QMediaService(parent)
++ , m_captureSession(0)
++ , m_cameraControl(0)
+ #if defined(USE_GSTREAMER_CAMERA)
+- m_videoInput = 0;
++ , m_videoInput(0)
+ #endif
+- m_audioInputSelector = 0;
+- m_videoInputDevice = 0;
+-
+- m_videoOutput = 0;
+- m_videoRenderer = 0;
+- m_videoWindow = 0;
++ , m_metaDataControl(0)
++ , m_audioInputSelector(0)
++ , m_videoInputDevice(0)
++ , m_videoOutput(0)
++ , m_videoRenderer(0)
++ , m_videoWindow(0)
+ #if defined(HAVE_WIDGETS)
+- m_videoWidgetControl = 0;
++ , m_videoWidgetControl(0)
+ #endif
+- m_imageCaptureControl = 0;
+-
++ , m_imageCaptureControl(0)
++ , m_audioProbeControl(0)
++{
+ if (service == Q_MEDIASERVICE_AUDIOSOURCE) {
+ m_captureSession = new QGstreamerCaptureSession(QGstreamerCaptureSession::Audio, this);
+ }
+@@ -163,12 +161,12 @@ QMediaControl *QGstreamerCaptureService::requestControl(const char *name)
+ return m_imageCaptureControl;
+
+ if (qstrcmp(name,QMediaAudioProbeControl_iid) == 0) {
+- if (m_captureSession) {
+- QGstreamerAudioProbeControl *probe = new QGstreamerAudioProbeControl(this);
+- m_captureSession->addProbe(probe);
+- return probe;
++ if (!m_audioProbeControl) {
++ m_audioProbeControl = new QGstreamerAudioProbeControl(this);
++ m_captureSession->addProbe(m_audioProbeControl);
+ }
+- return 0;
++ m_audioProbeControl->ref.ref();
++ return m_audioProbeControl;
+ }
+
+ if (!m_videoOutput) {
+@@ -194,17 +192,15 @@ QMediaControl *QGstreamerCaptureService::requestControl(const char *name)
+
+ void QGstreamerCaptureService::releaseControl(QMediaControl *control)
+ {
+- if (control && control == m_videoOutput) {
++ if (!control) {
++ return;
++ } else if (control == m_videoOutput) {
+ m_videoOutput = 0;
+ m_captureSession->setVideoPreview(0);
+- }
+-
+- QGstreamerAudioProbeControl* audioProbe = qobject_cast<QGstreamerAudioProbeControl*>(control);
+- if (audioProbe) {
+- if (m_captureSession)
+- m_captureSession->removeProbe(audioProbe);
+- delete audioProbe;
+- return;
++ } else if (control == m_audioProbeControl && !m_audioProbeControl->ref.deref()) {
++ m_captureSession->removeProbe(m_audioProbeControl);
++ delete m_audioProbeControl;
++ m_audioProbeControl = 0;
+ }
+ }
+
+diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.h b/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.h
+index 7ff8ce2..e0cf4ee 100644
+--- a/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.h
++++ b/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.h
+@@ -43,6 +43,7 @@ QT_BEGIN_NAMESPACE
+ class QAudioInputSelectorControl;
+ class QVideoDeviceSelectorControl;
+
++class QGstreamerAudioProbeControl;
+ class QGstreamerCaptureSession;
+ class QGstreamerCameraControl;
+ class QGstreamerMessage;
+@@ -86,6 +87,8 @@ private:
+ QMediaControl *m_videoWidgetControl;
+ #endif
+ QGstreamerImageCaptureControl *m_imageCaptureControl;
++
++ QGstreamerAudioProbeControl *m_audioProbeControl;
+ };
+
+ QT_END_NAMESPACE
+diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercaptureserviceplugin.cpp b/src/plugins/gstreamer/mediacapture/qgstreamercaptureserviceplugin.cpp
+index 0ac34ee..85ed687 100644
+--- a/src/plugins/gstreamer/mediacapture/qgstreamercaptureserviceplugin.cpp
++++ b/src/plugins/gstreamer/mediacapture/qgstreamercaptureserviceplugin.cpp
+@@ -110,90 +110,16 @@ QMultimedia::SupportEstimate QGstreamerCaptureServicePlugin::hasSupport(const QS
+ return QGstUtils::hasSupport(mimeType, codecs, m_supportedMimeTypeSet);
+ }
+
++
++static bool isEncoderOrMuxer(GstElementFactory *factory)
++{
++ return gst_element_factory_list_is_type(factory, GST_ELEMENT_FACTORY_TYPE_MUXER)
++ || gst_element_factory_list_is_type(factory, GST_ELEMENT_FACTORY_TYPE_ENCODER);
++}
++
+ void QGstreamerCaptureServicePlugin::updateSupportedMimeTypes() const
+ {
+- //enumerate supported mime types
+- gst_init(NULL, NULL);
+-
+- GList *plugins, *orig_plugins;
+- orig_plugins = plugins = gst_default_registry_get_plugin_list ();
+-
+- while (plugins) {
+- GList *features, *orig_features;
+-
+- GstPlugin *plugin = (GstPlugin *) (plugins->data);
+- plugins = g_list_next (plugins);
+-
+- if (plugin->flags & (1<<1)) //GST_PLUGIN_FLAG_BLACKLISTED
+- continue;
+-
+- orig_features = features = gst_registry_get_feature_list_by_plugin(gst_registry_get_default (),
+- plugin->desc.name);
+- while (features) {
+- if (!G_UNLIKELY(features->data == NULL)) {
+- GstPluginFeature *feature = GST_PLUGIN_FEATURE(features->data);
+- if (GST_IS_ELEMENT_FACTORY (feature)) {
+- GstElementFactory *factory = GST_ELEMENT_FACTORY(gst_plugin_feature_load(feature));
+- if (factory
+- && factory->numpadtemplates > 0
+- && (qstrcmp(factory->details.klass, "Codec/Decoder/Audio") == 0
+- || qstrcmp(factory->details.klass, "Codec/Decoder/Video") == 0
+- || qstrcmp(factory->details.klass, "Codec/Demux") == 0 )) {
+- const GList *pads = factory->staticpadtemplates;
+- while (pads) {
+- GstStaticPadTemplate *padtemplate = (GstStaticPadTemplate*)(pads->data);
+- pads = g_list_next (pads);
+- if (padtemplate->direction != GST_PAD_SINK)
+- continue;
+- if (padtemplate->static_caps.string) {
+- GstCaps *caps = gst_static_caps_get(&padtemplate->static_caps);
+- if (!gst_caps_is_any (caps) && ! gst_caps_is_empty (caps)) {
+- for (guint i = 0; i < gst_caps_get_size(caps); i++) {
+- GstStructure *structure = gst_caps_get_structure(caps, i);
+- QString nameLowcase = QString(gst_structure_get_name (structure)).toLower();
+-
+- m_supportedMimeTypeSet.insert(nameLowcase);
+- if (nameLowcase.contains("mpeg")) {
+- //Because mpeg version number is only included in the detail
+- //description, it is necessary to manually extract this information
+- //in order to match the mime type of mpeg4.
+- const GValue *value = gst_structure_get_value(structure, "mpegversion");
+- if (value) {
+- gchar *str = gst_value_serialize (value);
+- QString versions(str);
+- QStringList elements = versions.split(QRegExp("\\D+"), QString::SkipEmptyParts);
+- foreach (const QString &e, elements)
+- m_supportedMimeTypeSet.insert(nameLowcase + e);
+- g_free (str);
+- }
+- }
+- }
+- }
+- gst_caps_unref(caps);
+- }
+- }
+- gst_object_unref (factory);
+- }
+- } else if (GST_IS_TYPE_FIND_FACTORY(feature)) {
+- QString name(gst_plugin_feature_get_name(feature));
+- if (name.contains('/')) //filter out any string without '/' which is obviously not a mime type
+- m_supportedMimeTypeSet.insert(name.toLower());
+- }
+- }
+- features = g_list_next (features);
+- }
+- gst_plugin_feature_list_free (orig_features);
+- }
+- gst_plugin_list_free (orig_plugins);
+-
+-#if defined QT_SUPPORTEDMIMETYPES_DEBUG
+- QStringList list = m_supportedMimeTypeSet.toList();
+- list.sort();
+- if (qgetenv("QT_DEBUG_PLUGINS").toInt() > 0) {
+- foreach (const QString &type, list)
+- qDebug() << type;
+- }
+-#endif
++ m_supportedMimeTypeSet = QGstUtils::supportedMimeTypes(isEncoderOrMuxer);
+ }
+
+ QStringList QGstreamerCaptureServicePlugin::supportedMimeTypes() const
+diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp b/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp
+index a2bd80d..af5b339 100644
+--- a/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp
++++ b/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp
+@@ -45,6 +45,7 @@
+
+ #include <gst/gsttagsetter.h>
+ #include <gst/gstversion.h>
++#include <gst/video/video.h>
+
+ #include <QtCore/qdebug.h>
+ #include <QtCore/qurl.h>
+@@ -52,7 +53,6 @@
+ #include <QCoreApplication>
+ #include <QtCore/qmetaobject.h>
+ #include <QtCore/qfile.h>
+-
+ #include <QtGui/qimage.h>
+
+ QT_BEGIN_NAMESPACE
+@@ -64,7 +64,7 @@ QGstreamerCaptureSession::QGstreamerCaptureSession(QGstreamerCaptureSession::Cap
+ m_waitingForEos(false),
+ m_pipelineMode(EmptyPipeline),
+ m_captureMode(captureMode),
+- m_audioBufferProbeId(-1),
++ m_audioProbe(0),
+ m_audioInputFactory(0),
+ m_audioPreviewFactory(0),
+ m_videoInputFactory(0),
+@@ -169,7 +169,7 @@ GstElement *QGstreamerCaptureSession::buildEncodeBin()
+
+ if (m_captureMode & Video) {
+ GstElement *videoQueue = gst_element_factory_make("queue", "video-encode-queue");
+- GstElement *colorspace = gst_element_factory_make("ffmpegcolorspace", "ffmpegcolorspace-encoder");
++ GstElement *colorspace = gst_element_factory_make(QT_GSTREAMER_COLORCONVERSION_ELEMENT_NAME, "videoconvert-encoder");
+ GstElement *videoscale = gst_element_factory_make("videoscale","videoscale-encoder");
+ gst_bin_add_many(GST_BIN(encodeBin), videoQueue, colorspace, videoscale, NULL);
+
+@@ -280,7 +280,7 @@ GstElement *QGstreamerCaptureSession::buildVideoPreview()
+
+ if (m_viewfinderInterface) {
+ GstElement *bin = gst_bin_new("video-preview-bin");
+- GstElement *colorspace = gst_element_factory_make("ffmpegcolorspace", "ffmpegcolorspace-preview");
++ GstElement *colorspace = gst_element_factory_make(QT_GSTREAMER_COLORCONVERSION_ELEMENT_NAME, "videoconvert-preview");
+ GstElement *capsFilter = gst_element_factory_make("capsfilter", "capsfilter-video-preview");
+ GstElement *preview = m_viewfinderInterface->videoSink();
+
+@@ -299,36 +299,25 @@ GstElement *QGstreamerCaptureSession::buildVideoPreview()
+ resolution = m_imageEncodeControl->imageSettings().resolution();
+ }
+
+- if (!resolution.isEmpty() || frameRate > 0.001) {
+- GstCaps *caps = gst_caps_new_empty();
+- QStringList structureTypes;
+- structureTypes << "video/x-raw-yuv" << "video/x-raw-rgb";
+-
+- foreach(const QString &structureType, structureTypes) {
+- GstStructure *structure = gst_structure_new(structureType.toLatin1().constData(), NULL);
+-
+- if (!resolution.isEmpty()) {
+- gst_structure_set(structure, "width", G_TYPE_INT, resolution.width(), NULL);
+- gst_structure_set(structure, "height", G_TYPE_INT, resolution.height(), NULL);
+- }
+-
+- if (frameRate > 0.001) {
+- QPair<int,int> rate = m_videoEncodeControl->rateAsRational();
++ GstCaps *caps = QGstUtils::videoFilterCaps();
+
+- //qDebug() << "frame rate:" << num << denum;
++ if (!resolution.isEmpty()) {
++ gst_caps_set_simple(caps, "width", G_TYPE_INT, resolution.width(), NULL);
++ gst_caps_set_simple(caps, "height", G_TYPE_INT, resolution.height(), NULL);
++ }
++ if (frameRate > 0.001) {
++ QPair<int,int> rate = m_videoEncodeControl->rateAsRational();
+
+- gst_structure_set(structure, "framerate", GST_TYPE_FRACTION, rate.first, rate.second, NULL);
+- }
++ //qDebug() << "frame rate:" << num << denum;
+
+- gst_caps_append_structure(caps,structure);
+- }
++ gst_caps_set_simple(caps, "framerate", GST_TYPE_FRACTION, rate.first, rate.second, NULL);
++ }
+
+- //qDebug() << "set video preview caps filter:" << gst_caps_to_string(caps);
++ //qDebug() << "set video preview caps filter:" << gst_caps_to_string(caps);
+
+- g_object_set(G_OBJECT(capsFilter), "caps", caps, NULL);
++ g_object_set(G_OBJECT(capsFilter), "caps", caps, NULL);
+
+- gst_caps_unref(caps);
+- }
++ gst_caps_unref(caps);
+
+ // add ghostpads
+ GstPad *pad = gst_element_get_static_pad(colorspace, "sink");
+@@ -342,7 +331,7 @@ GstElement *QGstreamerCaptureSession::buildVideoPreview()
+ previewElement = gst_element_factory_make("fakesink", "video-preview");
+ #else
+ GstElement *bin = gst_bin_new("video-preview-bin");
+- GstElement *colorspace = gst_element_factory_make("ffmpegcolorspace", "ffmpegcolorspace-preview");
++ GstElement *colorspace = gst_element_factory_make(QT_GSTREAMER_COLORCONVERSION_ELEMENT_NAME, "videoconvert-preview");
+ GstElement *preview = gst_element_factory_make("ximagesink", "video-preview");
+ gst_bin_add_many(GST_BIN(bin), colorspace, preview, NULL);
+ gst_element_link(colorspace,preview);
+@@ -360,101 +349,49 @@ GstElement *QGstreamerCaptureSession::buildVideoPreview()
+ return previewElement;
+ }
+
+-
+-static gboolean passImageFilter(GstElement *element,
+- GstBuffer *buffer,
+- void *appdata)
++void QGstreamerCaptureSession::probeCaps(GstCaps *caps)
+ {
+- Q_UNUSED(element);
+- Q_UNUSED(buffer);
+-
+- QGstreamerCaptureSession *session = (QGstreamerCaptureSession *)appdata;
+- if (session->m_passImage || session->m_passPrerollImage) {
+- session->m_passImage = false;
+-
+- if (session->m_passPrerollImage) {
+- session->m_passPrerollImage = false;
+- return TRUE;
+- }
+- session->m_passPrerollImage = false;
+-
+- QImage img;
+-
+- GstCaps *caps = gst_buffer_get_caps(buffer);
+- if (caps) {
+- GstStructure *structure = gst_caps_get_structure (caps, 0);
+- gint width = 0;
+- gint height = 0;
+-
+- if (structure &&
+- gst_structure_get_int(structure, "width", &width) &&
+- gst_structure_get_int(structure, "height", &height) &&
+- width > 0 && height > 0) {
+- if (qstrcmp(gst_structure_get_name(structure), "video/x-raw-yuv") == 0) {
+- guint32 fourcc = 0;
+- gst_structure_get_fourcc(structure, "format", &fourcc);
+-
+- if (fourcc == GST_MAKE_FOURCC('I','4','2','0')) {
+- img = QImage(width/2, height/2, QImage::Format_RGB32);
+-
+- const uchar *data = (const uchar *)buffer->data;
++#if GST_CHECK_VERSION(1,0,0)
++ gst_video_info_from_caps(&m_previewInfo, caps);
++#else
++ Q_UNUSED(caps);
++#endif
++}
+
+- for (int y=0; y<height; y+=2) {
+- const uchar *yLine = data + y*width;
+- const uchar *uLine = data + width*height + y*width/4;
+- const uchar *vLine = data + width*height*5/4 + y*width/4;
++bool QGstreamerCaptureSession::probeBuffer(GstBuffer *buffer)
++{
++ if (m_passPrerollImage) {
++ m_passImage = false;
++ m_passPrerollImage = false;
+
+- for (int x=0; x<width; x+=2) {
+- const qreal Y = 1.164*(yLine[x]-16);
+- const int U = uLine[x/2]-128;
+- const int V = vLine[x/2]-128;
++ return true;
++ } else if (!m_passImage) {
++ return false;
++ }
+
+- int b = qBound(0, int(Y + 2.018*U), 255);
+- int g = qBound(0, int(Y - 0.813*V - 0.391*U), 255);
+- int r = qBound(0, int(Y + 1.596*V), 255);
++ m_passImage = false;
+
+- img.setPixel(x/2,y/2,qRgb(r,g,b));
+- }
+- }
+- }
++#if GST_CHECK_VERSION(1,0,0)
++ QImage img = QGstUtils::bufferToImage(buffer, m_previewInfo);
++#else
++ QImage img = QGstUtils::bufferToImage(buffer);
++#endif
+
+- } else if (qstrcmp(gst_structure_get_name(structure), "video/x-raw-rgb") == 0) {
+- QImage::Format format = QImage::Format_Invalid;
+- int bpp = 0;
+- gst_structure_get_int(structure, "bpp", &bpp);
+-
+- if (bpp == 24)
+- format = QImage::Format_RGB888;
+- else if (bpp == 32)
+- format = QImage::Format_RGB32;
+-
+- if (format != QImage::Format_Invalid) {
+- img = QImage((const uchar *)buffer->data,
+- width,
+- height,
+- format);
+- img.bits(); //detach
+- }
+- }
+- }
+- gst_caps_unref(caps);
+- }
++ if (img.isNull())
++ return true;
+
+- static QMetaMethod exposedSignal = QMetaMethod::fromSignal(&QGstreamerCaptureSession::imageExposed);
+- exposedSignal.invoke(session,
+- Qt::QueuedConnection,
+- Q_ARG(int,session->m_imageRequestId));
++ static QMetaMethod exposedSignal = QMetaMethod::fromSignal(&QGstreamerCaptureSession::imageExposed);
++ exposedSignal.invoke(this,
++ Qt::QueuedConnection,
++ Q_ARG(int,m_imageRequestId));
+
+- static QMetaMethod capturedSignal = QMetaMethod::fromSignal(&QGstreamerCaptureSession::imageCaptured);
+- capturedSignal.invoke(session,
+- Qt::QueuedConnection,
+- Q_ARG(int,session->m_imageRequestId),
+- Q_ARG(QImage,img));
++ static QMetaMethod capturedSignal = QMetaMethod::fromSignal(&QGstreamerCaptureSession::imageCaptured);
++ capturedSignal.invoke(this,
++ Qt::QueuedConnection,
++ Q_ARG(int,m_imageRequestId),
++ Q_ARG(QImage,img));
+
+- return TRUE;
+- } else {
+- return FALSE;
+- }
++ return true;
+ }
+
+ static gboolean saveImageFilter(GstElement *element,
+@@ -471,7 +408,15 @@ static gboolean saveImageFilter(GstElement *element,
+ if (!fileName.isEmpty()) {
+ QFile f(fileName);
+ if (f.open(QFile::WriteOnly)) {
+- f.write((const char *)buffer->data, buffer->size);
++#if GST_CHECK_VERSION(1,0,0)
++ GstMapInfo info;
++ if (gst_buffer_map(buffer, &info, GST_MAP_READ)) {
++ f.write(reinterpret_cast<const char *>(info.data), info.size);
++ gst_buffer_unmap(buffer, &info);
++ }
++#else
++ f.write(reinterpret_cast<const char *>(buffer->data), buffer->size);
++#endif
+ f.close();
+
+ static QMetaMethod savedSignal = QMetaMethod::fromSignal(&QGstreamerCaptureSession::imageSaved);
+@@ -489,18 +434,19 @@ GstElement *QGstreamerCaptureSession::buildImageCapture()
+ {
+ GstElement *bin = gst_bin_new("image-capture-bin");
+ GstElement *queue = gst_element_factory_make("queue", "queue-image-capture");
+- GstElement *colorspace = gst_element_factory_make("ffmpegcolorspace", "ffmpegcolorspace-image-capture");
++ GstElement *colorspace = gst_element_factory_make(QT_GSTREAMER_COLORCONVERSION_ELEMENT_NAME, "videoconvert-image-capture");
+ GstElement *encoder = gst_element_factory_make("jpegenc", "image-encoder");
+ GstElement *sink = gst_element_factory_make("fakesink","sink-image-capture");
+
+ GstPad *pad = gst_element_get_static_pad(queue, "src");
+ Q_ASSERT(pad);
+- gst_pad_add_buffer_probe(pad, G_CALLBACK(passImageFilter), this);
++
++ addProbeToPad(pad, false);
++
+ gst_object_unref(GST_OBJECT(pad));
+
+ g_object_set(G_OBJECT(sink), "signal-handoffs", TRUE, NULL);
+- g_signal_connect(G_OBJECT(sink), "handoff",
+- G_CALLBACK(saveImageFilter), this);
++ g_signal_connect(G_OBJECT(sink), "handoff", G_CALLBACK(saveImageFilter), this);
+
+ gst_bin_add_many(GST_BIN(bin), queue, colorspace, encoder, sink, NULL);
+ gst_element_link_many(queue, colorspace, encoder, sink, NULL);
+@@ -715,6 +661,8 @@ void QGstreamerCaptureSession::dumpGraph(const QString &fileName)
+ _gst_debug_bin_to_dot_file(GST_BIN(m_pipeline),
+ GstDebugGraphDetails(/*GST_DEBUG_GRAPH_SHOW_ALL |*/ GST_DEBUG_GRAPH_SHOW_MEDIA_TYPE | GST_DEBUG_GRAPH_SHOW_NON_DEFAULT_PARAMS | GST_DEBUG_GRAPH_SHOW_STATES),
+ fileName.toLatin1());
++#else
++ Q_UNUSED(fileName);
+ #endif
+ }
+
+@@ -877,10 +825,8 @@ void QGstreamerCaptureSession::setState(QGstreamerCaptureSession::State newState
+
+ qint64 QGstreamerCaptureSession::duration() const
+ {
+- GstFormat format = GST_FORMAT_TIME;
+- gint64 duration = 0;
+-
+- if ( m_encodeBin && gst_element_query_position(m_encodeBin, &format, &duration))
++ gint64 duration = 0;
++ if (m_encodeBin && qt_gst_element_query_position(m_encodeBin, GST_FORMAT_TIME, &duration))
+ return duration / 1000000;
+ else
+ return 0;
+@@ -896,50 +842,8 @@ void QGstreamerCaptureSession::setMetaData(const QMap<QByteArray, QVariant> &dat
+ //qDebug() << "QGstreamerCaptureSession::setMetaData" << data;
+ m_metaData = data;
+
+- if (m_encodeBin) {
+- GstIterator *elements = gst_bin_iterate_all_by_interface(GST_BIN(m_encodeBin), GST_TYPE_TAG_SETTER);
+- GstElement *element = 0;
+- while (gst_iterator_next(elements, (void**)&element) == GST_ITERATOR_OK) {
+- //qDebug() << "found element with tag setter interface:" << gst_element_get_name(element);
+- QMapIterator<QByteArray, QVariant> it(data);
+- while (it.hasNext()) {
+- it.next();
+- const QString tagName = it.key();
+- const QVariant tagValue = it.value();
+-
+-
+- switch(tagValue.type()) {
+- case QVariant::String:
+- gst_tag_setter_add_tags(GST_TAG_SETTER(element),
+- GST_TAG_MERGE_REPLACE_ALL,
+- tagName.toUtf8().constData(),
+- tagValue.toString().toUtf8().constData(),
+- NULL);
+- break;
+- case QVariant::Int:
+- case QVariant::LongLong:
+- gst_tag_setter_add_tags(GST_TAG_SETTER(element),
+- GST_TAG_MERGE_REPLACE_ALL,
+- tagName.toUtf8().constData(),
+- tagValue.toInt(),
+- NULL);
+- break;
+- case QVariant::Double:
+- gst_tag_setter_add_tags(GST_TAG_SETTER(element),
+- GST_TAG_MERGE_REPLACE_ALL,
+- tagName.toUtf8().constData(),
+- tagValue.toDouble(),
+- NULL);
+- break;
+- default:
+- break;
+- }
+-
+- }
+-
+- }
+- gst_iterator_free(elements);
+- }
++ if (m_encodeBin)
++ QGstUtils::setMetaData(GST_BIN(m_encodeBin), data);
+ }
+
+ bool QGstreamerCaptureSession::processBusMessage(const QGstreamerMessage &message)
+@@ -1058,34 +962,16 @@ void QGstreamerCaptureSession::setVolume(qreal volume)
+
+ void QGstreamerCaptureSession::addProbe(QGstreamerAudioProbeControl* probe)
+ {
+- QMutexLocker locker(&m_audioProbeMutex);
+-
+- if (m_audioProbes.contains(probe))
+- return;
+-
+- m_audioProbes.append(probe);
++ Q_ASSERT(!m_audioProbe);
++ m_audioProbe = probe;
++ addAudioBufferProbe();
+ }
+
+ void QGstreamerCaptureSession::removeProbe(QGstreamerAudioProbeControl* probe)
+ {
+- QMutexLocker locker(&m_audioProbeMutex);
+- m_audioProbes.removeOne(probe);
+-}
+-
+-gboolean QGstreamerCaptureSession::padAudioBufferProbe(GstPad *pad, GstBuffer *buffer, gpointer user_data)
+-{
+- Q_UNUSED(pad);
+-
+- QGstreamerCaptureSession *session = reinterpret_cast<QGstreamerCaptureSession*>(user_data);
+- QMutexLocker locker(&session->m_audioProbeMutex);
+-
+- if (session->m_audioProbes.isEmpty())
+- return TRUE;
+-
+- foreach (QGstreamerAudioProbeControl* probe, session->m_audioProbes)
+- probe->bufferProbed(buffer);
+-
+- return TRUE;
++ Q_ASSERT(m_audioProbe == probe);
++ removeAudioBufferProbe();
++ m_audioProbe = 0;
+ }
+
+ GstPad *QGstreamerCaptureSession::getAudioProbePad()
+@@ -1114,26 +1000,25 @@ GstPad *QGstreamerCaptureSession::getAudioProbePad()
+
+ void QGstreamerCaptureSession::removeAudioBufferProbe()
+ {
+- if (m_audioBufferProbeId == -1)
++ if (!m_audioProbe)
+ return;
+
+ GstPad *pad = getAudioProbePad();
+ if (pad) {
+- gst_pad_remove_buffer_probe(pad, m_audioBufferProbeId);
+- gst_object_unref(G_OBJECT(pad));
++ m_audioProbe->removeProbeFromPad(pad);
++ gst_object_unref(GST_OBJECT(pad));
+ }
+-
+- m_audioBufferProbeId = -1;
+ }
+
+ void QGstreamerCaptureSession::addAudioBufferProbe()
+ {
+- Q_ASSERT(m_audioBufferProbeId == -1);
++ if (!m_audioProbe)
++ return;
+
+ GstPad *pad = getAudioProbePad();
+ if (pad) {
+- m_audioBufferProbeId = gst_pad_add_buffer_probe(pad, G_CALLBACK(padAudioBufferProbe), this);
+- gst_object_unref(G_OBJECT(pad));
++ m_audioProbe->addProbeToPad(pad);
++ gst_object_unref(GST_OBJECT(pad));
+ }
+ }
+
+diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.h b/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.h
+index a759f22..ad26327 100644
+--- a/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.h
++++ b/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.h
+@@ -41,8 +41,10 @@
+ #include <QtCore/qurl.h>
+
+ #include <gst/gst.h>
++#include <gst/video/video.h>
+
+ #include <private/qgstreamerbushelper_p.h>
++#include <private/qgstreamerbufferprobe_p.h>
+
+ QT_BEGIN_NAMESPACE
+
+@@ -70,7 +72,10 @@ public:
+ virtual QList<QSize> supportedResolutions(qreal frameRate = -1) const = 0;
+ };
+
+-class QGstreamerCaptureSession : public QObject, public QGstreamerBusMessageFilter
++class QGstreamerCaptureSession
++ : public QObject
++ , public QGstreamerBusMessageFilter
++ , private QGstreamerBufferProbe
+ {
+ Q_OBJECT
+ Q_PROPERTY(qint64 duration READ duration NOTIFY durationChanged)
+@@ -131,7 +136,6 @@ public:
+
+ void addProbe(QGstreamerAudioProbeControl* probe);
+ void removeProbe(QGstreamerAudioProbeControl* probe);
+- static gboolean padAudioBufferProbe(GstPad *pad, GstBuffer *buffer, gpointer user_data);
+
+ signals:
+ void stateChanged(QGstreamerCaptureSession::State state);
+@@ -156,6 +160,9 @@ public slots:
+ void setVolume(qreal volume);
+
+ private:
++ void probeCaps(GstCaps *caps);
++ bool probeBuffer(GstBuffer *buffer);
++
+ enum PipelineMode { EmptyPipeline, PreviewPipeline, RecordingPipeline, PreviewAndRecordingPipeline };
+
+ GstElement *buildEncodeBin();
+@@ -180,9 +187,7 @@ private:
+ QGstreamerCaptureSession::CaptureMode m_captureMode;
+ QMap<QByteArray, QVariant> m_metaData;
+
+- QList<QGstreamerAudioProbeControl*> m_audioProbes;
+- QMutex m_audioProbeMutex;
+- int m_audioBufferProbeId;
++ QGstreamerAudioProbeControl *m_audioProbe;
+
+ QGstreamerElementFactory *m_audioInputFactory;
+ QGstreamerElementFactory *m_audioPreviewFactory;
+@@ -217,6 +222,10 @@ private:
+
+ GstElement *m_encodeBin;
+
++#if GST_CHECK_VERSION(1,0,0)
++ GstVideoInfo m_previewInfo;
++#endif
++
+ public:
+ bool m_passImage;
+ bool m_passPrerollImage;
+diff --git a/src/plugins/gstreamer/mediacapture/qgstreamervideoencode.cpp b/src/plugins/gstreamer/mediacapture/qgstreamervideoencode.cpp
+index 2f0d0ee..81b85d7 100644
+--- a/src/plugins/gstreamer/mediacapture/qgstreamervideoencode.cpp
++++ b/src/plugins/gstreamer/mediacapture/qgstreamervideoencode.cpp
+@@ -34,7 +34,7 @@
+ #include "qgstreamervideoencode.h"
+ #include "qgstreamercapturesession.h"
+ #include "qgstreamermediacontainercontrol.h"
+-
++#include <private/qgstutils_p.h>
+ #include <QtCore/qdebug.h>
+
+ #include <math.h>
+@@ -147,7 +147,7 @@ GstElement *QGstreamerVideoEncode::createEncoder()
+ GstElement *capsFilter = gst_element_factory_make("capsfilter", "capsfilter-video");
+ gst_bin_add(encoderBin, capsFilter);
+
+- GstElement *colorspace = gst_element_factory_make("ffmpegcolorspace", NULL);
++ GstElement *colorspace = gst_element_factory_make(QT_GSTREAMER_COLORCONVERSION_ELEMENT_NAME, NULL);
+ gst_bin_add(encoderBin, colorspace);
+ gst_bin_add(encoderBin, encoderElement);
+
+@@ -252,27 +252,22 @@ GstElement *QGstreamerVideoEncode::createEncoder()
+ }
+
+ if (!m_videoSettings.resolution().isEmpty() || m_videoSettings.frameRate() > 0.001) {
+- GstCaps *caps = gst_caps_new_empty();
+- QStringList structureTypes;
+- structureTypes << "video/x-raw-yuv" << "video/x-raw-rgb";
+-
+- foreach(const QString &structureType, structureTypes) {
+- GstStructure *structure = gst_structure_new(structureType.toLatin1().constData(), NULL);
+-
+- if (!m_videoSettings.resolution().isEmpty()) {
+- gst_structure_set(structure, "width", G_TYPE_INT, m_videoSettings.resolution().width(), NULL);
+- gst_structure_set(structure, "height", G_TYPE_INT, m_videoSettings.resolution().height(), NULL);
+- }
+-
+- if (m_videoSettings.frameRate() > 0.001) {
+- QPair<int,int> rate = rateAsRational();
+-
+- //qDebug() << "frame rate:" << num << denum;
+-
+- gst_structure_set(structure, "framerate", GST_TYPE_FRACTION, rate.first, rate.second, NULL);
+- }
++ GstCaps *caps = QGstUtils::videoFilterCaps();
++
++ if (!m_videoSettings.resolution().isEmpty()) {
++ gst_caps_set_simple(
++ caps,
++ "width", G_TYPE_INT, m_videoSettings.resolution().width(),
++ "height", G_TYPE_INT, m_videoSettings.resolution().height(),
++ NULL);
++ }
+
+- gst_caps_append_structure(caps,structure);
++ if (m_videoSettings.frameRate() > 0.001) {
++ QPair<int,int> rate = rateAsRational();
++ gst_caps_set_simple(
++ caps,
++ "framerate", GST_TYPE_FRACTION, rate.first, rate.second,
++ NULL);
+ }
+
+ //qDebug() << "set video caps filter:" << gst_caps_to_string(caps);
+diff --git a/src/plugins/gstreamer/mediaplayer/mediaplayer.pro b/src/plugins/gstreamer/mediaplayer/mediaplayer.pro
+index 2ca9377..b986fc7 100644
+--- a/src/plugins/gstreamer/mediaplayer/mediaplayer.pro
++++ b/src/plugins/gstreamer/mediaplayer/mediaplayer.pro
+@@ -28,4 +28,3 @@ SOURCES += \
+
+ OTHER_FILES += \
+ mediaplayer.json
+-
+diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp b/src/plugins/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp
+index fed756a..c1fb64a 100644
+--- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp
++++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp
+@@ -425,7 +425,6 @@ void QGstreamerPlayerControl::setMedia(const QMediaContent &content, QIODevice *
+ m_session->loadFromUri(request);
+ #endif
+
+-
+ #if defined(HAVE_GST_APPSRC)
+ if (!request.url().isEmpty() || userStreamValid) {
+ #else
+diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayerservice.cpp b/src/plugins/gstreamer/mediaplayer/qgstreamerplayerservice.cpp
+index ce267d7..84805b6 100644
+--- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayerservice.cpp
++++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayerservice.cpp
+@@ -51,7 +51,11 @@
+ #include <private/qgstreamervideorenderer_p.h>
+
+ #if defined(Q_WS_MAEMO_6) && defined(__arm__)
+-#include "qgstreamergltexturerenderer.h"
++#include "private/qgstreamergltexturerenderer.h"
++#endif
++
++#if defined(HAVE_MIR) && defined (__arm__)
++#include "private/qgstreamermirtexturerenderer_p.h"
+ #endif
+
+ #include "qgstreamerstreamscontrol.h"
+@@ -66,6 +70,8 @@ QT_BEGIN_NAMESPACE
+
+ QGstreamerPlayerService::QGstreamerPlayerService(QObject *parent):
+ QMediaService(parent)
++ , m_audioProbeControl(0)
++ , m_videoProbeControl(0)
+ , m_videoOutput(0)
+ , m_videoRenderer(0)
+ , m_videoWindow(0)
+@@ -82,6 +88,8 @@ QGstreamerPlayerService::QGstreamerPlayerService(QObject *parent):
+
+ #if defined(Q_WS_MAEMO_6) && defined(__arm__)
+ m_videoRenderer = new QGstreamerGLTextureRenderer(this);
++#elif defined(HAVE_MIR) && defined (__arm__)
++ m_videoRenderer = new QGstreamerMirTextureRenderer(this, m_session);
+ #else
+ m_videoRenderer = new QGstreamerVideoRenderer(this);
+ #endif
+@@ -115,23 +123,23 @@ QMediaControl *QGstreamerPlayerService::requestControl(const char *name)
+ if (qstrcmp(name, QMediaAvailabilityControl_iid) == 0)
+ return m_availabilityControl;
+
+- if (qstrcmp(name,QMediaVideoProbeControl_iid) == 0) {
+- if (m_session) {
+- QGstreamerVideoProbeControl *probe = new QGstreamerVideoProbeControl(this);
++ if (qstrcmp(name, QMediaVideoProbeControl_iid) == 0) {
++ if (!m_videoProbeControl) {
+ increaseVideoRef();
+- m_session->addProbe(probe);
+- return probe;
++ m_videoProbeControl = new QGstreamerVideoProbeControl(this);
++ m_session->addProbe(m_videoProbeControl);
+ }
+- return 0;
++ m_videoProbeControl->ref.ref();
++ return m_videoProbeControl;
+ }
+
+- if (qstrcmp(name,QMediaAudioProbeControl_iid) == 0) {
+- if (m_session) {
+- QGstreamerAudioProbeControl *probe = new QGstreamerAudioProbeControl(this);
+- m_session->addProbe(probe);
+- return probe;
++ if (qstrcmp(name, QMediaAudioProbeControl_iid) == 0) {
++ if (!m_audioProbeControl) {
++ m_audioProbeControl = new QGstreamerAudioProbeControl(this);
++ m_session->addProbe(m_audioProbeControl);
+ }
+- return 0;
++ m_audioProbeControl->ref.ref();
++ return m_audioProbeControl;
+ }
+
+ if (!m_videoOutput) {
+@@ -156,28 +164,21 @@ QMediaControl *QGstreamerPlayerService::requestControl(const char *name)
+
+ void QGstreamerPlayerService::releaseControl(QMediaControl *control)
+ {
+- if (control == m_videoOutput) {
++ if (!control) {
++ return;
++ } else if (control == m_videoOutput) {
+ m_videoOutput = 0;
+ m_control->setVideoOutput(0);
+ decreaseVideoRef();
+- }
+-
+- QGstreamerVideoProbeControl* videoProbe = qobject_cast<QGstreamerVideoProbeControl*>(control);
+- if (videoProbe) {
+- if (m_session) {
+- m_session->removeProbe(videoProbe);
+- decreaseVideoRef();
+- }
+- delete videoProbe;
+- return;
+- }
+-
+- QGstreamerAudioProbeControl* audioProbe = qobject_cast<QGstreamerAudioProbeControl*>(control);
+- if (audioProbe) {
+- if (m_session)
+- m_session->removeProbe(audioProbe);
+- delete audioProbe;
+- return;
++ } else if (control == m_videoProbeControl && !m_videoProbeControl->ref.deref()) {
++ m_session->removeProbe(m_videoProbeControl);
++ delete m_videoProbeControl;
++ m_videoProbeControl = 0;
++ decreaseVideoRef();
++ } else if (control == m_audioProbeControl && !m_audioProbeControl->ref.deref()) {
++ m_session->removeProbe(m_audioProbeControl);
++ delete m_audioProbeControl;
++ m_audioProbeControl = 0;
+ }
+ }
+
+diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayerservice.h b/src/plugins/gstreamer/mediaplayer/qgstreamerplayerservice.h
+index f3081e9..22be262 100644
+--- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayerservice.h
++++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayerservice.h
+@@ -52,6 +52,8 @@ class QGstreamerStreamsControl;
+ class QGstreamerVideoRenderer;
+ class QGstreamerVideoWidgetControl;
+ class QGStreamerAvailabilityControl;
++class QGstreamerAudioProbeControl;
++class QGstreamerVideoProbeControl;
+
+ class QGstreamerPlayerService : public QMediaService
+ {
+@@ -70,6 +72,9 @@ private:
+ QGstreamerStreamsControl *m_streamsControl;
+ QGStreamerAvailabilityControl *m_availabilityControl;
+
++ QGstreamerAudioProbeControl *m_audioProbeControl;
++ QGstreamerVideoProbeControl *m_videoProbeControl;
++
+ QMediaControl *m_videoOutput;
+ QMediaControl *m_videoRenderer;
+ QMediaControl *m_videoWindow;
+diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayerserviceplugin.cpp b/src/plugins/gstreamer/mediaplayer/qgstreamerplayerserviceplugin.cpp
+index 7d20b6d..f1fd421 100644
+--- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayerserviceplugin.cpp
++++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayerserviceplugin.cpp
+@@ -81,89 +81,15 @@ QMultimedia::SupportEstimate QGstreamerPlayerServicePlugin::hasSupport(const QSt
+ return QGstUtils::hasSupport(mimeType, codecs, m_supportedMimeTypeSet);
+ }
+
+-void QGstreamerPlayerServicePlugin::updateSupportedMimeTypes() const
++static bool isDecoderOrDemuxer(GstElementFactory *factory)
+ {
+- //enumerate supported mime types
+- gst_init(NULL, NULL);
+-
+- GList *plugins, *orig_plugins;
+- orig_plugins = plugins = gst_default_registry_get_plugin_list ();
+-
+- while (plugins) {
+- GList *features, *orig_features;
+-
+- GstPlugin *plugin = (GstPlugin *) (plugins->data);
+- plugins = g_list_next (plugins);
+-
+- if (plugin->flags & (1<<1)) //GST_PLUGIN_FLAG_BLACKLISTED
+- continue;
+-
+- orig_features = features = gst_registry_get_feature_list_by_plugin(gst_registry_get_default (),
+- plugin->desc.name);
+- while (features) {
+- if (!G_UNLIKELY(features->data == NULL)) {
+- GstPluginFeature *feature = GST_PLUGIN_FEATURE(features->data);
+- if (GST_IS_ELEMENT_FACTORY (feature)) {
+- GstElementFactory *factory = GST_ELEMENT_FACTORY(gst_plugin_feature_load(feature));
+- if (factory
+- && factory->numpadtemplates > 0
+- && (qstrcmp(factory->details.klass, "Codec/Decoder/Audio") == 0
+- || qstrcmp(factory->details.klass, "Codec/Decoder/Video") == 0
+- || qstrcmp(factory->details.klass, "Codec/Demux") == 0 )) {
+- const GList *pads = factory->staticpadtemplates;
+- while (pads) {
+- GstStaticPadTemplate *padtemplate = (GstStaticPadTemplate*)(pads->data);
+- pads = g_list_next (pads);
+- if (padtemplate->direction != GST_PAD_SINK)
+- continue;
+- if (padtemplate->static_caps.string) {
+- GstCaps *caps = gst_static_caps_get(&padtemplate->static_caps);
+- if (!gst_caps_is_any (caps) && ! gst_caps_is_empty (caps)) {
+- for (guint i = 0; i < gst_caps_get_size(caps); i++) {
+- GstStructure *structure = gst_caps_get_structure(caps, i);
+- QString nameLowcase = QString(gst_structure_get_name (structure)).toLower();
+-
+- m_supportedMimeTypeSet.insert(nameLowcase);
+- if (nameLowcase.contains("mpeg")) {
+- //Because mpeg version number is only included in the detail
+- //description, it is necessary to manually extract this information
+- //in order to match the mime type of mpeg4.
+- const GValue *value = gst_structure_get_value(structure, "mpegversion");
+- if (value) {
+- gchar *str = gst_value_serialize (value);
+- QString versions(str);
+- QStringList elements = versions.split(QRegExp("\\D+"), QString::SkipEmptyParts);
+- foreach (const QString &e, elements)
+- m_supportedMimeTypeSet.insert(nameLowcase + e);
+- g_free (str);
+- }
+- }
+- }
+- }
+- }
+- }
+- gst_object_unref (factory);
+- }
+- } else if (GST_IS_TYPE_FIND_FACTORY(feature)) {
+- QString name(gst_plugin_feature_get_name(feature));
+- if (name.contains('/')) //filter out any string without '/' which is obviously not a mime type
+- m_supportedMimeTypeSet.insert(name.toLower());
+- }
+- }
+- features = g_list_next (features);
+- }
+- gst_plugin_feature_list_free (orig_features);
+- }
+- gst_plugin_list_free (orig_plugins);
++ return gst_element_factory_list_is_type(factory, GST_ELEMENT_FACTORY_TYPE_DEMUXER)
++ || gst_element_factory_list_is_type(factory, GST_ELEMENT_FACTORY_TYPE_DECODER);
++}
+
+-#if defined QT_SUPPORTEDMIMETYPES_DEBUG
+- QStringList list = m_supportedMimeTypeSet.toList();
+- list.sort();
+- if (qgetenv("QT_DEBUG_PLUGINS").toInt() > 0) {
+- foreach (const QString &type, list)
+- qDebug() << type;
+- }
+-#endif
++void QGstreamerPlayerServicePlugin::updateSupportedMimeTypes() const
++{
++ m_supportedMimeTypeSet = QGstUtils::supportedMimeTypes(isDecoderOrDemuxer);
+ }
+
+ QStringList QGstreamerPlayerServicePlugin::supportedMimeTypes() const
+diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp b/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp
+index 15924a6..b5c354d 100644
+--- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp
++++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp
+@@ -37,7 +37,9 @@
+ #include <private/qgstreameraudioprobecontrol_p.h>
+ #include <private/qgstreamervideoprobecontrol_p.h>
+ #include <private/qgstreamervideorendererinterface_p.h>
++#if !GST_CHECK_VERSION(1,0,0)
+ #include <private/gstvideoconnector_p.h>
++#endif
+ #include <private/qgstutils_p.h>
+ #include <private/playlistfileparser_p.h>
+ #include <private/qgstutils_p.h>
+@@ -85,6 +87,7 @@ typedef enum {
+ GST_PLAY_FLAG_BUFFERING = 0x000000100
+ } GstPlayFlags;
+
++#if !GST_CHECK_VERSION(1,0,0)
+ #define DEFAULT_RAW_CAPS \
+ "video/x-raw-yuv; " \
+ "video/x-raw-rgb; " \
+@@ -97,7 +100,9 @@ typedef enum {
+ "text/x-pango-markup; " \
+ "video/x-dvd-subpicture; " \
+ "subpicture/x-pgs"
++
+ static GstStaticCaps static_RawCaps = GST_STATIC_CAPS(DEFAULT_RAW_CAPS);
++#endif
+
+ QGstreamerPlayerSession::QGstreamerPlayerSession(QObject *parent)
+ :QObject(parent),
+@@ -105,7 +110,9 @@ QGstreamerPlayerSession::QGstreamerPlayerSession(QObject *parent)
+ m_pendingState(QMediaPlayer::StoppedState),
+ m_busHelper(0),
+ m_playbin(0),
++#if !GST_CHECK_VERSION(1,0,0)
+ m_usingColorspaceElement(false),
++#endif
+ m_videoSink(0),
+ m_pendingVideoSink(0),
+ m_nullVideoSink(0),
+@@ -117,8 +124,8 @@ QGstreamerPlayerSession::QGstreamerPlayerSession(QObject *parent)
+ #if defined(HAVE_GST_APPSRC)
+ m_appSrc(0),
+ #endif
+- m_videoBufferProbeId(-1),
+- m_audioBufferProbeId(-1),
++ m_videoProbe(0),
++ m_audioProbe(0),
+ m_volume(100),
+ m_playbackRate(1.0),
+ m_muted(false),
+@@ -138,8 +145,7 @@ QGstreamerPlayerSession::QGstreamerPlayerSession(QObject *parent)
+ Q_ASSERT(result == TRUE);
+ Q_UNUSED(result);
+
+- m_playbin = gst_element_factory_make("playbin2", NULL);
+-
++ m_playbin = gst_element_factory_make(QT_GSTREAMER_PLAYBIN_ELEMENT_NAME, NULL);
+ if (m_playbin) {
+ //GST_PLAY_FLAG_NATIVE_VIDEO omits configuration of ffmpegcolorspace and videoscale,
+ //since those elements are included in the video output bin when necessary.
+@@ -147,13 +153,14 @@ QGstreamerPlayerSession::QGstreamerPlayerSession(QObject *parent)
+ int flags = GST_PLAY_FLAG_VIDEO | GST_PLAY_FLAG_AUDIO |
+ GST_PLAY_FLAG_NATIVE_VIDEO | GST_PLAY_FLAG_NATIVE_AUDIO;
+ #else
+- int flags = 0;
+- g_object_get(G_OBJECT(m_playbin), "flags", &flags, NULL);
++ int flags = GST_PLAY_FLAG_VIDEO | GST_PLAY_FLAG_AUDIO;
+ QByteArray envFlags = qgetenv("QT_GSTREAMER_PLAYBIN_FLAGS");
+ if (!envFlags.isEmpty()) {
+ flags |= envFlags.toInt();
++#if !GST_CHECK_VERSION(1,0,0)
+ } else {
+ flags |= GST_PLAY_FLAG_NATIVE_VIDEO;
++#endif
+ }
+ #endif
+ g_object_set(G_OBJECT(m_playbin), "flags", flags, NULL);
+@@ -185,12 +192,16 @@ QGstreamerPlayerSession::QGstreamerPlayerSession(QObject *parent)
+ }
+ }
+
++#if GST_CHECK_VERSION(1,0,0)
++ m_videoIdentity = gst_element_factory_make("identity", NULL); // floating ref
++#else
+ m_videoIdentity = GST_ELEMENT(g_object_new(gst_video_connector_get_type(), 0)); // floating ref
+ g_signal_connect(G_OBJECT(m_videoIdentity), "connection-failed", G_CALLBACK(insertColorSpaceElement), (gpointer)this);
++ m_colorSpace = gst_element_factory_make(QT_GSTREAMER_COLORCONVERSION_ELEMENT_NAME, "ffmpegcolorspace-vo");
+
+- m_colorSpace = gst_element_factory_make("ffmpegcolorspace", "ffmpegcolorspace-vo");
+ // might not get a parent, take ownership to avoid leak
+ qt_gst_object_ref_sink(GST_OBJECT(m_colorSpace));
++#endif
+
+ m_nullVideoSink = gst_element_factory_make("fakesink", NULL);
+ g_object_set(G_OBJECT(m_nullVideoSink), "sync", true, NULL);
+@@ -206,7 +217,7 @@ QGstreamerPlayerSession::QGstreamerPlayerSession(QObject *parent)
+
+ // add ghostpads
+ GstPad *pad = gst_element_get_static_pad(m_videoIdentity,"sink");
+- gst_element_add_pad(GST_ELEMENT(m_videoOutputBin), gst_ghost_pad_new("videosink", pad));
++ gst_element_add_pad(GST_ELEMENT(m_videoOutputBin), gst_ghost_pad_new("sink", pad));
+ gst_object_unref(GST_OBJECT(pad));
+
+ if (m_playbin != 0) {
+@@ -244,7 +255,9 @@ QGstreamerPlayerSession::~QGstreamerPlayerSession()
+ delete m_busHelper;
+ gst_object_unref(GST_OBJECT(m_bus));
+ gst_object_unref(GST_OBJECT(m_playbin));
++#if !GST_CHECK_VERSION(1,0,0)
+ gst_object_unref(GST_OBJECT(m_colorSpace));
++#endif
+ gst_object_unref(GST_OBJECT(m_nullVideoSink));
+ gst_object_unref(GST_OBJECT(m_videoOutputBin));
+ }
+@@ -339,12 +352,10 @@ qint64 QGstreamerPlayerSession::duration() const
+
+ qint64 QGstreamerPlayerSession::position() const
+ {
+- GstFormat format = GST_FORMAT_TIME;
+ gint64 position = 0;
+
+- if ( m_playbin && gst_element_query_position(m_playbin, &format, &position))
++ if (m_playbin && qt_gst_element_query_position(m_playbin, GST_FORMAT_TIME, &position))
+ m_lastPosition = position / 1000000;
+-
+ return m_lastPosition;
+ }
+
+@@ -474,17 +485,26 @@ bool QGstreamerPlayerSession::isAudioAvailable() const
+ return m_audioAvailable;
+ }
+
++#if GST_CHECK_VERSION(1,0,0)
++static GstPadProbeReturn block_pad_cb(GstPad *pad, GstPadProbeInfo *info, gpointer user_data)
++#else
+ static void block_pad_cb(GstPad *pad, gboolean blocked, gpointer user_data)
++#endif
+ {
+ Q_UNUSED(pad);
++#if GST_CHECK_VERSION(1,0,0)
++ Q_UNUSED(info);
++ Q_UNUSED(user_data);
++ return GST_PAD_PROBE_OK;
++#else
+ #ifdef DEBUG_PLAYBIN
+ qDebug() << "block_pad_cb, blocked:" << blocked;
+ #endif
+-
+ if (blocked && user_data) {
+ QGstreamerPlayerSession *session = reinterpret_cast<QGstreamerPlayerSession*>(user_data);
+ QMetaObject::invokeMethod(session, "finishVideoOutputChange", Qt::QueuedConnection);
+ }
++#endif
+ }
+
+ void QGstreamerPlayerSession::updateVideoRenderer()
+@@ -529,7 +549,7 @@ void QGstreamerPlayerSession::setVideoRenderer(QObject *videoOutput)
+ m_renderer = renderer;
+
+ #ifdef DEBUG_VO_BIN_DUMP
+- _gst_debug_bin_to_dot_file_with_ts(GST_BIN(m_playbin),
++ gst_debug_bin_to_dot_file_with_ts(GST_BIN(m_playbin),
+ GstDebugGraphDetails(GST_DEBUG_GRAPH_SHOW_ALL /* GST_DEBUG_GRAPH_SHOW_MEDIA_TYPE | GST_DEBUG_GRAPH_SHOW_NON_DEFAULT_PARAMS | GST_DEBUG_GRAPH_SHOW_STATES*/),
+ "playbin_set");
+ #endif
+@@ -570,12 +590,14 @@ void QGstreamerPlayerSession::setVideoRenderer(QObject *videoOutput)
+ gst_element_set_state(m_videoSink, GST_STATE_NULL);
+ gst_element_set_state(m_playbin, GST_STATE_NULL);
+
++#if !GST_CHECK_VERSION(1,0,0)
+ if (m_usingColorspaceElement) {
+ gst_element_unlink(m_colorSpace, m_videoSink);
+ gst_bin_remove(GST_BIN(m_videoOutputBin), m_colorSpace);
+ } else {
+ gst_element_unlink(m_videoIdentity, m_videoSink);
+ }
++#endif
+
+ removeVideoBufferProbe();
+
+@@ -585,8 +607,9 @@ void QGstreamerPlayerSession::setVideoRenderer(QObject *videoOutput)
+
+ gst_bin_add(GST_BIN(m_videoOutputBin), m_videoSink);
+
+- m_usingColorspaceElement = false;
+ bool linked = gst_element_link(m_videoIdentity, m_videoSink);
++#if !GST_CHECK_VERSION(1,0,0)
++ m_usingColorspaceElement = false;
+ if (!linked) {
+ m_usingColorspaceElement = true;
+ #ifdef DEBUG_PLAYBIN
+@@ -595,6 +618,10 @@ void QGstreamerPlayerSession::setVideoRenderer(QObject *videoOutput)
+ gst_bin_add(GST_BIN(m_videoOutputBin), m_colorSpace);
+ linked = gst_element_link_many(m_videoIdentity, m_colorSpace, m_videoSink, NULL);
+ }
++#endif
++
++ if (!linked)
++ qWarning() << "Linking video output element failed";
+
+ if (g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "show-preroll-frame") != 0) {
+ gboolean value = m_displayPrerolledFrame;
+@@ -633,7 +660,11 @@ void QGstreamerPlayerSession::setVideoRenderer(QObject *videoOutput)
+
+ //block pads, async to avoid locking in paused state
+ GstPad *srcPad = gst_element_get_static_pad(m_videoIdentity, "src");
++#if GST_CHECK_VERSION(1,0,0)
++ this->pad_probe_id = gst_pad_add_probe(srcPad, (GstPadProbeType)(GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_BLOCKING), block_pad_cb, this, NULL);
++#else
+ gst_pad_set_blocked_async(srcPad, true, &block_pad_cb, this);
++#endif
+ gst_object_unref(GST_OBJECT(srcPad));
+
+ //Unpause the sink to avoid waiting until the buffer is processed
+@@ -671,16 +702,22 @@ void QGstreamerPlayerSession::finishVideoOutputChange()
+ }
+
+ if (m_pendingVideoSink == m_videoSink) {
++ qDebug() << "Abort, no change";
+ //video output was change back to the current one,
+ //no need to torment the pipeline, just unblock the pad
+ if (gst_pad_is_blocked(srcPad))
++#if GST_CHECK_VERSION(1,0,0)
++ gst_pad_remove_probe(srcPad, this->pad_probe_id);
++#else
+ gst_pad_set_blocked_async(srcPad, false, &block_pad_cb, 0);
++#endif
+
+ m_pendingVideoSink = 0;
+ gst_object_unref(GST_OBJECT(srcPad));
+ return;
+ }
+
++#if !GST_CHECK_VERSION(1,0,0)
+ if (m_usingColorspaceElement) {
+ gst_element_set_state(m_colorSpace, GST_STATE_NULL);
+ gst_element_set_state(m_videoSink, GST_STATE_NULL);
+@@ -688,6 +725,9 @@ void QGstreamerPlayerSession::finishVideoOutputChange()
+ gst_element_unlink(m_colorSpace, m_videoSink);
+ gst_bin_remove(GST_BIN(m_videoOutputBin), m_colorSpace);
+ } else {
++#else
++ {
++#endif
+ gst_element_set_state(m_videoSink, GST_STATE_NULL);
+ gst_element_unlink(m_videoIdentity, m_videoSink);
+ }
+@@ -703,8 +743,9 @@ void QGstreamerPlayerSession::finishVideoOutputChange()
+
+ addVideoBufferProbe();
+
+- m_usingColorspaceElement = false;
+ bool linked = gst_element_link(m_videoIdentity, m_videoSink);
++#if !GST_CHECK_VERSION(1,0,0)
++ m_usingColorspaceElement = false;
+ if (!linked) {
+ m_usingColorspaceElement = true;
+ #ifdef DEBUG_PLAYBIN
+@@ -713,6 +754,7 @@ void QGstreamerPlayerSession::finishVideoOutputChange()
+ gst_bin_add(GST_BIN(m_videoOutputBin), m_colorSpace);
+ linked = gst_element_link_many(m_videoIdentity, m_colorSpace, m_videoSink, NULL);
+ }
++#endif
+
+ if (!linked)
+ qWarning() << "Linking video output element failed";
+@@ -720,6 +762,8 @@ void QGstreamerPlayerSession::finishVideoOutputChange()
+ #ifdef DEBUG_PLAYBIN
+ qDebug() << "notify the video connector it has to emit a new segment message...";
+ #endif
++
++#if !GST_CHECK_VERSION(1,0,0)
+ //it's necessary to send a new segment event just before
+ //the first buffer pushed to the new sink
+ g_signal_emit_by_name(m_videoIdentity,
+@@ -727,7 +771,7 @@ void QGstreamerPlayerSession::finishVideoOutputChange()
+ true //emit connection-failed signal
+ //to have a chance to insert colorspace element
+ );
+-
++#endif
+
+ GstState state = GST_STATE_VOID_PENDING;
+
+@@ -743,8 +787,10 @@ void QGstreamerPlayerSession::finishVideoOutputChange()
+ break;
+ }
+
++#if !GST_CHECK_VERSION(1,0,0)
+ if (m_usingColorspaceElement)
+ gst_element_set_state(m_colorSpace, state);
++#endif
+
+ gst_element_set_state(m_videoSink, state);
+
+@@ -760,16 +806,23 @@ void QGstreamerPlayerSession::finishVideoOutputChange()
+
+ //don't have to wait here, it will unblock eventually
+ if (gst_pad_is_blocked(srcPad))
+- gst_pad_set_blocked_async(srcPad, false, &block_pad_cb, 0);
++#if GST_CHECK_VERSION(1,0,0)
++ gst_pad_remove_probe(srcPad, this->pad_probe_id);
++#else
++ gst_pad_set_blocked_async(srcPad, false, &block_pad_cb, 0);
++#endif
++
+ gst_object_unref(GST_OBJECT(srcPad));
+
+ #ifdef DEBUG_VO_BIN_DUMP
+- _gst_debug_bin_to_dot_file_with_ts(GST_BIN(m_playbin),
+- GstDebugGraphDetails(GST_DEBUG_GRAPH_SHOW_ALL /* GST_DEBUG_GRAPH_SHOW_MEDIA_TYPE | GST_DEBUG_GRAPH_SHOW_NON_DEFAULT_PARAMS | GST_DEBUG_GRAPH_SHOW_STATES*/),
++ gst_debug_bin_to_dot_file_with_ts(GST_BIN(m_playbin),
++ GstDebugGraphDetails(GST_DEBUG_GRAPH_SHOW_ALL /* | GST_DEBUG_GRAPH_SHOW_MEDIA_TYPE | GST_DEBUG_GRAPH_SHOW_NON_DEFAULT_PARAMS | GST_DEBUG_GRAPH_SHOW_STATES */),
+ "playbin_finish");
+ #endif
+ }
+
++#if !GST_CHECK_VERSION(1,0,0)
++
+ void QGstreamerPlayerSession::insertColorSpaceElement(GstElement *element, gpointer data)
+ {
+ #ifdef DEBUG_PLAYBIN
+@@ -814,6 +867,7 @@ void QGstreamerPlayerSession::insertColorSpaceElement(GstElement *element, gpoin
+ gst_element_set_state(session->m_colorSpace, state);
+ }
+
++#endif
+
+ bool QGstreamerPlayerSession::isVideoAvailable() const
+ {
+@@ -830,6 +884,7 @@ bool QGstreamerPlayerSession::play()
+ #ifdef DEBUG_PLAYBIN
+ qDebug() << Q_FUNC_INFO;
+ #endif
++
+ m_everPlayed = false;
+ if (m_playbin) {
+ m_pendingState = QMediaPlayer::PlayingState;
+@@ -1161,21 +1216,20 @@ bool QGstreamerPlayerSession::processBusMessage(const QGstreamerMessage &message
+ case GST_MESSAGE_SEGMENT_DONE:
+ break;
+ case GST_MESSAGE_LATENCY:
+-#if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 13)
++#if GST_CHECK_VERSION(0,10,13)
+ case GST_MESSAGE_ASYNC_START:
+ break;
+ case GST_MESSAGE_ASYNC_DONE:
+ {
+- GstFormat format = GST_FORMAT_TIME;
+ gint64 position = 0;
+- if (gst_element_query_position(m_playbin, &format, &position)) {
++ if (qt_gst_element_query_position(m_playbin, GST_FORMAT_TIME, &position)) {
+ position /= 1000000;
+ m_lastPosition = position;
+ emit positionChanged(position);
+ }
+ break;
+ }
+-#if GST_VERSION_MICRO >= 23
++#if GST_CHECK_VERSION(0,10,23)
+ case GST_MESSAGE_REQUEST_STATE:
+ #endif
+ #endif
+@@ -1327,8 +1381,11 @@ void QGstreamerPlayerSession::getStreamsInfo()
+ default:
+ break;
+ }
+-
++#if GST_CHECK_VERSION(1,0,0)
++ if (tags && GST_IS_TAG_LIST(tags)) {
++#else
+ if (tags && gst_is_tag_list(tags)) {
++#endif
+ gchar *languageCode = 0;
+ if (gst_tag_list_get_string(tags, GST_TAG_LANGUAGE_CODE, &languageCode))
+ streamProperties[QMediaMetaData::Language] = QString::fromUtf8(languageCode);
+@@ -1365,9 +1422,8 @@ void QGstreamerPlayerSession::updateVideoResolutionTag()
+ #endif
+ QSize size;
+ QSize aspectRatio;
+-
+ GstPad *pad = gst_element_get_static_pad(m_videoIdentity, "src");
+- GstCaps *caps = gst_pad_get_negotiated_caps(pad);
++ GstCaps *caps = qt_gst_pad_get_current_caps(pad);
+
+ if (caps) {
+ const GstStructure *structure = gst_caps_get_structure(caps, 0);
+@@ -1407,11 +1463,10 @@ void QGstreamerPlayerSession::updateVideoResolutionTag()
+
+ void QGstreamerPlayerSession::updateDuration()
+ {
+- GstFormat format = GST_FORMAT_TIME;
+ gint64 gstDuration = 0;
+ int duration = -1;
+
+- if (m_playbin && gst_element_query_duration(m_playbin, &format, &gstDuration))
++ if (m_playbin && qt_gst_element_query_duration(m_playbin, GST_FORMAT_TIME, &gstDuration))
+ duration = gstDuration / 1000000;
+
+ if (m_duration != duration) {
+@@ -1467,7 +1522,7 @@ void QGstreamerPlayerSession::playbinNotifySource(GObject *o, GParamSpec *p, gpo
+
+ // The rest
+ if (g_object_class_find_property(G_OBJECT_GET_CLASS(source), "extra-headers") != 0) {
+- GstStructure *extras = gst_structure_empty_new("extras");
++ GstStructure *extras = qt_gst_structure_new_empty("extras");
+
+ foreach (const QByteArray &rawHeader, self->m_request.rawHeaderList()) {
+ if (rawHeader == userAgentString) // Filter User-Agent
+@@ -1528,7 +1583,8 @@ void QGstreamerPlayerSession::playbinNotifySource(GObject *o, GParamSpec *p, gpo
+ qDebug() << "Current source is a non-live source";
+ #endif
+
+- g_object_set(G_OBJECT(self->m_videoSink), "sync", !self->m_isLiveSource, NULL);
++ if (self->m_videoSink)
++ g_object_set(G_OBJECT(self->m_videoSink), "sync", !self->m_isLiveSource, NULL);
+
+ gst_object_unref(source);
+ }
+@@ -1623,7 +1679,11 @@ GstAutoplugSelectResult QGstreamerPlayerSession::handleAutoplugSelect(GstBin *bi
+ const gchar *factoryName = gst_plugin_feature_get_name(GST_PLUGIN_FEATURE(factory));
+ if (g_str_has_prefix(factoryName, "vaapi")) {
+ GstPad *sinkPad = gst_element_get_static_pad(session->m_videoSink, "sink");
++#if GST_CHECK_VERSION(1,0,0)
++ GstCaps *sinkCaps = gst_pad_query_caps(sinkPad, NULL);
++#else
+ GstCaps *sinkCaps = gst_pad_get_caps(sinkPad);
++#endif
+
+ #if (GST_VERSION_MAJOR == 0) && ((GST_VERSION_MINOR < 10) || (GST_VERSION_MICRO < 33))
+ if (!factory_can_src_any_caps(factory, sinkCaps))
+@@ -1652,8 +1712,10 @@ void QGstreamerPlayerSession::handleElementAdded(GstBin *bin, GstElement *elemen
+ // Disable on-disk buffering.
+ g_object_set(G_OBJECT(element), "temp-template", NULL, NULL);
+ } else if (g_str_has_prefix(elementName, "uridecodebin") ||
+- g_str_has_prefix(elementName, "decodebin2")) {
+-
++#if GST_CHECK_VERSION(1,0,0)
++ g_str_has_prefix(elementName, "decodebin")) {
++#else
++ g_str_has_prefix(elementName, "decodebin2")) {
+ if (g_str_has_prefix(elementName, "uridecodebin")) {
+ // Add video/x-surface (VAAPI) to default raw formats
+ g_object_set(G_OBJECT(element), "caps", gst_static_caps_get(&static_RawCaps), NULL);
+@@ -1661,7 +1723,7 @@ void QGstreamerPlayerSession::handleElementAdded(GstBin *bin, GstElement *elemen
+ // video sink doesn't support it
+ g_signal_connect(element, "autoplug-select", G_CALLBACK(handleAutoplugSelect), session);
+ }
+-
++#endif
+ //listen for queue2 element added to uridecodebin/decodebin2 as well.
+ //Don't touch other bins since they may have unrelated queues
+ g_signal_connect(element, "element-added",
+@@ -1711,68 +1773,30 @@ void QGstreamerPlayerSession::showPrerollFrames(bool enabled)
+
+ void QGstreamerPlayerSession::addProbe(QGstreamerVideoProbeControl* probe)
+ {
+- QMutexLocker locker(&m_videoProbeMutex);
+-
+- if (m_videoProbes.contains(probe))
+- return;
+-
+- m_videoProbes.append(probe);
++ Q_ASSERT(!m_videoProbe);
++ m_videoProbe = probe;
++ addVideoBufferProbe();
+ }
+
+ void QGstreamerPlayerSession::removeProbe(QGstreamerVideoProbeControl* probe)
+ {
+- QMutexLocker locker(&m_videoProbeMutex);
+- m_videoProbes.removeOne(probe);
+- // Do not emit flush signal in this case.
+- // Assume user releases any outstanding references to video frames.
+-}
+-
+-gboolean QGstreamerPlayerSession::padVideoBufferProbe(GstPad *pad, GstBuffer *buffer, gpointer user_data)
+-{
+- Q_UNUSED(pad);
+-
+- QGstreamerPlayerSession *session = reinterpret_cast<QGstreamerPlayerSession*>(user_data);
+- QMutexLocker locker(&session->m_videoProbeMutex);
+-
+- if (session->m_videoProbes.isEmpty())
+- return TRUE;
+-
+- foreach (QGstreamerVideoProbeControl* probe, session->m_videoProbes)
+- probe->bufferProbed(buffer);
+-
+- return TRUE;
++ Q_ASSERT(m_videoProbe == probe);
++ removeVideoBufferProbe();
++ m_videoProbe = 0;
+ }
+
+ void QGstreamerPlayerSession::addProbe(QGstreamerAudioProbeControl* probe)
+ {
+- QMutexLocker locker(&m_audioProbeMutex);
+-
+- if (m_audioProbes.contains(probe))
+- return;
+-
+- m_audioProbes.append(probe);
++ Q_ASSERT(!m_audioProbe);
++ m_audioProbe = probe;
++ addAudioBufferProbe();
+ }
+
+ void QGstreamerPlayerSession::removeProbe(QGstreamerAudioProbeControl* probe)
+ {
+- QMutexLocker locker(&m_audioProbeMutex);
+- m_audioProbes.removeOne(probe);
+-}
+-
+-gboolean QGstreamerPlayerSession::padAudioBufferProbe(GstPad *pad, GstBuffer *buffer, gpointer user_data)
+-{
+- Q_UNUSED(pad);
+-
+- QGstreamerPlayerSession *session = reinterpret_cast<QGstreamerPlayerSession*>(user_data);
+- QMutexLocker locker(&session->m_audioProbeMutex);
+-
+- if (session->m_audioProbes.isEmpty())
+- return TRUE;
+-
+- foreach (QGstreamerAudioProbeControl* probe, session->m_audioProbes)
+- probe->bufferProbed(buffer);
+-
+- return TRUE;
++ Q_ASSERT(m_audioProbe == probe);
++ removeAudioBufferProbe();
++ m_audioProbe = 0;
+ }
+
+ // This function is similar to stop(),
+@@ -1797,80 +1821,62 @@ void QGstreamerPlayerSession::endOfMediaReset()
+
+ void QGstreamerPlayerSession::removeVideoBufferProbe()
+ {
+- if (m_videoBufferProbeId == -1)
++ if (!m_videoProbe)
+ return;
+
+- if (!m_videoSink) {
+- m_videoBufferProbeId = -1;
+- return;
+- }
+-
+ GstPad *pad = gst_element_get_static_pad(m_videoSink, "sink");
+ if (pad) {
+- gst_pad_remove_buffer_probe(pad, m_videoBufferProbeId);
++ m_videoProbe->removeProbeFromPad(pad);
+ gst_object_unref(GST_OBJECT(pad));
+ }
+-
+- m_videoBufferProbeId = -1;
+ }
+
+ void QGstreamerPlayerSession::addVideoBufferProbe()
+ {
+- Q_ASSERT(m_videoBufferProbeId == -1);
+- if (!m_videoSink)
++ if (!m_videoProbe)
+ return;
+
+ GstPad *pad = gst_element_get_static_pad(m_videoSink, "sink");
+ if (pad) {
+- m_videoBufferProbeId = gst_pad_add_buffer_probe(pad, G_CALLBACK(padVideoBufferProbe), this);
++ m_videoProbe->addProbeToPad(pad);
+ gst_object_unref(GST_OBJECT(pad));
+ }
+ }
+
+ void QGstreamerPlayerSession::removeAudioBufferProbe()
+ {
+- if (m_audioBufferProbeId == -1)
+- return;
+-
+- if (!m_audioSink) {
+- m_audioBufferProbeId = -1;
++ if (!m_audioProbe)
+ return;
+- }
+
+ GstPad *pad = gst_element_get_static_pad(m_audioSink, "sink");
+ if (pad) {
+- gst_pad_remove_buffer_probe(pad, m_audioBufferProbeId);
++ m_audioProbe->removeProbeFromPad(pad);
+ gst_object_unref(GST_OBJECT(pad));
+ }
+-
+- m_audioBufferProbeId = -1;
+ }
+
+ void QGstreamerPlayerSession::addAudioBufferProbe()
+ {
+- Q_ASSERT(m_audioBufferProbeId == -1);
+- if (!m_audioSink)
++ if (!m_audioProbe)
+ return;
+
+ GstPad *pad = gst_element_get_static_pad(m_audioSink, "sink");
+ if (pad) {
+- m_audioBufferProbeId = gst_pad_add_buffer_probe(pad, G_CALLBACK(padAudioBufferProbe), this);
++ m_audioProbe->addProbeToPad(pad);
+ gst_object_unref(GST_OBJECT(pad));
+ }
+ }
+
+ void QGstreamerPlayerSession::flushVideoProbes()
+ {
+- QMutexLocker locker(&m_videoProbeMutex);
+- foreach (QGstreamerVideoProbeControl* probe, m_videoProbes)
+- probe->startFlushing();
++ if (m_videoProbe)
++ m_videoProbe->startFlushing();
+ }
+
+ void QGstreamerPlayerSession::resumeVideoProbes()
+ {
+- QMutexLocker locker(&m_videoProbeMutex);
+- foreach (QGstreamerVideoProbeControl* probe, m_videoProbes)
+- probe->stopFlushing();
++ if (m_videoProbe)
++ m_videoProbe->stopFlushing();
+ }
+
+ void QGstreamerPlayerSession::playlistTypeFindFunction(GstTypeFind *find, gpointer userData)
+@@ -1878,7 +1884,11 @@ void QGstreamerPlayerSession::playlistTypeFindFunction(GstTypeFind *find, gpoint
+ QGstreamerPlayerSession* session = (QGstreamerPlayerSession*)userData;
+
+ const gchar *uri = 0;
++#if GST_CHECK_VERSION(1,0,0)
++ g_object_get(G_OBJECT(session->m_playbin), "current-uri", &uri, NULL);
++#else
+ g_object_get(G_OBJECT(session->m_playbin), "uri", &uri, NULL);
++#endif
+
+ guint64 length = gst_type_find_get_length(find);
+ if (!length)
+@@ -1887,7 +1897,7 @@ void QGstreamerPlayerSession::playlistTypeFindFunction(GstTypeFind *find, gpoint
+ length = qMin(length, guint64(1024));
+
+ while (length > 0) {
+- guint8 *data = gst_type_find_peek(find, 0, length);
++ const guint8 *data = gst_type_find_peek(find, 0, length);
+ if (data) {
+ session->m_isPlaylist = (QPlaylistFileParser::findPlaylistType(QString::fromUtf8(uri), 0, data, length) != QPlaylistFileParser::UNKNOWN);
+ return;
+diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.h b/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.h
+index f2e760a..92b4a0c 100644
+--- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.h
++++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.h
+@@ -119,11 +119,9 @@ public:
+
+ void addProbe(QGstreamerVideoProbeControl* probe);
+ void removeProbe(QGstreamerVideoProbeControl* probe);
+- static gboolean padVideoBufferProbe(GstPad *pad, GstBuffer *buffer, gpointer user_data);
+
+ void addProbe(QGstreamerAudioProbeControl* probe);
+ void removeProbe(QGstreamerAudioProbeControl* probe);
+- static gboolean padAudioBufferProbe(GstPad *pad, GstBuffer *buffer, gpointer user_data);
+
+ void endOfMediaReset();
+
+@@ -172,7 +170,9 @@ private:
+ static void playbinNotifySource(GObject *o, GParamSpec *p, gpointer d);
+ static void handleVolumeChange(GObject *o, GParamSpec *p, gpointer d);
+ static void handleMutedChange(GObject *o, GParamSpec *p, gpointer d);
++#if !GST_CHECK_VERSION(1,0,0)
+ static void insertColorSpaceElement(GstElement *element, gpointer data);
++#endif
+ static void handleElementAdded(GstBin *bin, GstElement *element, QGstreamerPlayerSession *session);
+ static void handleStreamsChange(GstBin *bin, gpointer user_data);
+ static GstAutoplugSelectResult handleAutoplugSelect(GstBin *bin, GstPad *pad, GstCaps *caps, GstElementFactory *factory, QGstreamerPlayerSession *session);
+@@ -194,11 +194,14 @@ private:
+ QGstreamerBusHelper* m_busHelper;
+ GstElement* m_playbin;
+
++ GstElement* m_videoSink;
++
+ GstElement* m_videoOutputBin;
+ GstElement* m_videoIdentity;
++#if !GST_CHECK_VERSION(1,0,0)
+ GstElement* m_colorSpace;
+ bool m_usingColorspaceElement;
+- GstElement* m_videoSink;
++#endif
+ GstElement* m_pendingVideoSink;
+ GstElement* m_nullVideoSink;
+
+@@ -218,13 +221,8 @@ private:
+ QList<QMediaStreamsControl::StreamType> m_streamTypes;
+ QMap<QMediaStreamsControl::StreamType, int> m_playbin2StreamOffset;
+
+- QList<QGstreamerVideoProbeControl*> m_videoProbes;
+- QMutex m_videoProbeMutex;
+- int m_videoBufferProbeId;
+-
+- QList<QGstreamerAudioProbeControl*> m_audioProbes;
+- QMutex m_audioProbeMutex;
+- int m_audioBufferProbeId;
++ QGstreamerVideoProbeControl *m_videoProbe;
++ QGstreamerAudioProbeControl *m_audioProbe;
+
+ int m_volume;
+ qreal m_playbackRate;
+@@ -252,6 +250,7 @@ private:
+ bool m_isLiveSource;
+
+ bool m_isPlaylist;
++ gulong pad_probe_id;
+ };
+
+ QT_END_NAMESPACE
+diff --git a/tests/auto/integration/qcamerabackend/tst_qcamerabackend.cpp b/tests/auto/integration/qcamerabackend/tst_qcamerabackend.cpp
+index 344f1f5..2711ae0 100644
+--- a/tests/auto/integration/qcamerabackend/tst_qcamerabackend.cpp
++++ b/tests/auto/integration/qcamerabackend/tst_qcamerabackend.cpp
+@@ -495,6 +495,8 @@ void tst_QCameraBackend::testCaptureToBuffer()
+ QCOMPARE(imageCapture.bufferFormat(), QVideoFrame::Format_Jpeg);
+ }
+
++ QTRY_VERIFY(imageCapture.isReadyForCapture());
++
+ //Try to capture to both buffer and file
+ #ifdef Q_WS_MAEMO_6
+ QVERIFY(imageCapture.isCaptureDestinationSupported(QCameraImageCapture::CaptureToBuffer | QCameraImageCapture::CaptureToFile));
+@@ -651,11 +653,11 @@ void tst_QCameraBackend::testVideoRecording()
+ {
+ QFETCH(QByteArray, device);
+
+- QCamera *camera = device.isEmpty() ? new QCamera : new QCamera(device);
++ QScopedPointer<QCamera> camera(device.isEmpty() ? new QCamera : new QCamera(device));
+
+- QMediaRecorder recorder(camera);
++ QMediaRecorder recorder(camera.data());
+
+- QSignalSpy errorSignal(camera, SIGNAL(error(QCamera::Error)));
++ QSignalSpy errorSignal(camera.data(), SIGNAL(error(QCamera::Error)));
+ QSignalSpy recorderErrorSignal(&recorder, SIGNAL(error(QMediaRecorder::Error)));
+ QSignalSpy recorderStatusSignal(&recorder, SIGNAL(statusChanged(QMediaRecorder::Status)));
+
+@@ -702,8 +704,6 @@ void tst_QCameraBackend::testVideoRecording()
+ camera->setCaptureMode(QCamera::CaptureStillImage);
+ QTRY_COMPARE(recorder.status(), QMediaRecorder::UnloadedStatus);
+ QCOMPARE(recorderStatusSignal.last().first().value<QMediaRecorder::Status>(), recorder.status());
+-
+- delete camera;
+ }
+
+ QTEST_MAIN(tst_QCameraBackend)
+diff --git a/tests/auto/integration/qmediaplayerbackend/tst_qmediaplayerbackend.cpp b/tests/auto/integration/qmediaplayerbackend/tst_qmediaplayerbackend.cpp
+index 0a1441c..ddf438b 100644
+--- a/tests/auto/integration/qmediaplayerbackend/tst_qmediaplayerbackend.cpp
++++ b/tests/auto/integration/qmediaplayerbackend/tst_qmediaplayerbackend.cpp
+@@ -724,7 +724,7 @@ void tst_QMediaPlayerBackend::seekPauseSeek()
+
+ {
+ QVideoFrame frame = surface->m_frameList.back();
+- const qint64 elapsed = frame.startTime() - position;
++ const qint64 elapsed = (frame.startTime() / 1000) - position; // frame.startTime() is microsecond, position is milliseconds.
+ QVERIFY2(qAbs(elapsed) < (qint64)500, QByteArray::number(elapsed).constData());
+ QCOMPARE(frame.width(), 160);
+ QCOMPARE(frame.height(), 120);
+@@ -748,7 +748,7 @@ void tst_QMediaPlayerBackend::seekPauseSeek()
+
+ {
+ QVideoFrame frame = surface->m_frameList.back();
+- const qint64 elapsed = frame.startTime() - position;
++ const qint64 elapsed = (frame.startTime() / 1000) - position;
+ QVERIFY2(qAbs(elapsed) < (qint64)500, QByteArray::number(elapsed).constData());
+ QCOMPARE(frame.width(), 160);
+ QCOMPARE(frame.height(), 120);
+--
+2.1.4
+
diff --git a/recipes-qt/qt5/qtmultimedia/0001-Initial-porting-effort-to-GStreamer-1.0.patch b/recipes-qt/qt5/qtmultimedia/0001-Initial-porting-effort-to-GStreamer-1.0.patch
deleted file mode 100644
index 8c6c4fa..0000000
--- a/recipes-qt/qt5/qtmultimedia/0001-Initial-porting-effort-to-GStreamer-1.0.patch
+++ /dev/null
@@ -1,2369 +0,0 @@
-From 4af76880d63e8d392eb8add8b8999e3f5031675a Mon Sep 17 00:00:00 2001
-From: Yoann Lopes <yoann.lopes at digia.com>
-Date: Thu, 31 Oct 2013 15:06:30 +0100
-Subject: [PATCH 1/2] Initial porting effort to GStreamer 1.0.
-
-Imported from git at github.com:jhodapp/qtmultimedia.git
-
-Contributions from:
-Ilya Smelykh <ilya at videoexpertsgroup.com>
-Jim Hodapp <jim.hodapp at canonical.com>
-Sergio Schvezov <sergio.schvezov at canonical.com>
-
-Change-Id: I10fa5e5078efa4564ce833befd417008e26a90a9
-Reviewed-by: Yoann Lopes <yoann.lopes at digia.com>
-(cherry picked from commit d91dac090d92fdbc3a3425e8d969c62e5c79eff9)
-
-Conflicts:
- src/gsttools/qgstreamervideorenderer.cpp
- src/gsttools/qgstreamervideowidget.cpp
- src/gsttools/qgstreamervideowindow.cpp
- src/plugins/gstreamer/camerabin/camerabinsession.cpp
- src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp
- src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp
----
- config.tests/gstreamer/gstreamer.pro | 11 +-
- config.tests/gstreamer_appsrc/gstreamer_appsrc.pro | 13 +-
- .../gstreamer_encodingprofiles.pro | 13 +-
- .../gstreamer_photography.pro | 15 +-
- qtmultimedia.pro | 25 ++-
- src/gsttools/gsttools.pro | 22 +--
- src/gsttools/gstvideoconnector.c | 199 +++++++++++++++++++--
- src/gsttools/qgstappsrc.cpp | 29 ++-
- src/gsttools/qgstreameraudioprobecontrol.cpp | 19 +-
- src/gsttools/qgstreamerbushelper.cpp | 8 +
- src/gsttools/qgstreamervideoprobecontrol.cpp | 9 +
- src/gsttools/qgstreamervideorenderer.cpp | 3 +-
- src/gsttools/qgstreamervideowidget.cpp | 29 ++-
- src/gsttools/qgstreamervideowindow.cpp | 79 +++++++-
- src/gsttools/qgstutils.cpp | 27 ++-
- src/gsttools/qgstvideobuffer.cpp | 18 +-
- src/gsttools/qvideosurfacegstsink.cpp | 138 +++++++++++++-
- src/multimedia/gsttools_headers/qgstappsrc_p.h | 3 +
- .../qgstreameraudioprobecontrol_p.h | 5 +-
- .../qgstreamervideoprobecontrol_p.h | 4 +
- .../gsttools_headers/qgstreamervideowindow_p.h | 4 +
- src/multimedia/gsttools_headers/qgstutils_p.h | 4 +
- .../gsttools_headers/qgstvideobuffer_p.h | 3 +
- .../gsttools_headers/qvideosurfacegstsink_p.h | 6 +-
- .../qgstreameraudiodecoderserviceplugin.cpp | 27 ++-
- .../audiodecoder/qgstreameraudiodecodersession.cpp | 33 +++-
- .../gstreamer/camerabin/camerabinsession.cpp | 25 +++
- src/plugins/gstreamer/common.pri | 21 ++-
- src/plugins/gstreamer/gstreamer.pro | 3 +-
- .../mediacapture/qgstreamercapturesession.cpp | 5 +
- src/plugins/gstreamer/mediaplayer/mediaplayer.pro | 1 -
- .../mediaplayer/qgstreamerplayercontrol.cpp | 2 +
- .../mediaplayer/qgstreamerplayerservice.cpp | 9 +-
- .../mediaplayer/qgstreamerplayerserviceplugin.cpp | 27 ++-
- .../mediaplayer/qgstreamerplayersession.cpp | 154 ++++++++++++++--
- .../mediaplayer/qgstreamerplayersession.h | 9 +
- 36 files changed, 872 insertions(+), 130 deletions(-)
-
-diff --git a/config.tests/gstreamer/gstreamer.pro b/config.tests/gstreamer/gstreamer.pro
-index 02a7e34..6b9843a 100644
---- a/config.tests/gstreamer/gstreamer.pro
-+++ b/config.tests/gstreamer/gstreamer.pro
-@@ -3,11 +3,10 @@ SOURCES += main.cpp
- CONFIG += link_pkgconfig
-
- PKGCONFIG += \
-- gstreamer-0.10 \
-- gstreamer-base-0.10 \
-- gstreamer-interfaces-0.10 \
-- gstreamer-audio-0.10 \
-- gstreamer-video-0.10 \
-- gstreamer-pbutils-0.10
-+ gstreamer-$$GST_VERSION \
-+ gstreamer-base-$$GST_VERSION \
-+ gstreamer-audio-$$GST_VERSION \
-+ gstreamer-video-$$GST_VERSION \
-+ gstreamer-pbutils-$$GST_VERSION
-
-
-diff --git a/config.tests/gstreamer_appsrc/gstreamer_appsrc.pro b/config.tests/gstreamer_appsrc/gstreamer_appsrc.pro
-index 9f61703..0f3ca2b 100644
---- a/config.tests/gstreamer_appsrc/gstreamer_appsrc.pro
-+++ b/config.tests/gstreamer_appsrc/gstreamer_appsrc.pro
-@@ -3,11 +3,8 @@ SOURCES += main.cpp
- CONFIG += link_pkgconfig
-
- PKGCONFIG += \
-- gstreamer-0.10 \
-- gstreamer-base-0.10 \
-- gstreamer-interfaces-0.10 \
-- gstreamer-audio-0.10 \
-- gstreamer-video-0.10 \
-- gstreamer-app-0.10
--
--
-+ gstreamer-$$GST_VERSION \
-+ gstreamer-base-$$GST_VERSION \
-+ gstreamer-audio-$$GST_VERSION \
-+ gstreamer-video-$$GST_VERSION \
-+ gstreamer-pbutils-$$GST_VERSION
-diff --git a/config.tests/gstreamer_encodingprofiles/gstreamer_encodingprofiles.pro b/config.tests/gstreamer_encodingprofiles/gstreamer_encodingprofiles.pro
-index 7e8a9e7..fad40b0 100644
---- a/config.tests/gstreamer_encodingprofiles/gstreamer_encodingprofiles.pro
-+++ b/config.tests/gstreamer_encodingprofiles/gstreamer_encodingprofiles.pro
-@@ -2,11 +2,10 @@ SOURCES += main.cpp
-
- CONFIG += link_pkgconfig
-
--PKGCONFIG += \
-- gstreamer-0.10 \
-- gstreamer-base-0.10 \
-- gstreamer-interfaces-0.10 \
-- gstreamer-audio-0.10 \
-- gstreamer-video-0.10 \
-- gstreamer-pbutils-0.10
-
-+PKGCONFIG += \
-+ gstreamer-$$GST_VERSION \
-+ gstreamer-base-$$GST_VERSION \
-+ gstreamer-audio-$$GST_VERSION \
-+ gstreamer-video-$$GST_VERSION \
-+ gstreamer-pbutils-$$GST_VERSION
-diff --git a/config.tests/gstreamer_photography/gstreamer_photography.pro b/config.tests/gstreamer_photography/gstreamer_photography.pro
-index 6b530cb..975991f 100644
---- a/config.tests/gstreamer_photography/gstreamer_photography.pro
-+++ b/config.tests/gstreamer_photography/gstreamer_photography.pro
-@@ -3,12 +3,11 @@ SOURCES += main.cpp
- CONFIG += link_pkgconfig
-
- PKGCONFIG += \
-- gstreamer-0.10 \
-- gstreamer-base-0.10 \
-- gstreamer-interfaces-0.10 \
-- gstreamer-audio-0.10 \
-- gstreamer-video-0.10 \
-- gstreamer-pbutils-0.10
--
--LIBS += -lgstphotography-0.10
-+ gstreamer-$$GST_VERSION \
-+ gstreamer-base-$$GST_VERSION \
-+ gstreamer-audio-$$GST_VERSION \
-+ gstreamer-video-$$GST_VERSION \
-+ gstreamer-pbutils-$$GST_VERSION
-+
-+LIBS += -lgstphotography-$$GST_VERSION
-
-diff --git a/qtmultimedia.pro b/qtmultimedia.pro
-index 3cec526..109dd81 100644
---- a/qtmultimedia.pro
-+++ b/qtmultimedia.pro
-@@ -17,11 +17,26 @@ win32 {
- } else {
- qtCompileTest(alsa)
- qtCompileTest(pulseaudio)
-- qtCompileTest(gstreamer) {
-- qtCompileTest(gstreamer_photography)
-- qtCompileTest(gstreamer_encodingprofiles)
-- qtCompileTest(gstreamer_appsrc)
-- qtCompileTest(linux_v4l)
-+ !done_config_gstreamer {
-+ gstver=1.0
-+ cache(GST_VERSION, set, gstver);
-+ qtCompileTest(gstreamer) {
-+ qtCompileTest(gstreamer_photography)
-+ qtCompileTest(gstreamer_encodingprofiles)
-+ qtCompileTest(gstreamer_appsrc)
-+ qtCompileTest(linux_v4l)
-+ } else {
-+ gstver=0.10
-+ cache(GST_VERSION, set, gstver);
-+ # Force a re-run of the test
-+ CONFIG -= done_config_gstreamer
-+ qtCompileTest(gstreamer) {
-+ qtCompileTest(gstreamer_photography)
-+ qtCompileTest(gstreamer_encodingprofiles)
-+ qtCompileTest(gstreamer_appsrc)
-+ qtCompileTest(linux_v4l)
-+ }
-+ }
- }
- qtCompileTest(resourcepolicy)
- qtCompileTest(gpu_vivante)
-diff --git a/src/gsttools/gsttools.pro b/src/gsttools/gsttools.pro
-index 7c809a7..6b9bf5d 100644
---- a/src/gsttools/gsttools.pro
-+++ b/src/gsttools/gsttools.pro
-@@ -2,7 +2,7 @@ TEMPLATE = lib
-
- TARGET = qgsttools_p
- QPRO_PWD = $$PWD
--QT = core-private multimedia-private gui-private
-+QT = core-private multimedia-private gui-private opengl
-
- !static:DEFINES += QT_MAKEDLL
- DEFINES += GLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_26
-@@ -15,13 +15,14 @@ LIBS_PRIVATE += \
-
- CONFIG += link_pkgconfig
-
--PKGCONFIG_PRIVATE += \
-- gstreamer-0.10 \
-- gstreamer-base-0.10 \
-- gstreamer-interfaces-0.10 \
-- gstreamer-audio-0.10 \
-- gstreamer-video-0.10 \
-- gstreamer-pbutils-0.10
-+PKGCONFIG += \
-+ gstreamer-$$GST_VERSION \
-+ gstreamer-base-$$GST_VERSION \
-+ gstreamer-audio-$$GST_VERSION \
-+ gstreamer-video-$$GST_VERSION \
-+ gstreamer-pbutils-$$GST_VERSION
-+
-+equals(GST_VERSION,"0.10"): PKGCONFIG_PRIVATE += gstreamer-interfaces-$$GST_VERSION
-
- maemo*: PKGCONFIG_PRIVATE +=gstreamer-plugins-bad-0.10
-
-@@ -33,6 +34,7 @@ config_resourcepolicy {
- # Header files must go inside source directory of a module
- # to be installed by syncqt.
- INCLUDEPATH += ../multimedia/gsttools_headers/
-+INCLUDEPATH += ../plugins/gstreamer/mediaplayer/
- VPATH += ../multimedia/gsttools_headers/
-
- PRIVATE_HEADERS += \
-@@ -91,13 +93,13 @@ maemo6 {
- }
-
- config_gstreamer_appsrc {
-- PKGCONFIG_PRIVATE += gstreamer-app-0.10
-+ PKGCONFIG_PRIVATE += gstreamer-app-$$GST_VERSION
- PRIVATE_HEADERS += qgstappsrc_p.h
- SOURCES += qgstappsrc.cpp
-
- DEFINES += HAVE_GST_APPSRC
-
-- LIBS_PRIVATE += -lgstapp-0.10
-+ LIBS_PRIVATE += -lgstapp-$$GST_VERSION
- }
-
- config_linux_v4l: DEFINES += USE_V4L
-diff --git a/src/gsttools/gstvideoconnector.c b/src/gsttools/gstvideoconnector.c
-index 3ed539e..ed0ed3c 100644
---- a/src/gsttools/gstvideoconnector.c
-+++ b/src/gsttools/gstvideoconnector.c
-@@ -59,26 +59,93 @@ GST_STATIC_PAD_TEMPLATE ("src",
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS_ANY);
-
-+
-+#if GST_CHECK_VERSION(1,0,0)
-+
-+G_DEFINE_TYPE(GstVideoConnector, gst_video_connector, GST_TYPE_ELEMENT);
-+#else
- #define _do_init(bla) \
- GST_DEBUG_CATEGORY_INIT (video_connector_debug, \
- "video-connector", 0, "An identity like element for reconnecting video stream");
-
- GST_BOILERPLATE_FULL (GstVideoConnector, gst_video_connector, GstElement,
- GST_TYPE_ELEMENT, _do_init);
-+#endif
-
- static void gst_video_connector_dispose (GObject * object);
-+
-+#if GST_CHECK_VERSION(1,0,0)
-+static GstFlowReturn gst_video_connector_chain (GstPad * pad, GstObject* parent, GstBuffer * buf);
-+#else
- static GstFlowReturn gst_video_connector_chain (GstPad * pad, GstBuffer * buf);
- static GstFlowReturn gst_video_connector_buffer_alloc (GstPad * pad,
- guint64 offset, guint size, GstCaps * caps, GstBuffer ** buf);
-+#endif
-+
- static GstStateChangeReturn gst_video_connector_change_state (GstElement *
- element, GstStateChange transition);
-+
-+#if GST_CHECK_VERSION(1,0,0)
-+static gboolean gst_video_connector_handle_sink_event (GstPad * pad, GstObject* parent,
-+ GstEvent * event);
-+#else
- static gboolean gst_video_connector_handle_sink_event (GstPad * pad,
- GstEvent * event);
-+#endif
-+
-+#if GST_CHECK_VERSION(1,0,0)
-+static GstPadProbeReturn gst_video_connector_new_buffer_probe(GstPad *pad, GstPadProbeInfo *info, gpointer object);
-+static GstPadProbeReturn gst_video_connector_new_event_probe(GstPad *pad, GstPadProbeInfo *info, gpointer object);
-+static GstPadProbeReturn gst_video_connector_new_query_probe(GstPad *pad, GstPadProbeInfo *info, gpointer object);
-+#else
- static gboolean gst_video_connector_new_buffer_probe(GstObject *pad, GstBuffer *buffer, guint * object);
--static void gst_video_connector_resend_new_segment(GstElement * element, gboolean emitFailedSignal);
- static gboolean gst_video_connector_setcaps (GstPad *pad, GstCaps *caps);
- static GstCaps *gst_video_connector_getcaps (GstPad * pad);
- static gboolean gst_video_connector_acceptcaps (GstPad * pad, GstCaps * caps);
-+#endif
-+
-+static void gst_video_connector_resend_new_segment(GstElement * element, gboolean emitFailedSignal);
-+
-+#if GST_CHECK_VERSION(1,0,0)
-+static void
-+gst_video_connector_class_init (GstVideoConnectorClass * klass)
-+{
-+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-+ GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
-+
-+ gst_element_class_set_details_simple (gstelement_class, "Video Connector",
-+ "Generic",
-+ "An identity like element used for reconnecting video stream",
-+ "Dmytro Poplavskiy <dmytro.poplavskiy at nokia.com>");
-+ gst_element_class_add_pad_template (gstelement_class,
-+ gst_static_pad_template_get (&gst_video_connector_sink_factory));
-+ gst_element_class_add_pad_template (gstelement_class,
-+ gst_static_pad_template_get (&gst_video_connector_src_factory));
-+
-+ gst_video_connector_parent_class = g_type_class_peek_parent (klass);
-+
-+ gobject_class->dispose = gst_video_connector_dispose;
-+ gstelement_class->change_state = gst_video_connector_change_state;
-+ klass->resend_new_segment = gst_video_connector_resend_new_segment;
-+
-+ gst_video_connector_signals[SIGNAL_RESEND_NEW_SEGMENT] =
-+ g_signal_new ("resend-new-segment", G_TYPE_FROM_CLASS (klass),
-+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
-+ G_STRUCT_OFFSET (GstVideoConnectorClass, resend_new_segment), NULL, NULL,
-+ g_cclosure_marshal_VOID__BOOLEAN, G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
-+
-+ gst_video_connector_signals[SIGNAL_CONNECTION_FAILED] =
-+ g_signal_new ("connection-failed", G_TYPE_FROM_CLASS (klass),
-+ G_SIGNAL_RUN_LAST,
-+ 0, NULL, NULL,
-+ g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
-+
-+ GST_DEBUG_CATEGORY_INIT(video_connector_debug, "video-connector", 0,
-+ "An identity like element for reconnecting video stream");
-+
-+}
-+
-+#else
-
- static void
- gst_video_connector_base_init (gpointer g_class)
-@@ -120,18 +187,33 @@ gst_video_connector_class_init (GstVideoConnectorClass * klass)
- g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
- }
-
-+#endif
-+
- static void
--gst_video_connector_init (GstVideoConnector *element,
-- GstVideoConnectorClass *g_class)
-+gst_video_connector_init (GstVideoConnector *element
-+#if GST_CHECK_VERSION(1,0,0)
-+#else
-+ ,GstVideoConnectorClass *g_class
-+#endif
-+ )
- {
-+#if GST_CHECK_VERSION(1,0,0)
-+#else
- (void) g_class;
-+#endif
- element->sinkpad =
- gst_pad_new_from_static_template (&gst_video_connector_sink_factory,
- "sink");
- gst_pad_set_chain_function(element->sinkpad,
- GST_DEBUG_FUNCPTR (gst_video_connector_chain));
-+#if GST_CHECK_VERSION(1,0,0)
-+ /* gstreamer 1.x uses QUERIES and EVENTS for allocation and caps handiling purposes */
-+ GST_OBJECT_FLAG_SET (element->sinkpad, GST_PAD_FLAG_PROXY_CAPS);
-+ GST_OBJECT_FLAG_SET (element->sinkpad, GST_PAD_FLAG_PROXY_ALLOCATION);
-+#else
- gst_pad_set_event_function(element->sinkpad,
- GST_DEBUG_FUNCPTR (gst_video_connector_handle_sink_event));
-+
- gst_pad_set_bufferalloc_function(element->sinkpad,
- GST_DEBUG_FUNCPTR (gst_video_connector_buffer_alloc));
- gst_pad_set_setcaps_function(element->sinkpad,
-@@ -140,14 +222,23 @@ gst_video_connector_init (GstVideoConnector *element,
- GST_DEBUG_FUNCPTR(gst_video_connector_getcaps));
- gst_pad_set_acceptcaps_function(element->sinkpad,
- GST_DEBUG_FUNCPTR(gst_video_connector_acceptcaps));
--
-+#endif
- gst_element_add_pad (GST_ELEMENT (element), element->sinkpad);
-
- element->srcpad =
- gst_pad_new_from_static_template (&gst_video_connector_src_factory,
- "src");
-+#if GST_CHECK_VERSION(1,0,0)
-+ gst_pad_add_probe(element->srcpad, GST_PAD_PROBE_TYPE_BUFFER,
-+ gst_video_connector_new_buffer_probe, element, NULL);
-+ gst_pad_add_probe(element->srcpad, GST_PAD_PROBE_TYPE_QUERY_DOWNSTREAM,
-+ gst_video_connector_new_query_probe, element, NULL);
-+ gst_pad_add_probe(element->sinkpad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM,
-+ gst_video_connector_new_event_probe, element, NULL);
-+#else
- gst_pad_add_buffer_probe(element->srcpad,
- G_CALLBACK(gst_video_connector_new_buffer_probe), element);
-+#endif
- gst_element_add_pad (GST_ELEMENT (element), element->srcpad);
-
- element->relinked = FALSE;
-@@ -175,9 +266,16 @@ gst_video_connector_dispose (GObject * object)
-
- gst_video_connector_reset (element);
-
-+#if GST_CHECK_VERSION(1,0,0)
-+ G_OBJECT_CLASS (gst_video_connector_parent_class)->dispose (object);
-+#else
- G_OBJECT_CLASS (parent_class)->dispose (object);
-+#endif
- }
-
-+#if GST_CHECK_VERSION(1,0,0)
-+/* For gstreamer 1.x we handle it in ALLOCATION Query */
-+#else
- // "When this function returns anything else than GST_FLOW_OK,
- // the buffer allocation failed and buf does not contain valid data."
- static GstFlowReturn
-@@ -221,6 +319,7 @@ gst_video_connector_buffer_alloc (GstPad * pad, guint64 offset, guint size,
- if (state == GST_STATE_NULL) {
- GST_DEBUG_OBJECT (element, "Downstream element is in NULL state");
- // Downstream filter seems to be in the wrong state
-+
- return GST_FLOW_UNEXPECTED;
- }
- }
-@@ -293,6 +392,7 @@ static GstCaps *gst_video_connector_getcaps (GstPad * pad)
- return caps;
- }
-
-+
- static gboolean gst_video_connector_acceptcaps (GstPad * pad, GstCaps * caps)
- {
- GstVideoConnector *element;
-@@ -300,6 +400,7 @@ static gboolean gst_video_connector_acceptcaps (GstPad * pad, GstCaps * caps)
-
- return gst_pad_peer_accept_caps(element->srcpad, caps);
- }
-+#endif
-
- static void
- gst_video_connector_resend_new_segment(GstElement * element, gboolean emitFailedSignal)
-@@ -311,11 +412,39 @@ gst_video_connector_resend_new_segment(GstElement * element, gboolean emitFailed
- connector->failedSignalEmited = FALSE;
- }
-
-+#if GST_CHECK_VERSION(1,0,0)
-+static GstPadProbeReturn gst_video_connector_new_event_probe(GstPad *pad, GstPadProbeInfo *info, gpointer object)
-+{
-+ GstVideoConnector *connector = GST_VIDEO_CONNECTOR (object);
-+ GstEvent *event = gst_pad_probe_info_get_event(info);
-+
-+ GST_DEBUG_OBJECT(connector, "Event %"GST_PTR_FORMAT" received\n", event);
-+
-+ return GST_PAD_PROBE_OK;
-+}
-+
-+static GstPadProbeReturn gst_video_connector_new_query_probe(GstPad *pad, GstPadProbeInfo *info, gpointer object)
-+{
-+ GstVideoConnector *connector = GST_VIDEO_CONNECTOR (object);
-+ GstQuery *query = gst_pad_probe_info_get_query(info);
-+
-+ GST_DEBUG_OBJECT(connector, "Query %"GST_PTR_FORMAT" received\n", query);
-+
-+ return GST_PAD_PROBE_OK;
-+}
-+#endif
-
-+#if GST_CHECK_VERSION(1,0,0)
-+static GstPadProbeReturn gst_video_connector_new_buffer_probe(GstPad *pad, GstPadProbeInfo *info, gpointer object)
-+{
-+ (void) info;
-+#else
- static gboolean gst_video_connector_new_buffer_probe(GstObject *pad, GstBuffer *buffer, guint * object)
- {
-- (void) pad;
- (void) buffer;
-+#endif
-+ (void) pad;
-+
-
- GstVideoConnector *element = GST_VIDEO_CONNECTOR (object);
-
-@@ -327,16 +456,23 @@ static gboolean gst_video_connector_new_buffer_probe(GstObject *pad, GstBuffer *
- if (element->relinked)
- GST_LOG_OBJECT(element, "rejected buffer because of new segment request");
-
-- return !element->relinked;
-+ return element->relinked ? GST_PAD_PROBE_DROP : GST_PAD_PROBE_OK;
- }
-
--
- static GstFlowReturn
-+#if GST_CHECK_VERSION(1,0,0)
-+gst_video_connector_chain (GstPad * pad, GstObject* parent, GstBuffer * buf)
-+#else
- gst_video_connector_chain (GstPad * pad, GstBuffer * buf)
-+#endif
- {
- GstFlowReturn res;
- GstVideoConnector *element;
-
-+#if GST_CHECK_VERSION(1,0,0)
-+ (void)parent;
-+#endif
-+
- element = GST_VIDEO_CONNECTOR (gst_pad_get_parent (pad));
-
- do {
-@@ -348,20 +484,29 @@ gst_video_connector_chain (GstPad * pad, GstBuffer * buf)
- */
- while (element->relinked) {
- element->relinked = FALSE;
--
-+#if GST_CHECK_VERSION(1,0,0)
-+ if (element->latest_buffer && GST_BUFFER_TIMESTAMP_IS_VALID(element->latest_buffer)) {
-+ element->segment.position = GST_BUFFER_TIMESTAMP (element->latest_buffer);
-+ }
-+#else
- gint64 pos = element->segment.last_stop;
--
- if (element->latest_buffer && GST_BUFFER_TIMESTAMP_IS_VALID(element->latest_buffer)) {
- pos = GST_BUFFER_TIMESTAMP (element->latest_buffer);
- }
-+#endif
-
- //push a new segment and last buffer
-+#if GST_CHECK_VERSION(1,0,0)
-+ GstEvent *ev = gst_event_new_segment (&element->segment);
-+
-+#else
- GstEvent *ev = gst_event_new_new_segment (TRUE,
- element->segment.rate,
- element->segment.format,
- pos, //start
- element->segment.stop,
- pos);
-+#endif
-
- GST_DEBUG_OBJECT (element, "Pushing new segment event");
- if (!gst_pad_push_event (element->srcpad, ev)) {
-@@ -424,8 +569,11 @@ gst_video_connector_change_state (GstElement * element,
- GstStateChangeReturn result;
-
- connector = GST_VIDEO_CONNECTOR(element);
-+#if GST_CHECK_VERSION(1,0,0)
-+ result = GST_ELEMENT_CLASS (gst_video_connector_parent_class)->change_state(element, transition);
-+#else
- result = GST_ELEMENT_CLASS (parent_class)->change_state(element, transition);
--
-+#endif
- switch (transition) {
- case GST_STATE_CHANGE_PAUSED_TO_READY:
- gst_video_connector_reset (connector);
-@@ -440,9 +588,32 @@ gst_video_connector_change_state (GstElement * element,
- return result;
- }
-
--static gboolean
--gst_video_connector_handle_sink_event (GstPad * pad, GstEvent * event)
-+#if GST_CHECK_VERSION(1,0,0)
-+static gboolean gst_video_connector_handle_sink_event (GstPad * pad, GstObject* parent,
-+ GstEvent * event)
-+{
-+ GstVideoConnector *element = GST_VIDEO_CONNECTOR (gst_pad_get_parent (pad));
-+
-+ switch (GST_EVENT_TYPE (event)) {
-+ case GST_EVENT_SEGMENT:
-+ break;
-+ case GST_EVENT_CAPS:
-+ break;
-+ default:
-+ break;
-+ }
-+
-+ gst_object_unref (element);
-+ return gst_pad_event_default (pad, parent, event);
-+}
-+
-+#else
-+
-+static gboolean gst_video_connector_handle_sink_event (GstPad * pad,
-+ GstEvent * event)
- {
-+ (void)parent;
-+
- if (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT) {
- GstVideoConnector *element = GST_VIDEO_CONNECTOR (gst_pad_get_parent (pad));
-
-@@ -453,7 +624,6 @@ gst_video_connector_handle_sink_event (GstPad * pad, GstEvent * event)
-
- gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
- &start, &stop, &time);
--
- GST_LOG_OBJECT (element,
- "NEWSEGMENT update %d, rate %lf, applied rate %lf, "
- "format %d, " "%" G_GINT64_FORMAT " -- %" G_GINT64_FORMAT ", time %"
-@@ -461,9 +631,10 @@ gst_video_connector_handle_sink_event (GstPad * pad, GstEvent * event)
-
- gst_segment_set_newsegment_full (&element->segment, update,
- rate, arate, format, start, stop, time);
--
- gst_object_unref (element);
- }
-
- return gst_pad_event_default (pad, event);
- }
-+
-+#endif
-diff --git a/src/gsttools/qgstappsrc.cpp b/src/gsttools/qgstappsrc.cpp
-index 561a96f..d5e106f 100644
---- a/src/gsttools/qgstappsrc.cpp
-+++ b/src/gsttools/qgstappsrc.cpp
-@@ -147,23 +147,44 @@ void QGstAppSrc::pushDataToAppSrc()
- size = qMin(m_stream->bytesAvailable(), (qint64)m_dataRequestSize);
-
- if (size) {
-- void *data = g_malloc(size);
-- GstBuffer* buffer = gst_app_buffer_new(data, size, g_free, data);
-+ GstBuffer* buffer = gst_buffer_new_and_alloc(size);
-+
-+#if GST_CHECK_VERSION(1,0,0)
-+ GstMapInfo mapInfo;
-+ gst_buffer_map(buffer, &mapInfo, GST_MAP_WRITE);
-+ void* bufferData = mapInfo.data;
-+#else
-+ void* bufferData = GST_BUFFER_DATA(buffer);
-+#endif
-+
- buffer->offset = m_stream->pos();
-- qint64 bytesRead = m_stream->read((char*)GST_BUFFER_DATA(buffer), size);
-+ qint64 bytesRead = m_stream->read((char*)bufferData, size);
- buffer->offset_end = buffer->offset + bytesRead - 1;
-
-+#if GST_CHECK_VERSION(1,0,0)
-+ gst_buffer_unmap(buffer, &mapInfo);
-+#endif
-+
- if (bytesRead > 0) {
- m_dataRequested = false;
- m_enoughData = false;
- GstFlowReturn ret = gst_app_src_push_buffer (GST_APP_SRC (element()), buffer);
- if (ret == GST_FLOW_ERROR) {
- qWarning()<<"appsrc: push buffer error";
-+#if GST_CHECK_VERSION(1,0,0)
-+ } else if (ret == GST_FLOW_FLUSHING) {
-+ qWarning()<<"appsrc: push buffer wrong state";
-+ }
-+#else
- } else if (ret == GST_FLOW_WRONG_STATE) {
- qWarning()<<"appsrc: push buffer wrong state";
-- } else if (ret == GST_FLOW_RESEND) {
-+ }
-+#endif
-+#if GST_VERSION_MAJOR < 1
-+ else if (ret == GST_FLOW_RESEND) {
- qWarning()<<"appsrc: push buffer resend";
- }
-+#endif
- }
- } else {
- sendEOS();
-diff --git a/src/gsttools/qgstreameraudioprobecontrol.cpp b/src/gsttools/qgstreameraudioprobecontrol.cpp
-index 3baca53..be3de3f 100644
---- a/src/gsttools/qgstreameraudioprobecontrol.cpp
-+++ b/src/gsttools/qgstreameraudioprobecontrol.cpp
-@@ -45,9 +45,14 @@ QGstreamerAudioProbeControl::~QGstreamerAudioProbeControl()
-
- }
-
-+#if GST_CHECK_VERSION(1,0,0)
-+void QGstreamerAudioProbeControl::bufferProbed(GstBuffer* buffer, GstCaps* caps)
-+{
-+#else
- void QGstreamerAudioProbeControl::bufferProbed(GstBuffer* buffer)
- {
-- GstCaps* caps = gst_buffer_get_caps(buffer);
-+ gst_buffer_get_caps(buffer);
-+#endif
- if (!caps)
- return;
-
-@@ -56,8 +61,20 @@ void QGstreamerAudioProbeControl::bufferProbed(GstBuffer* buffer)
- if (!format.isValid())
- return;
-
-+ #if GST_CHECK_VERSION(1,0,0)
-+
-+ GstMapInfo info;
-+
-+ gst_buffer_map (buffer, &info, GST_MAP_READ);
-+ QAudioBuffer audioBuffer = QAudioBuffer(QByteArray((const char*)info.data, info.size), format);
-+ gst_buffer_unmap(buffer, &info);
-+
-+ #else
-+
- QAudioBuffer audioBuffer = QAudioBuffer(QByteArray((const char*)buffer->data, buffer->size), format);
-
-+ #endif
-+
- {
- QMutexLocker locker(&m_bufferMutex);
- m_pendingBuffer = audioBuffer;
-diff --git a/src/gsttools/qgstreamerbushelper.cpp b/src/gsttools/qgstreamerbushelper.cpp
-index 84eda46..eb1fc36 100644
---- a/src/gsttools/qgstreamerbushelper.cpp
-+++ b/src/gsttools/qgstreamerbushelper.cpp
-@@ -154,13 +154,21 @@ QGstreamerBusHelper::QGstreamerBusHelper(GstBus* bus, QObject* parent):
- QObject(parent)
- {
- d = new QGstreamerBusHelperPrivate(this, bus);
-+#if GST_CHECK_VERSION(1,0,0)
-+ gst_bus_set_sync_handler(bus, (GstBusSyncHandler)syncGstBusFilter, d, 0);
-+#else
- gst_bus_set_sync_handler(bus, (GstBusSyncHandler)syncGstBusFilter, d);
-+#endif
- gst_object_ref(GST_OBJECT(bus));
- }
-
- QGstreamerBusHelper::~QGstreamerBusHelper()
- {
-+#if GST_CHECK_VERSION(1,0,0)
-+ gst_bus_set_sync_handler(d->bus(), 0, 0, 0);
-+#else
- gst_bus_set_sync_handler(d->bus(),0,0);
-+#endif
- gst_object_unref(GST_OBJECT(d->bus()));
- }
-
-diff --git a/src/gsttools/qgstreamervideoprobecontrol.cpp b/src/gsttools/qgstreamervideoprobecontrol.cpp
-index a78a9da..9c31140 100644
---- a/src/gsttools/qgstreamervideoprobecontrol.cpp
-+++ b/src/gsttools/qgstreamervideoprobecontrol.cpp
-@@ -67,12 +67,21 @@ void QGstreamerVideoProbeControl::stopFlushing()
- m_flushing = false;
- }
-
-+#if GST_CHECK_VERSION(1,0,0)
-+void QGstreamerVideoProbeControl::bufferProbed(GstBuffer* buffer, GstCaps* caps)
-+#else
- void QGstreamerVideoProbeControl::bufferProbed(GstBuffer* buffer)
-+#endif
- {
- if (m_flushing)
- return;
-
-+#if GST_CHECK_VERSION(1,0,0)
-+ // FIXME:
-+ // GstCaps* caps = NULL;//gst_buffer_get_caps(buffer);
-+#else
- GstCaps* caps = gst_buffer_get_caps(buffer);
-+#endif
- if (!caps)
- return;
-
-diff --git a/src/gsttools/qgstreamervideorenderer.cpp b/src/gsttools/qgstreamervideorenderer.cpp
-index 2b66f76..804dce9 100644
---- a/src/gsttools/qgstreamervideorenderer.cpp
-+++ b/src/gsttools/qgstreamervideorenderer.cpp
-@@ -35,8 +35,7 @@
- #include <private/qvideosurfacegstsink_p.h>
- #include <private/qgstutils_p.h>
- #include <qabstractvideosurface.h>
--
--#include <QDebug>
-+#include <QtCore/qdebug.h>
-
- #include <gst/gst.h>
-
-diff --git a/src/gsttools/qgstreamervideowidget.cpp b/src/gsttools/qgstreamervideowidget.cpp
-index aa2e2a3..14c1f04 100644
---- a/src/gsttools/qgstreamervideowidget.cpp
-+++ b/src/gsttools/qgstreamervideowidget.cpp
-@@ -40,8 +40,13 @@
- #include <QtGui/qpainter.h>
-
- #include <gst/gst.h>
-+
-+#if !GST_CHECK_VERSION(1,0,0)
- #include <gst/interfaces/xoverlay.h>
- #include <gst/interfaces/propertyprobe.h>
-+#else
-+#include <gst/video/videooverlay.h>
-+#endif
-
- QT_BEGIN_NAMESPACE
-
-@@ -169,9 +174,13 @@ bool QGstreamerVideoWidgetControl::processSyncMessage(const QGstreamerMessage &m
- {
- 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;
-@@ -199,18 +208,29 @@ bool QGstreamerVideoWidgetControl::processBusMessage(const QGstreamerMessage &me
-
- void QGstreamerVideoWidgetControl::setOverlay()
- {
-+#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);
-+ }
-+#endif
- }
-
- void QGstreamerVideoWidgetControl::updateNativeVideoSize()
- {
- if (m_videoSink) {
- //find video native size to update video widget size hint
-- GstPad *pad = gst_element_get_static_pad(m_videoSink,"sink");
-+ GstPad *pad = gst_element_get_static_pad(m_videoSink, "sink");
-+#if !GST_CHECK_VERSION(1,0,0)
- GstCaps *caps = gst_pad_get_negotiated_caps(pad);
- gst_object_unref(GST_OBJECT(pad));
-+#else
-+ GstCaps *caps = gst_pad_get_current_caps(pad);
-+ gst_object_unref(GST_OBJECT(pad));
-+#endif
-
- if (caps) {
- m_widget->setNativeSize(QGstUtils::capsCorrectedResolution(caps));
-@@ -225,8 +245,13 @@ void QGstreamerVideoWidgetControl::updateNativeVideoSize()
-
- void QGstreamerVideoWidgetControl::windowExposed()
- {
-+#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
- }
-
- QWidget *QGstreamerVideoWidgetControl::videoWidget()
-diff --git a/src/gsttools/qgstreamervideowindow.cpp b/src/gsttools/qgstreamervideowindow.cpp
-index a373dcc..587b010 100644
---- a/src/gsttools/qgstreamervideowindow.cpp
-+++ b/src/gsttools/qgstreamervideowindow.cpp
-@@ -37,8 +37,12 @@
- #include <QtCore/qdebug.h>
-
- #include <gst/gst.h>
-+#include <gst/video/videooverlay.h>
-+
-+#if !GST_CHECK_VERSION(1,0,0)
- #include <gst/interfaces/xoverlay.h>
- #include <gst/interfaces/propertyprobe.h>
-+#endif
-
-
- QGstreamerVideoWindow::QGstreamerVideoWindow(QObject *parent, const char *elementName)
-@@ -49,18 +53,25 @@ QGstreamerVideoWindow::QGstreamerVideoWindow(QObject *parent, const char *elemen
- , m_fullScreen(false)
- , m_colorKey(QColor::Invalid)
- {
-- if (elementName)
-+ if (elementName) {
- m_videoSink = gst_element_factory_make(elementName, NULL);
-- else
-+ } else {
- 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");
-+#if GST_CHECK_VERSION(1,0,0)
-+ m_bufferProbeId = gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_BUFFER, padBufferProbe, this, NULL);
-+#else
- m_bufferProbeId = gst_pad_add_buffer_probe(pad, G_CALLBACK(padBufferProbe), this);
-+#endif
- gst_object_unref(GST_OBJECT(pad));
- }
-+ else
-+ qDebug() << "No m_videoSink available!";
- }
-
- QGstreamerVideoWindow::~QGstreamerVideoWindow()
-@@ -82,11 +93,15 @@ void QGstreamerVideoWindow::setWinId(WId id)
- WId oldId = m_windowId;
-
- 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);
-
-@@ -97,7 +112,20 @@ 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);
-
-+ GstPad *pad = gst_element_get_static_pad(m_videoSink,"sink");
-+ m_bufferProbeId = gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_BUFFER, padBufferProbe, this, NULL);
-+
-+ 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)) {
-@@ -110,7 +138,7 @@ bool QGstreamerVideoWindow::processSyncMessage(const QGstreamerMessage &message)
-
- return true;
- }
--
-+#endif
- return false;
- }
-
-@@ -122,7 +150,19 @@ 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())
-@@ -136,6 +176,7 @@ void QGstreamerVideoWindow::setDisplayRect(const QRect &rect)
- repaint();
- #endif
- }
-+#endif
- }
-
- Qt::AspectRatioMode QGstreamerVideoWindow::aspectRatioMode() const
-@@ -157,6 +198,16 @@ void QGstreamerVideoWindow::setAspectRatioMode(Qt::AspectRatioMode 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;
-@@ -165,6 +216,7 @@ void QGstreamerVideoWindow::repaint()
- gst_x_overlay_expose(GST_X_OVERLAY(m_videoSink));
- }
- }
-+#endif
- }
-
- QColor QGstreamerVideoWindow::colorKey() const
-@@ -296,11 +348,22 @@ QSize QGstreamerVideoWindow::nativeSize() const
- return m_nativeSize;
- }
-
-+#if GST_CHECK_VERSION(1,0,0)
-+GstPadProbeReturn QGstreamerVideoWindow::padBufferProbe(GstPad *pad, GstPadProbeInfo *info, gpointer user_data)
-+#else
- void QGstreamerVideoWindow::padBufferProbe(GstPad *pad, GstBuffer * /* buffer */, gpointer user_data)
-+#endif
- {
- QGstreamerVideoWindow *control = reinterpret_cast<QGstreamerVideoWindow*>(user_data);
- QMetaObject::invokeMethod(control, "updateNativeVideoSize", Qt::QueuedConnection);
-+
-+#if GST_CHECK_VERSION(1,0,0)
-+ Q_UNUSED(pad);
-+ Q_UNUSED(info);
-+ return GST_PAD_PROBE_REMOVE;
-+#else
- gst_pad_remove_buffer_probe(pad, control->m_bufferProbeId);
-+#endif
- }
-
- void QGstreamerVideoWindow::updateNativeVideoSize()
-@@ -311,7 +374,11 @@ void QGstreamerVideoWindow::updateNativeVideoSize()
- if (m_videoSink) {
- //find video native size to update video widget size hint
- GstPad *pad = gst_element_get_static_pad(m_videoSink,"sink");
-+#if GST_CHECK_VERSION(1,0,0)
-+ GstCaps *caps = gst_pad_get_current_caps(pad);
-+#else
- GstCaps *caps = gst_pad_get_negotiated_caps(pad);
-+#endif
- gst_object_unref(GST_OBJECT(pad));
-
- if (caps) {
-diff --git a/src/gsttools/qgstutils.cpp b/src/gsttools/qgstutils.cpp
-index 556fc03..5ea2c59 100644
---- a/src/gsttools/qgstutils.cpp
-+++ b/src/gsttools/qgstutils.cpp
-@@ -89,8 +89,13 @@ static void addTagToMap(const GstTagList *list,
- break;
- default:
- // GST_TYPE_DATE is a function, not a constant, so pull it out of the switch
-+#if GST_CHECK_VERSION(1,0,0)
-+ if (G_VALUE_TYPE(&val) == G_TYPE_DATE) {
-+ const GDate *date = (const GDate *)g_value_get_boxed(&val);
-+#else
- if (G_VALUE_TYPE(&val) == GST_TYPE_DATE) {
- const GDate *date = gst_value_get_date(&val);
-+#endif
- if (g_date_valid(date)) {
- int year = g_date_get_year(date);
- int month = g_date_get_month(date);
-@@ -254,6 +259,24 @@ QAudioFormat QGstUtils::audioFormatForCaps(const GstCaps *caps)
- }
-
-
-+
-+#if GST_CHECK_VERSION(1,0,0)
-+/*!
-+ Returns audio format for a buffer.
-+ If the buffer doesn't have a valid audio format, an empty QAudioFormat is returned.
-+*/
-+
-+QAudioFormat QGstUtils::audioFormatForSample(GstSample *sample)
-+{
-+ GstCaps* caps = gst_sample_get_caps(sample);
-+ if (!caps)
-+ return QAudioFormat();
-+
-+ QAudioFormat format = QGstUtils::audioFormatForCaps(caps);
-+ gst_caps_unref(caps);
-+ return format;
-+}
-+#else
- /*!
- Returns audio format for a buffer.
- If the buffer doesn't have a valid audio format, an empty QAudioFormat is returned.
-@@ -269,7 +292,7 @@ QAudioFormat QGstUtils::audioFormatForBuffer(GstBuffer *buffer)
- gst_caps_unref(caps);
- return format;
- }
--
-+#endif
-
- /*!
- Builds GstCaps for an audio format.
-@@ -579,7 +602,7 @@ QByteArray QGstUtils::cameraDriver(const QString &device, GstElementFactory *fac
-
- void qt_gst_object_ref_sink(gpointer object)
- {
--#if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 24)
-+#if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 24) || GST_CHECK_VERSION(1,0,0)
- gst_object_ref_sink(object);
- #else
- g_return_if_fail (GST_IS_OBJECT(object));
-diff --git a/src/gsttools/qgstvideobuffer.cpp b/src/gsttools/qgstvideobuffer.cpp
-index 18702ec..93f22f5 100644
---- a/src/gsttools/qgstvideobuffer.cpp
-+++ b/src/gsttools/qgstvideobuffer.cpp
-@@ -70,21 +70,33 @@ QAbstractVideoBuffer::MapMode QGstVideoBuffer::mapMode() const
- uchar *QGstVideoBuffer::map(MapMode mode, int *numBytes, int *bytesPerLine)
- {
- if (mode != NotMapped && m_mode == NotMapped) {
-- if (numBytes)
-- *numBytes = m_buffer->size;
-+ m_mode = mode;
-
- if (bytesPerLine)
- *bytesPerLine = m_bytesPerLine;
-
-- m_mode = mode;
-+#if GST_CHECK_VERSION(1,0,0)
-+ gst_buffer_map(m_buffer, &m_mapInfo, GST_MAP_READ);
-+ if (numBytes)
-+ *numBytes = m_mapInfo.size;
-+
-+ return m_mapInfo.data;
-+#else
-+ if (numBytes)
-+ *numBytes = m_buffer->size;
-
- return m_buffer->data;
-+#endif
- } else {
- return 0;
- }
- }
- void QGstVideoBuffer::unmap()
- {
-+#if GST_CHECK_VERSION(1,0,0)
-+ if (m_mode != NotMapped)
-+ gst_buffer_unmap(m_buffer, &m_mapInfo);
-+#endif
- m_mode = NotMapped;
- }
-
-diff --git a/src/gsttools/qvideosurfacegstsink.cpp b/src/gsttools/qvideosurfacegstsink.cpp
-index f3e2d88..a964e82 100644
---- a/src/gsttools/qvideosurfacegstsink.cpp
-+++ b/src/gsttools/qvideosurfacegstsink.cpp
-@@ -43,7 +43,11 @@
-
- #include "qvideosurfacegstsink_p.h"
-
--//#define DEBUG_VIDEO_SURFACE_SINK
-+#if GST_VERSION_MAJOR >=1
-+#include <gst/video/video.h>
-+#endif
-+
-+#define DEBUG_VIDEO_SURFACE_SINK
-
- QT_BEGIN_NAMESPACE
-
-@@ -62,10 +66,12 @@ QVideoSurfaceGstDelegate::QVideoSurfaceGstDelegate(
- if (m_surface) {
- foreach (QObject *instance, bufferPoolLoader()->instances(QGstBufferPoolPluginKey)) {
- QGstBufferPoolInterface* plugin = qobject_cast<QGstBufferPoolInterface*>(instance);
-+
- if (plugin) {
- m_pools.append(plugin);
- }
- }
-+
- updateSupportedFormats();
- connect(m_surface, SIGNAL(supportedFormatsChanged()), this, SLOT(updateSupportedFormats()));
- }
-@@ -198,6 +204,8 @@ GstFlowReturn QVideoSurfaceGstDelegate::render(GstBuffer *buffer)
- if (QThread::currentThread() == thread()) {
- if (!m_surface.isNull())
- m_surface->present(m_frame);
-+ else
-+ qWarning() << "m_surface.isNull().";
- } else {
- QMetaObject::invokeMethod(this, "queuedRender", Qt::QueuedConnection);
- m_renderCondition.wait(&m_mutex, 300);
-@@ -283,6 +291,27 @@ void QVideoSurfaceGstDelegate::updateSupportedFormats()
- }
- }
-
-+#if GST_CHECK_VERSION(1,0,0)
-+struct YuvFormat
-+{
-+ QVideoFrame::PixelFormat pixelFormat;
-+ GstVideoFormat vfmt;
-+ guint32 fourcc;
-+ int bitsPerPixel;
-+};
-+
-+static const YuvFormat qt_yuvColorLookup[] =
-+{
-+ { QVideoFrame::Format_YUV420P, GST_VIDEO_FORMAT_I420, GST_MAKE_FOURCC('I','4','2','0'), 8 },
-+ { QVideoFrame::Format_YV12, GST_VIDEO_FORMAT_YV12, GST_MAKE_FOURCC('Y','V','1','2'), 8 },
-+ { QVideoFrame::Format_UYVY, GST_VIDEO_FORMAT_UYVY, GST_MAKE_FOURCC('U','Y','V','Y'), 16 },
-+ { QVideoFrame::Format_YUYV, GST_VIDEO_FORMAT_YUY2, GST_MAKE_FOURCC('Y','U','Y','2'), 16 },
-+ { QVideoFrame::Format_NV12, GST_VIDEO_FORMAT_NV12, GST_MAKE_FOURCC('N','V','1','2'), 8 },
-+ { QVideoFrame::Format_NV21, GST_VIDEO_FORMAT_NV21, GST_MAKE_FOURCC('N','V','2','1'), 8 },
-+ { QVideoFrame::Format_AYUV444, GST_VIDEO_FORMAT_AYUV, GST_MAKE_FOURCC('A','Y','U','V'), 32 },
-+};
-+
-+#else
- struct YuvFormat
- {
- QVideoFrame::PixelFormat pixelFormat;
-@@ -300,6 +329,7 @@ static const YuvFormat qt_yuvColorLookup[] =
- { QVideoFrame::Format_NV21, GST_MAKE_FOURCC('N','V','2','1'), 8 },
- { QVideoFrame::Format_AYUV444, GST_MAKE_FOURCC('A','Y','U','V'), 32 }
- };
-+#endif
-
- static int indexOfYuvColor(QVideoFrame::PixelFormat format)
- {
-@@ -312,12 +342,20 @@ static int indexOfYuvColor(QVideoFrame::PixelFormat format)
- return -1;
- }
-
-+#if GST_VERSION_MAJOR >=1
-+static int indexOfYuvColor(GstVideoFormat vfmt)
-+#else
- static int indexOfYuvColor(guint32 fourcc)
-+#endif
- {
- const int count = sizeof(qt_yuvColorLookup) / sizeof(YuvFormat);
-
- for (int i = 0; i < count; ++i)
-+#if GST_VERSION_MAJOR >=1
-+ if (qt_yuvColorLookup[i].vfmt == vfmt)
-+#else
- if (qt_yuvColorLookup[i].fourcc == fourcc)
-+#endif
- return i;
-
- return -1;
-@@ -388,13 +426,13 @@ GType QVideoSurfaceGstSink::get_type()
- if (type == 0) {
- static const GTypeInfo info =
- {
-- sizeof(QVideoSurfaceGstSinkClass), // class_size
-+ sizeof(QVideoSurfaceGstSinkClass), // class_size
- base_init, // base_init
- NULL, // base_finalize
- class_init, // class_init
- NULL, // class_finalize
- NULL, // class_data
-- sizeof(QVideoSurfaceGstSink), // instance_size
-+ sizeof(QVideoSurfaceGstSink), // instance_size
- 0, // n_preallocs
- instance_init, // instance_init
- 0 // value_table
-@@ -419,7 +457,11 @@ void QVideoSurfaceGstSink::class_init(gpointer g_class, gpointer class_data)
- GstBaseSinkClass *base_sink_class = reinterpret_cast<GstBaseSinkClass *>(g_class);
- base_sink_class->get_caps = QVideoSurfaceGstSink::get_caps;
- base_sink_class->set_caps = QVideoSurfaceGstSink::set_caps;
-+// FIXME:
-+#if GST_CHECK_VERSION(1,0,0)
-+#else
- base_sink_class->buffer_alloc = QVideoSurfaceGstSink::buffer_alloc;
-+#endif
- base_sink_class->start = QVideoSurfaceGstSink::start;
- base_sink_class->stop = QVideoSurfaceGstSink::stop;
-
-@@ -434,6 +476,18 @@ void QVideoSurfaceGstSink::base_init(gpointer g_class)
- {
- static GstStaticPadTemplate sink_pad_template = GST_STATIC_PAD_TEMPLATE(
- "sink", GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS(
-+#if GST_CHECK_VERSION(1,0,0)
-+ "video/x-raw, "
-+ "format = (string) RGBA,"
-+ "framerate = (fraction) [ 0, MAX ], "
-+ "width = (int) [ 1, MAX ], "
-+ "height = (int) [ 1, MAX ]; "
-+ "video/x-raw, "
-+ "format = (string) I420,"
-+ "framerate = (fraction) [ 0, MAX ], "
-+ "width = (int) [ 1, MAX ], "
-+ "height = (int) [ 1, MAX ]"));
-+#else
- "video/x-raw-rgb, "
- "framerate = (fraction) [ 0, MAX ], "
- "width = (int) [ 1, MAX ], "
-@@ -442,6 +496,7 @@ void QVideoSurfaceGstSink::base_init(gpointer g_class)
- "framerate = (fraction) [ 0, MAX ], "
- "width = (int) [ 1, MAX ], "
- "height = (int) [ 1, MAX ]"));
-+#endif
-
- gst_element_class_add_pad_template(
- GST_ELEMENT_CLASS(g_class), gst_static_pad_template_get(&sink_pad_template));
-@@ -490,7 +545,11 @@ GstStateChangeReturn QVideoSurfaceGstSink::change_state(
- element, transition);
- }
-
--GstCaps *QVideoSurfaceGstSink::get_caps(GstBaseSink *base)
-+GstCaps *QVideoSurfaceGstSink::get_caps(GstBaseSink *base
-+#if GST_CHECK_VERSION(1,0,0)
-+ , GstCaps* /*filterCaps*/
-+#endif
-+)
- {
- VO_SINK(base);
-
-@@ -503,6 +562,7 @@ GstCaps *QVideoSurfaceGstSink::get_caps(GstBaseSink *base)
- QList<QVideoFrame::PixelFormat> poolHandleFormats;
- sink->delegate->poolMutex()->lock();
- QGstBufferPoolInterface *pool = sink->delegate->pool();
-+
- if (pool)
- poolHandleFormats = sink->delegate->supportedPixelFormats(pool->handleType());
- sink->delegate->poolMutex()->unlock();
-@@ -518,11 +578,19 @@ GstCaps *QVideoSurfaceGstSink::get_caps(GstBaseSink *base)
-
- if (index != -1) {
- gst_caps_append_structure(caps, gst_structure_new(
-+#if GST_CHECK_VERSION(1,0,0)
-+ "video/x-raw",
-+#else
- "video/x-raw-yuv",
-+#endif
- "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, INT_MAX, 1,
- "width" , GST_TYPE_INT_RANGE, 1, INT_MAX,
- "height" , GST_TYPE_INT_RANGE, 1, INT_MAX,
-- "format" , GST_TYPE_FOURCC, qt_yuvColorLookup[index].fourcc,
-+#if GST_CHECK_VERSION(1,0,0)
-+ "format" , G_TYPE_STRING, gst_video_format_to_string(qt_yuvColorLookup[index].vfmt),
-+#else
-+ "format" , GST_TYPE_FOURCC, qt_yuvColorLookup[index].fourcc,
-+#endif
- NULL));
- continue;
- }
-@@ -532,7 +600,18 @@ GstCaps *QVideoSurfaceGstSink::get_caps(GstBaseSink *base)
- for (int i = 0; i < count; ++i) {
- if (qt_rgbColorLookup[i].pixelFormat == format) {
- GstStructure *structure = gst_structure_new(
-+#if GST_CHECK_VERSION(1,0,0)
-+ "video/x-raw",
-+ "format" , G_TYPE_STRING, gst_video_format_to_string(gst_video_format_from_masks(qt_rgbColorLookup[i].depth,
-+ qt_rgbColorLookup[i].bitsPerPixel,
-+ qt_rgbColorLookup[i].endianness,
-+ qt_rgbColorLookup[i].red,
-+ qt_rgbColorLookup[i].green,
-+ qt_rgbColorLookup[i].blue,
-+ qt_rgbColorLookup[i].alpha)),
-+#else
- "video/x-raw-rgb",
-+#endif
- "framerate" , GST_TYPE_FRACTION_RANGE, 0, 1, INT_MAX, 1,
- "width" , GST_TYPE_INT_RANGE, 1, INT_MAX,
- "height" , GST_TYPE_INT_RANGE, 1, INT_MAX,
-@@ -553,6 +632,7 @@ GstCaps *QVideoSurfaceGstSink::get_caps(GstBaseSink *base)
- }
- }
-
-+// printf("get Caps %"GST_PTR_FORMAT"\n", caps);
- return caps;
- }
-
-@@ -592,7 +672,7 @@ gboolean QVideoSurfaceGstSink::set_caps(GstBaseSink *base, GstCaps *caps)
- sink->lastRequestedCaps = 0;
-
- #ifdef DEBUG_VIDEO_SURFACE_SINK
-- qDebug() << "Staring video surface, format:";
-+ qDebug() << "Starting video surface, format:";
- qDebug() << format;
- qDebug() << "bytesPerLine:" << bytesPerLine;
- #endif
-@@ -617,11 +697,49 @@ QVideoSurfaceFormat QVideoSurfaceGstSink::formatForCaps(GstCaps *caps, int *byte
- gst_structure_get_int(structure, "width", &size.rwidth());
- gst_structure_get_int(structure, "height", &size.rheight());
-
-+#if GST_CHECK_VERSION(1, 0, 0)
-+ GstVideoInfo info;
-+ gst_video_info_from_caps(&info, caps);
-+
-+ if (info.finfo->format == GST_VIDEO_FORMAT_I420) {
-+ int index = indexOfYuvColor(GST_VIDEO_FORMAT_I420);
-+
-+ if (index != -1) {
-+ pixelFormat = qt_yuvColorLookup[index].pixelFormat;
-+ bitsPerPixel = qt_yuvColorLookup[index].bitsPerPixel;
-+ }
-+ } else if (info.finfo->format == GST_VIDEO_FORMAT_RGBx) {
-+ int depth = 0;
-+ int endianness = 0;
-+ int red = 0;
-+ int green = 0;
-+ int blue = 0;
-+ int alpha = 0;
-+
-+ gst_structure_get_int(structure, "bpp", &bitsPerPixel);
-+ gst_structure_get_int(structure, "depth", &depth);
-+ gst_structure_get_int(structure, "endianness", &endianness);
-+ gst_structure_get_int(structure, "red_mask", &red);
-+ gst_structure_get_int(structure, "green_mask", &green);
-+ gst_structure_get_int(structure, "blue_mask", &blue);
-+ gst_structure_get_int(structure, "alpha_mask", &alpha);
-+
-+ int index = indexOfRgbColor(bitsPerPixel, depth, endianness, red, green, blue, alpha);
-+ printf("INDEX %x\n", index);
-+ if (index != -1)
-+ pixelFormat = qt_rgbColorLookup[index].pixelFormat;
-+ }
-+#else
-+
- if (qstrcmp(gst_structure_get_name(structure), "video/x-raw-yuv") == 0) {
- guint32 fourcc = 0;
-+#if GST_CHECK_VERSION(1, 0, 0)
-+ int index = indexOfYuvColor(gst_video_format_from_string(gst_structure_get_string(structure, "format")));
-+#else
- gst_structure_get_fourcc(structure, "format", &fourcc);
-
- int index = indexOfYuvColor(fourcc);
-+#endif
- if (index != -1) {
- pixelFormat = qt_yuvColorLookup[index].pixelFormat;
- bitsPerPixel = qt_yuvColorLookup[index].bitsPerPixel;
-@@ -647,6 +765,7 @@ QVideoSurfaceFormat QVideoSurfaceGstSink::formatForCaps(GstCaps *caps, int *byte
- if (index != -1)
- pixelFormat = qt_rgbColorLookup[index].pixelFormat;
- }
-+#endif
-
- if (pixelFormat != QVideoFrame::Format_Invalid) {
- QVideoSurfaceFormat format(size, pixelFormat, handleType);
-@@ -722,7 +841,11 @@ GstFlowReturn QVideoSurfaceGstSink::buffer_alloc(
-
- poolLock.unlock();
-
-+#if GST_CHECK_VERSION(1,0,0)
-+ GstCaps *intersection = gst_caps_intersect(get_caps(GST_BASE_SINK(sink), NULL), caps);
-+#else
- GstCaps *intersection = gst_caps_intersect(get_caps(GST_BASE_SINK(sink)), caps);
-+#endif
-
- if (gst_caps_is_empty (intersection)) {
- gst_caps_unref(intersection);
-@@ -763,7 +886,7 @@ GstFlowReturn QVideoSurfaceGstSink::buffer_alloc(
- QVideoSurfaceFormat surfaceFormat = sink->delegate->surfaceFormat();
-
- if (!pool->isFormatSupported(surfaceFormat)) {
-- //qDebug() << "sink doesn't support native pool format, skip custom buffers allocation";
-+ qDebug() << "sink doesn't support native pool format, skip custom buffers allocation";
- return GST_FLOW_OK;
- }
-
-@@ -787,7 +910,6 @@ GstFlowReturn QVideoSurfaceGstSink::buffer_alloc(
- gboolean QVideoSurfaceGstSink::start(GstBaseSink *base)
- {
- Q_UNUSED(base);
--
- return TRUE;
- }
-
-diff --git a/src/multimedia/gsttools_headers/qgstappsrc_p.h b/src/multimedia/gsttools_headers/qgstappsrc_p.h
-index 4af9252..0e0fc0a 100644
---- a/src/multimedia/gsttools_headers/qgstappsrc_p.h
-+++ b/src/multimedia/gsttools_headers/qgstappsrc_p.h
-@@ -39,7 +39,10 @@
-
- #include <gst/gst.h>
- #include <gst/app/gstappsrc.h>
-+
-+#if GST_VERSION_MAJOR < 1
- #include <gst/app/gstappbuffer.h>
-+#endif
-
- QT_BEGIN_NAMESPACE
-
-diff --git a/src/multimedia/gsttools_headers/qgstreameraudioprobecontrol_p.h b/src/multimedia/gsttools_headers/qgstreameraudioprobecontrol_p.h
-index 34669b8..0f3b165 100644
---- a/src/multimedia/gsttools_headers/qgstreameraudioprobecontrol_p.h
-+++ b/src/multimedia/gsttools_headers/qgstreameraudioprobecontrol_p.h
-@@ -47,8 +47,11 @@ class QGstreamerAudioProbeControl : public QMediaAudioProbeControl
- public:
- explicit QGstreamerAudioProbeControl(QObject *parent);
- virtual ~QGstreamerAudioProbeControl();
--
-+#if GST_CHECK_VERSION(1,0,0)
-+ void bufferProbed(GstBuffer* buffer, GstCaps* caps);
-+#else
- void bufferProbed(GstBuffer* buffer);
-+#endif
-
- private slots:
- void bufferProbed();
-diff --git a/src/multimedia/gsttools_headers/qgstreamervideoprobecontrol_p.h b/src/multimedia/gsttools_headers/qgstreamervideoprobecontrol_p.h
-index 49064f9..fce6309 100644
---- a/src/multimedia/gsttools_headers/qgstreamervideoprobecontrol_p.h
-+++ b/src/multimedia/gsttools_headers/qgstreamervideoprobecontrol_p.h
-@@ -48,7 +48,11 @@ public:
- explicit QGstreamerVideoProbeControl(QObject *parent);
- virtual ~QGstreamerVideoProbeControl();
-
-+#if GST_CHECK_VERSION(1,0,0)
-+ void bufferProbed(GstBuffer* buffer, GstCaps*);
-+#else
- void bufferProbed(GstBuffer* buffer);
-+#endif
- void startFlushing();
- void stopFlushing();
-
-diff --git a/src/multimedia/gsttools_headers/qgstreamervideowindow_p.h b/src/multimedia/gsttools_headers/qgstreamervideowindow_p.h
-index 81e5764..c9fdb5c 100644
---- a/src/multimedia/gsttools_headers/qgstreamervideowindow_p.h
-+++ b/src/multimedia/gsttools_headers/qgstreamervideowindow_p.h
-@@ -104,7 +104,11 @@ private slots:
- void updateNativeVideoSize();
-
- private:
-+#if GST_CHECK_VERSION(1,0,0)
-+ static GstPadProbeReturn padBufferProbe(GstPad *pad, GstPadProbeInfo *info, gpointer user_data);
-+#else
- static void padBufferProbe(GstPad *pad, GstBuffer *buffer, gpointer user_data);
-+#endif
-
- GstElement *m_videoSink;
- WId m_windowId;
-diff --git a/src/multimedia/gsttools_headers/qgstutils_p.h b/src/multimedia/gsttools_headers/qgstutils_p.h
-index 65ff759..6015980 100644
---- a/src/multimedia/gsttools_headers/qgstutils_p.h
-+++ b/src/multimedia/gsttools_headers/qgstutils_p.h
-@@ -73,7 +73,11 @@ namespace QGstUtils {
- QSize capsResolution(const GstCaps *caps);
- QSize capsCorrectedResolution(const GstCaps *caps);
- QAudioFormat audioFormatForCaps(const GstCaps *caps);
-+#if GST_CHECK_VERSION(1,0,0)
-+ QAudioFormat audioFormatForSample(GstSample *sample);
-+#else
- QAudioFormat audioFormatForBuffer(GstBuffer *buffer);
-+#endif
- GstCaps *capsForAudioFormat(QAudioFormat format);
- void initializeGst();
- QMultimedia::SupportEstimate hasSupport(const QString &mimeType,
-diff --git a/src/multimedia/gsttools_headers/qgstvideobuffer_p.h b/src/multimedia/gsttools_headers/qgstvideobuffer_p.h
-index 1e0fda8..be48820 100644
---- a/src/multimedia/gsttools_headers/qgstvideobuffer_p.h
-+++ b/src/multimedia/gsttools_headers/qgstvideobuffer_p.h
-@@ -71,6 +71,9 @@ private:
- int m_bytesPerLine;
- MapMode m_mode;
- QVariant m_handle;
-+#if GST_CHECK_VERSION(1,0,0)
-+ GstMapInfo m_mapInfo;
-+#endif
- };
-
- QT_END_NAMESPACE
-diff --git a/src/multimedia/gsttools_headers/qvideosurfacegstsink_p.h b/src/multimedia/gsttools_headers/qvideosurfacegstsink_p.h
-index 11b305d..01935f7 100644
---- a/src/multimedia/gsttools_headers/qvideosurfacegstsink_p.h
-+++ b/src/multimedia/gsttools_headers/qvideosurfacegstsink_p.h
-@@ -131,7 +131,11 @@ private:
-
- static GstStateChangeReturn change_state(GstElement *element, GstStateChange transition);
-
-- static GstCaps *get_caps(GstBaseSink *sink);
-+ static GstCaps *get_caps(GstBaseSink *sink
-+#if GST_CHECK_VERSION(1,0,0)
-+ , GstCaps* /*filterCaps*/
-+#endif
-+ );
- static gboolean set_caps(GstBaseSink *sink, GstCaps *caps);
-
- static GstFlowReturn buffer_alloc(
-diff --git a/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderserviceplugin.cpp b/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderserviceplugin.cpp
-index 3098aab..9c54663 100644
---- a/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderserviceplugin.cpp
-+++ b/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderserviceplugin.cpp
-@@ -74,29 +74,42 @@ void QGstreamerAudioDecoderServicePlugin::updateSupportedMimeTypes() const
- gst_init(NULL, NULL);
-
- GList *plugins, *orig_plugins;
-+#if GST_CHECK_VERSION(1,0,0)
-+ orig_plugins = plugins = gst_registry_get_plugin_list (gst_registry_get());
-+#else
- orig_plugins = plugins = gst_default_registry_get_plugin_list ();
--
-+#endif
- while (plugins) {
- GList *features, *orig_features;
-
- GstPlugin *plugin = (GstPlugin *) (plugins->data);
- plugins = g_list_next (plugins);
-
-+#if GST_CHECK_VERSION(1,0,0)
-+ if (GST_OBJECT_FLAG_IS_SET(plugin, GST_PLUGIN_FLAG_BLACKLISTED))
-+ continue;
-+#else
- if (plugin->flags & (1<<1)) //GST_PLUGIN_FLAG_BLACKLISTED
- continue;
--
-- orig_features = features = gst_registry_get_feature_list_by_plugin(gst_registry_get_default (),
-- plugin->desc.name);
-+#endif
-+ orig_features = features = gst_registry_get_feature_list_by_plugin(gst_registry_get (),
-+ gst_plugin_get_name(plugin));
- while (features) {
- if (!G_UNLIKELY(features->data == NULL)) {
- GstPluginFeature *feature = GST_PLUGIN_FEATURE(features->data);
- if (GST_IS_ELEMENT_FACTORY (feature)) {
- GstElementFactory *factory = GST_ELEMENT_FACTORY(gst_plugin_feature_load(feature));
- if (factory
-- && factory->numpadtemplates > 0
-+ && gst_element_factory_get_num_pad_templates(factory) > 0
-+#if GST_CHECK_VERSION(1,0,0)
-+ && (qstrcmp(gst_element_factory_get_metadata(factory, GST_ELEMENT_METADATA_KLASS), "Codec/Decoder/Audio") == 0
-+ || qstrcmp(gst_element_factory_get_metadata(factory, GST_ELEMENT_METADATA_KLASS), "Codec/Demux") == 0 )
-+#else
- && (qstrcmp(factory->details.klass, "Codec/Decoder/Audio") == 0
-- || qstrcmp(factory->details.klass, "Codec/Demux") == 0 )) {
-- const GList *pads = factory->staticpadtemplates;
-+ || qstrcmp(factory->details.klass, "Codec/Demux") == 0 )
-+#endif
-+ ) {
-+ const GList *pads = gst_element_factory_get_static_pad_templates(factory);
- while (pads) {
- GstStaticPadTemplate *padtemplate = (GstStaticPadTemplate*)(pads->data);
- pads = g_list_next (pads);
-diff --git a/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodersession.cpp b/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodersession.cpp
-index f944a60..72d1cf1 100644
---- a/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodersession.cpp
-+++ b/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodersession.cpp
-@@ -446,21 +446,40 @@ QAudioBuffer QGstreamerAudioDecoderSession::read()
- if (buffersAvailable == 1)
- emit bufferAvailableChanged(false);
-
-+ const char* bufferData = 0;
-+ int bufferSize = 0;
-+
-+#if GST_CHECK_VERSION(1,0,0)
-+ GstSample *sample = gst_app_sink_pull_sample(m_appSink);
-+ GstBuffer *buffer = gst_sample_get_buffer(sample);
-+ GstMapInfo mapInfo;
-+ gst_buffer_map(buffer, &mapInfo, GST_MAP_READ);
-+ bufferData = (const char*)mapInfo.data;
-+ bufferSize = mapInfo.size;
-+ QAudioFormat format = QGstUtils::audioFormatForSample(sample);
-+#else
- GstBuffer *buffer = gst_app_sink_pull_buffer(m_appSink);
--
-+ bufferData = (const char*)buffer->data;
-+ bufferSize = buffer->size;
- QAudioFormat format = QGstUtils::audioFormatForBuffer(buffer);
-+#endif
-+
- if (format.isValid()) {
- // XXX At the moment we have to copy data from GstBuffer into QAudioBuffer.
- // We could improve performance by implementing QAbstractAudioBuffer for GstBuffer.
- qint64 position = getPositionFromBuffer(buffer);
-- audioBuffer = QAudioBuffer(QByteArray((const char*)buffer->data, buffer->size), format, position);
-+ audioBuffer = QAudioBuffer(QByteArray((const char*)bufferData, bufferSize), format, position);
- position /= 1000; // convert to milliseconds
- if (position != m_position) {
- m_position = position;
- emit positionChanged(m_position);
- }
- }
-+#if GST_CHECK_VERSION(1,0,0)
-+ gst_sample_unref(sample);
-+#else
- gst_buffer_unref(buffer);
-+#endif
- }
-
- return audioBuffer;
-@@ -531,7 +550,12 @@ void QGstreamerAudioDecoderSession::addAppSink()
-
- GstAppSinkCallbacks callbacks;
- memset(&callbacks, 0, sizeof(callbacks));
-+#if GST_CHECK_VERSION(1,0,0)
-+ // ### Should perhaps also rename new_buffer to new_sample.
-+ callbacks.new_sample = &new_buffer;
-+#else
- callbacks.new_buffer = &new_buffer;
-+#endif
- gst_app_sink_set_callbacks(m_appSink, &callbacks, this, NULL);
- gst_app_sink_set_max_buffers(m_appSink, MAX_BUFFERS_IN_QUEUE);
- gst_base_sink_set_sync(GST_BASE_SINK(m_appSink), FALSE);
-@@ -557,8 +581,13 @@ void QGstreamerAudioDecoderSession::updateDuration()
- gint64 gstDuration = 0;
- int duration = -1;
-
-+#if GST_CHECK_VERSION(1,0,0)
-+ if (m_playbin && gst_element_query_duration(m_playbin, format, &gstDuration))
-+ duration = gstDuration / 1000000;
-+#else
- if (m_playbin && gst_element_query_duration(m_playbin, &format, &gstDuration))
- duration = gstDuration / 1000000;
-+#endif
-
- if (m_duration != duration) {
- m_duration = duration;
-diff --git a/src/plugins/gstreamer/camerabin/camerabinsession.cpp b/src/plugins/gstreamer/camerabin/camerabinsession.cpp
-index a4038c5..9d1fdfa 100644
---- a/src/plugins/gstreamer/camerabin/camerabinsession.cpp
-+++ b/src/plugins/gstreamer/camerabin/camerabinsession.cpp
-@@ -760,7 +760,11 @@ qint64 CameraBinSession::duration() const
- if (fileSink) {
- GstFormat format = GST_FORMAT_TIME;
- gint64 duration = 0;
-+#if GST_CHECK_VERSION(1,0,0)
-+ bool ret = gst_element_query_duration(fileSink, format, &duration);
-+#else
- bool ret = gst_element_query_position(fileSink, &format, &duration);
-+#endif
- gst_object_unref(GST_OBJECT(fileSink));
- if (ret)
- return duration / 1000000;
-@@ -797,8 +801,13 @@ void CameraBinSession::setMetaData(const QMap<QByteArray, QVariant> &data)
-
- if (m_camerabin) {
- GstIterator *elements = gst_bin_iterate_all_by_interface(GST_BIN(m_camerabin), GST_TYPE_TAG_SETTER);
-+#if GST_CHECK_VERSION(1,0,0)
-+ GValue *element = 0;
-+ while (gst_iterator_next(elements, element) == GST_ITERATOR_OK) {
-+#else
- GstElement *element = 0;
- while (gst_iterator_next(elements, (void**)&element) == GST_ITERATOR_OK) {
-+#endif
- gst_tag_setter_reset_tags(GST_TAG_SETTER(element));
-
- QMapIterator<QByteArray, QVariant> it(data);
-@@ -859,7 +868,11 @@ bool CameraBinSession::processSyncMessage(const QGstreamerMessage &message)
-
- if (gm && GST_MESSAGE_TYPE(gm) == GST_MESSAGE_ELEMENT) {
- if (m_captureMode == QCamera::CaptureStillImage &&
-+#if GST_CHECK_VERSION(1,0,0)
-+ gst_message_has_name (gm, "preview-image")) {
-+#else
- gst_structure_has_name(gm->structure, "preview-image")) {
-+#endif
- st = gst_message_get_structure(gm);
-
- if (gst_structure_has_field_typed(st, "buffer", GST_TYPE_BUFFER)) {
-@@ -869,7 +882,11 @@ bool CameraBinSession::processSyncMessage(const QGstreamerMessage &message)
-
- QImage img;
-
-+#if GST_CHECK_VERSION(1,0,0)
- GstCaps *caps = gst_buffer_get_caps(buffer);
-+#else
-+ GstCaps *caps = gst_buffer_get_caps(buffer);
-+#endif
- if (caps) {
- GstStructure *structure = gst_caps_get_structure(caps, 0);
- gint width = 0;
-@@ -1142,7 +1159,11 @@ QList< QPair<int,int> > CameraBinSession::supportedFrameRates(const QSize &frame
- gst_structure_remove_all_fields(structure);
- gst_structure_set_value(structure, "framerate", &rate);
- }
-+#if GST_CHECK_VERSION(1,0,0)
-+ caps = gst_caps_simplify(caps);
-+#else
- gst_caps_do_simplify(caps);
-+#endif
-
-
- for (uint i=0; i<gst_caps_get_size(caps); i++) {
-@@ -1262,7 +1283,11 @@ QList<QSize> CameraBinSession::supportedResolutions(QPair<int,int> rate,
- gst_structure_set_value(structure, "width", &w);
- gst_structure_set_value(structure, "height", &h);
- }
-+#if GST_CHECK_VERSION(1,0,0)
-+ caps = gst_caps_simplify(caps);
-+#else
- gst_caps_do_simplify(caps);
-+#endif
-
- for (uint i=0; i<gst_caps_get_size(caps); i++) {
- GstStructure *structure = gst_caps_get_structure(caps, i);
-diff --git a/src/plugins/gstreamer/common.pri b/src/plugins/gstreamer/common.pri
-index 8b421b8..2e7f746 100644
---- a/src/plugins/gstreamer/common.pri
-+++ b/src/plugins/gstreamer/common.pri
-@@ -12,14 +12,17 @@ LIBS += -lqgsttools_p
- CONFIG += link_pkgconfig
-
- PKGCONFIG += \
-- gstreamer-0.10 \
-- gstreamer-base-0.10 \
-- gstreamer-interfaces-0.10 \
-- gstreamer-audio-0.10 \
-- gstreamer-video-0.10 \
-- gstreamer-pbutils-0.10
-+ gstreamer-$$GST_VERSION \
-+ gstreamer-base-$$GST_VERSION \
-+ gstreamer-audio-$$GST_VERSION \
-+ gstreamer-video-$$GST_VERSION \
-+ gstreamer-pbutils-$$GST_VERSION
-
--maemo*:PKGCONFIG +=gstreamer-plugins-bad-0.10
-+maemo*:PKGCONFIG +=gstreamer-plugins-bad-$$GST_VERSION
-+
-+mir: {
-+ DEFINES += HAVE_MIR
-+}
-
- config_resourcepolicy {
- DEFINES += HAVE_RESOURCE_POLICY
-@@ -27,8 +30,8 @@ config_resourcepolicy {
- }
-
- config_gstreamer_appsrc {
-- PKGCONFIG += gstreamer-app-0.10
-+ PKGCONFIG += gstreamer-app-$$GST_VERSION
- DEFINES += HAVE_GST_APPSRC
-- LIBS += -lgstapp-0.10
-+ LIBS += -lgstapp-$$GST_VERSION
- }
-
-diff --git a/src/plugins/gstreamer/gstreamer.pro b/src/plugins/gstreamer/gstreamer.pro
-index 7649010..fce55ac 100644
---- a/src/plugins/gstreamer/gstreamer.pro
-+++ b/src/plugins/gstreamer/gstreamer.pro
-@@ -2,11 +2,10 @@ TEMPLATE = subdirs
-
- SUBDIRS += \
- audiodecoder \
-- mediacapture \
- mediaplayer
-
- config_gstreamer_encodingprofiles {
-- SUBDIRS += camerabin
-+# SUBDIRS += camerabin
- }
-
- OTHER_FILES += \
-diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp b/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp
-index a2bd80d..d12e9a5 100644
---- a/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp
-+++ b/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp
-@@ -498,6 +498,11 @@ GstElement *QGstreamerCaptureSession::buildImageCapture()
- gst_pad_add_buffer_probe(pad, G_CALLBACK(passImageFilter), this);
- gst_object_unref(GST_OBJECT(pad));
-
-+#if GST_CHECK_VERSION(1,0,0)
-+ gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_BUFFER, passImageFilter, this);
-+#else
-+ gst_pad_add_buffer_probe(pad, G_CALLBACK(passImageFilter), this);
-+#endif
- g_object_set(G_OBJECT(sink), "signal-handoffs", TRUE, NULL);
- g_signal_connect(G_OBJECT(sink), "handoff",
- G_CALLBACK(saveImageFilter), this);
-diff --git a/src/plugins/gstreamer/mediaplayer/mediaplayer.pro b/src/plugins/gstreamer/mediaplayer/mediaplayer.pro
-index 2ca9377..b986fc7 100644
---- a/src/plugins/gstreamer/mediaplayer/mediaplayer.pro
-+++ b/src/plugins/gstreamer/mediaplayer/mediaplayer.pro
-@@ -28,4 +28,3 @@ SOURCES += \
-
- OTHER_FILES += \
- mediaplayer.json
--
-diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp b/src/plugins/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp
-index fed756a..8239710 100644
---- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp
-+++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp
-@@ -537,6 +537,8 @@ void QGstreamerPlayerControl::processEOS()
- m_session->showPrerollFrames(false); // stop showing prerolled frames in stop state
- }
-
-+ qWarning() << "Processing EOS!";
-+
- popAndNotifyState();
- }
-
-diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayerservice.cpp b/src/plugins/gstreamer/mediaplayer/qgstreamerplayerservice.cpp
-index ce267d7..062de07 100644
---- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayerservice.cpp
-+++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayerservice.cpp
-@@ -51,7 +51,11 @@
- #include <private/qgstreamervideorenderer_p.h>
-
- #if defined(Q_WS_MAEMO_6) && defined(__arm__)
--#include "qgstreamergltexturerenderer.h"
-+#include "private/qgstreamergltexturerenderer.h"
-+#endif
-+
-+#if defined(HAVE_MIR) && defined (__arm__)
-+#include "private/qgstreamermirtexturerenderer_p.h"
- #endif
-
- #include "qgstreamerstreamscontrol.h"
-@@ -82,6 +86,9 @@ QGstreamerPlayerService::QGstreamerPlayerService(QObject *parent):
-
- #if defined(Q_WS_MAEMO_6) && defined(__arm__)
- m_videoRenderer = new QGstreamerGLTextureRenderer(this);
-+#elif defined(HAVE_MIR) && defined (__arm__)
-+ //m_videoRenderer = new QGstreamerVideoRenderer(this);
-+ m_videoRenderer = new QGstreamerMirTextureRenderer(this, m_session);
- #else
- m_videoRenderer = new QGstreamerVideoRenderer(this);
- #endif
-diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayerserviceplugin.cpp b/src/plugins/gstreamer/mediaplayer/qgstreamerplayerserviceplugin.cpp
-index 7d20b6d..bf2f9f8 100644
---- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayerserviceplugin.cpp
-+++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayerserviceplugin.cpp
-@@ -87,7 +87,11 @@ void QGstreamerPlayerServicePlugin::updateSupportedMimeTypes() const
- gst_init(NULL, NULL);
-
- GList *plugins, *orig_plugins;
-+#if GST_CHECK_VERSION(1,0,0)
-+ orig_plugins = plugins = gst_registry_get_plugin_list (gst_registry_get());
-+#else
- orig_plugins = plugins = gst_default_registry_get_plugin_list ();
-+#endif
-
- while (plugins) {
- GList *features, *orig_features;
-@@ -95,22 +99,33 @@ void QGstreamerPlayerServicePlugin::updateSupportedMimeTypes() const
- GstPlugin *plugin = (GstPlugin *) (plugins->data);
- plugins = g_list_next (plugins);
-
-+#if GST_CHECK_VERSION(1,0,0)
-+ if (GST_OBJECT_FLAG_IS_SET(plugin, GST_PLUGIN_FLAG_BLACKLISTED))
-+ continue;
-+#else
- if (plugin->flags & (1<<1)) //GST_PLUGIN_FLAG_BLACKLISTED
- continue;
-+#endif
-
-- orig_features = features = gst_registry_get_feature_list_by_plugin(gst_registry_get_default (),
-- plugin->desc.name);
-+ orig_features = features = gst_registry_get_feature_list_by_plugin(gst_registry_get(),
-+ gst_plugin_get_name(plugin));
- while (features) {
- if (!G_UNLIKELY(features->data == NULL)) {
- GstPluginFeature *feature = GST_PLUGIN_FEATURE(features->data);
- if (GST_IS_ELEMENT_FACTORY (feature)) {
- GstElementFactory *factory = GST_ELEMENT_FACTORY(gst_plugin_feature_load(feature));
- if (factory
-- && factory->numpadtemplates > 0
-- && (qstrcmp(factory->details.klass, "Codec/Decoder/Audio") == 0
-+#if GST_CHECK_VERSION(1,0,0)
-+ && (qstrcmp(gst_element_factory_get_metadata(factory, GST_ELEMENT_METADATA_KLASS), "Codec/Decoder/Audio") == 0
-+ || qstrcmp(gst_element_factory_get_metadata(factory, GST_ELEMENT_METADATA_KLASS),"Codec/Decoder/Video") == 0
-+ || qstrcmp(gst_element_factory_get_metadata(factory, GST_ELEMENT_METADATA_KLASS), "Codec/Demux") == 0 )
-+#else
-+ && (qstrcmp(factory->details.klass, "Codec/Decoder/Audio") == 0
- || qstrcmp(factory->details.klass, "Codec/Decoder/Video") == 0
-- || qstrcmp(factory->details.klass, "Codec/Demux") == 0 )) {
-- const GList *pads = factory->staticpadtemplates;
-+ || qstrcmp(factory->details.klass, "Codec/Demux") == 0 )
-+#endif
-+ ) {
-+ const GList *pads = gst_element_factory_get_static_pad_templates(factory);
- while (pads) {
- GstStaticPadTemplate *padtemplate = (GstStaticPadTemplate*)(pads->data);
- pads = g_list_next (pads);
-diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp b/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp
-index 15924a6..8013d0d 100644
---- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp
-+++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp
-@@ -85,6 +85,16 @@ typedef enum {
- GST_PLAY_FLAG_BUFFERING = 0x000000100
- } GstPlayFlags;
-
-+#if GST_CHECK_VERSION(1,0,0)
-+#define DEFAULT_RAW_CAPS \
-+ "video/x-surface; " \
-+ "text/plain; " \
-+ "text/x-pango-markup; " \
-+ "video/x-dvd-subpicture; " \
-+ "subpicture/x-pgs" \
-+ "video/x-raw" \
-+ "audio/x-raw"
-+#else
- #define DEFAULT_RAW_CAPS \
- "video/x-raw-yuv; " \
- "video/x-raw-rgb; " \
-@@ -97,6 +107,8 @@ typedef enum {
- "text/x-pango-markup; " \
- "video/x-dvd-subpicture; " \
- "subpicture/x-pgs"
-+#endif
-+
- static GstStaticCaps static_RawCaps = GST_STATIC_CAPS(DEFAULT_RAW_CAPS);
-
- QGstreamerPlayerSession::QGstreamerPlayerSession(QObject *parent)
-@@ -137,8 +149,11 @@ QGstreamerPlayerSession::QGstreamerPlayerSession(QObject *parent)
- gboolean result = gst_type_find_register(0, "playlist", GST_RANK_MARGINAL, playlistTypeFindFunction, 0, 0, this, 0);
- Q_ASSERT(result == TRUE);
- Q_UNUSED(result);
--
-+#if GST_CHECK_VERSION(1,0,0)
-+ m_playbin = gst_element_factory_make("playbin", NULL);
-+#else
- m_playbin = gst_element_factory_make("playbin2", NULL);
-+#endif
-
- if (m_playbin) {
- //GST_PLAY_FLAG_NATIVE_VIDEO omits configuration of ffmpegcolorspace and videoscale,
-@@ -188,7 +203,11 @@ QGstreamerPlayerSession::QGstreamerPlayerSession(QObject *parent)
- m_videoIdentity = GST_ELEMENT(g_object_new(gst_video_connector_get_type(), 0)); // floating ref
- g_signal_connect(G_OBJECT(m_videoIdentity), "connection-failed", G_CALLBACK(insertColorSpaceElement), (gpointer)this);
-
-+#if GST_CHECK_VERSION(1,0,0)
-+ m_colorSpace = gst_element_factory_make("videoconvert", "ffmpegcolorspace-vo");
-+#else
- m_colorSpace = gst_element_factory_make("ffmpegcolorspace", "ffmpegcolorspace-vo");
-+#endif
- // might not get a parent, take ownership to avoid leak
- qt_gst_object_ref_sink(GST_OBJECT(m_colorSpace));
-
-@@ -206,7 +225,7 @@ QGstreamerPlayerSession::QGstreamerPlayerSession(QObject *parent)
-
- // add ghostpads
- GstPad *pad = gst_element_get_static_pad(m_videoIdentity,"sink");
-- gst_element_add_pad(GST_ELEMENT(m_videoOutputBin), gst_ghost_pad_new("videosink", pad));
-+ gst_element_add_pad(GST_ELEMENT(m_videoOutputBin), gst_ghost_pad_new("sink", pad));
- gst_object_unref(GST_OBJECT(pad));
-
- if (m_playbin != 0) {
-@@ -218,7 +237,7 @@ QGstreamerPlayerSession::QGstreamerPlayerSession(QObject *parent)
- g_object_set(G_OBJECT(m_playbin), "video-sink", m_videoOutputBin, NULL);
-
- g_signal_connect(G_OBJECT(m_playbin), "notify::source", G_CALLBACK(playbinNotifySource), this);
-- g_signal_connect(G_OBJECT(m_playbin), "element-added", G_CALLBACK(handleElementAdded), this);
-+ //g_signal_connect(G_OBJECT(m_playbin), "element-added", G_CALLBACK(handleElementAdded), this);
-
- if (usePlaybinVolume()) {
- updateVolume();
-@@ -342,9 +361,13 @@ qint64 QGstreamerPlayerSession::position() const
- GstFormat format = GST_FORMAT_TIME;
- gint64 position = 0;
-
-+#if GST_CHECK_VERSION(1,0,0)
-+ if ( m_playbin && gst_element_query_position(m_playbin, format, &position))
-+ m_lastPosition = position / 1000000;
-+#else
- if ( m_playbin && gst_element_query_position(m_playbin, &format, &position))
- m_lastPosition = position / 1000000;
--
-+#endif
- return m_lastPosition;
- }
-
-@@ -474,9 +497,18 @@ bool QGstreamerPlayerSession::isAudioAvailable() const
- return m_audioAvailable;
- }
-
-+#if GST_CHECK_VERSION(1,0,0)
-+static GstPadProbeReturn block_pad_cb(GstPad *pad, GstPadProbeInfo *info, gpointer user_data)
-+#else
- static void block_pad_cb(GstPad *pad, gboolean blocked, gpointer user_data)
-+#endif
- {
- Q_UNUSED(pad);
-+#if GST_CHECK_VERSION(1,0,0)
-+ Q_UNUSED(info);
-+ Q_UNUSED(user_data);
-+ return GST_PAD_PROBE_OK;
-+#else
- #ifdef DEBUG_PLAYBIN
- qDebug() << "block_pad_cb, blocked:" << blocked;
- #endif
-@@ -485,6 +517,7 @@ static void block_pad_cb(GstPad *pad, gboolean blocked, gpointer user_data)
- QGstreamerPlayerSession *session = reinterpret_cast<QGstreamerPlayerSession*>(user_data);
- QMetaObject::invokeMethod(session, "finishVideoOutputChange", Qt::QueuedConnection);
- }
-+#endif
- }
-
- void QGstreamerPlayerSession::updateVideoRenderer()
-@@ -529,7 +562,7 @@ void QGstreamerPlayerSession::setVideoRenderer(QObject *videoOutput)
- m_renderer = renderer;
-
- #ifdef DEBUG_VO_BIN_DUMP
-- _gst_debug_bin_to_dot_file_with_ts(GST_BIN(m_playbin),
-+ gst_debug_bin_to_dot_file_with_ts(GST_BIN(m_playbin),
- GstDebugGraphDetails(GST_DEBUG_GRAPH_SHOW_ALL /* GST_DEBUG_GRAPH_SHOW_MEDIA_TYPE | GST_DEBUG_GRAPH_SHOW_NON_DEFAULT_PARAMS | GST_DEBUG_GRAPH_SHOW_STATES*/),
- "playbin_set");
- #endif
-@@ -633,7 +666,11 @@ void QGstreamerPlayerSession::setVideoRenderer(QObject *videoOutput)
-
- //block pads, async to avoid locking in paused state
- GstPad *srcPad = gst_element_get_static_pad(m_videoIdentity, "src");
-+#if GST_CHECK_VERSION(1,0,0)
-+ this->pad_probe_id = gst_pad_add_probe(srcPad, (GstPadProbeType)(GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_BLOCK), block_pad_cb, this, NULL);
-+#else
- gst_pad_set_blocked_async(srcPad, true, &block_pad_cb, this);
-+#endif
- gst_object_unref(GST_OBJECT(srcPad));
-
- //Unpause the sink to avoid waiting until the buffer is processed
-@@ -674,7 +711,11 @@ void QGstreamerPlayerSession::finishVideoOutputChange()
- //video output was change back to the current one,
- //no need to torment the pipeline, just unblock the pad
- if (gst_pad_is_blocked(srcPad))
-+#if GST_CHECK_VERSION(1,0,0)
-+ gst_pad_remove_probe(srcPad, this->pad_probe_id);
-+#else
- gst_pad_set_blocked_async(srcPad, false, &block_pad_cb, 0);
-+#endif
-
- m_pendingVideoSink = 0;
- gst_object_unref(GST_OBJECT(srcPad));
-@@ -760,12 +801,17 @@ void QGstreamerPlayerSession::finishVideoOutputChange()
-
- //don't have to wait here, it will unblock eventually
- if (gst_pad_is_blocked(srcPad))
-- gst_pad_set_blocked_async(srcPad, false, &block_pad_cb, 0);
-+#if GST_CHECK_VERSION(1,0,0)
-+ gst_pad_remove_probe(srcPad, this->pad_probe_id);
-+#else
-+ gst_pad_set_blocked_async(srcPad, false, &block_pad_cb, 0);
-+#endif
-+
- gst_object_unref(GST_OBJECT(srcPad));
-
- #ifdef DEBUG_VO_BIN_DUMP
-- _gst_debug_bin_to_dot_file_with_ts(GST_BIN(m_playbin),
-- GstDebugGraphDetails(GST_DEBUG_GRAPH_SHOW_ALL /* GST_DEBUG_GRAPH_SHOW_MEDIA_TYPE | GST_DEBUG_GRAPH_SHOW_NON_DEFAULT_PARAMS | GST_DEBUG_GRAPH_SHOW_STATES*/),
-+ gst_debug_bin_to_dot_file_with_ts(GST_BIN(m_playbin),
-+ GstDebugGraphDetails(GST_DEBUG_GRAPH_SHOW_ALL /* | GST_DEBUG_GRAPH_SHOW_MEDIA_TYPE | GST_DEBUG_GRAPH_SHOW_NON_DEFAULT_PARAMS | GST_DEBUG_GRAPH_SHOW_STATES */),
- "playbin_finish");
- #endif
- }
-@@ -830,6 +876,7 @@ bool QGstreamerPlayerSession::play()
- #ifdef DEBUG_PLAYBIN
- qDebug() << Q_FUNC_INFO;
- #endif
-+
- m_everPlayed = false;
- if (m_playbin) {
- m_pendingState = QMediaPlayer::PlayingState;
-@@ -1327,8 +1374,11 @@ void QGstreamerPlayerSession::getStreamsInfo()
- default:
- break;
- }
--
-+#if GST_CHECK_VERSION(1,0,0)
-+ if (tags && GST_IS_TAG_LIST(tags)) {
-+#else
- if (tags && gst_is_tag_list(tags)) {
-+#endif
- gchar *languageCode = 0;
- if (gst_tag_list_get_string(tags, GST_TAG_LANGUAGE_CODE, &languageCode))
- streamProperties[QMediaMetaData::Language] = QString::fromUtf8(languageCode);
-@@ -1367,7 +1417,11 @@ void QGstreamerPlayerSession::updateVideoResolutionTag()
- QSize aspectRatio;
-
- GstPad *pad = gst_element_get_static_pad(m_videoIdentity, "src");
-+#if GST_CHECK_VERSION(1,0,0)
-+ GstCaps *caps = gst_pad_get_current_caps(pad);
-+#else
- GstCaps *caps = gst_pad_get_negotiated_caps(pad);
-+#endif
-
- if (caps) {
- const GstStructure *structure = gst_caps_get_structure(caps, 0);
-@@ -1411,7 +1465,11 @@ void QGstreamerPlayerSession::updateDuration()
- gint64 gstDuration = 0;
- int duration = -1;
-
-+#if GST_CHECK_VERSION(1,0,0)
-+ if (m_playbin && gst_element_query_duration(m_playbin, format, &gstDuration))
-+#else
- if (m_playbin && gst_element_query_duration(m_playbin, &format, &gstDuration))
-+#endif
- duration = gstDuration / 1000000;
-
- if (m_duration != duration) {
-@@ -1467,7 +1525,11 @@ void QGstreamerPlayerSession::playbinNotifySource(GObject *o, GParamSpec *p, gpo
-
- // The rest
- if (g_object_class_find_property(G_OBJECT_GET_CLASS(source), "extra-headers") != 0) {
-+#if GST_CHECK_VERSION(1,0,0)
-+ GstStructure *extras = gst_structure_new_empty("extras");
-+#else
- GstStructure *extras = gst_structure_empty_new("extras");
-+#endif
-
- foreach (const QByteArray &rawHeader, self->m_request.rawHeaderList()) {
- if (rawHeader == userAgentString) // Filter User-Agent
-@@ -1623,7 +1685,11 @@ GstAutoplugSelectResult QGstreamerPlayerSession::handleAutoplugSelect(GstBin *bi
- const gchar *factoryName = gst_plugin_feature_get_name(GST_PLUGIN_FEATURE(factory));
- if (g_str_has_prefix(factoryName, "vaapi")) {
- GstPad *sinkPad = gst_element_get_static_pad(session->m_videoSink, "sink");
-+#if GST_CHECK_VERSION(1,0,0)
-+ GstCaps *sinkCaps = gst_pad_query_caps(sinkPad, NULL);
-+#else
- GstCaps *sinkCaps = gst_pad_get_caps(sinkPad);
-+#endif
-
- #if (GST_VERSION_MAJOR == 0) && ((GST_VERSION_MINOR < 10) || (GST_VERSION_MICRO < 33))
- if (!factory_can_src_any_caps(factory, sinkCaps))
-@@ -1652,14 +1718,19 @@ void QGstreamerPlayerSession::handleElementAdded(GstBin *bin, GstElement *elemen
- // Disable on-disk buffering.
- g_object_set(G_OBJECT(element), "temp-template", NULL, NULL);
- } else if (g_str_has_prefix(elementName, "uridecodebin") ||
-- g_str_has_prefix(elementName, "decodebin2")) {
--
-+#if GST_CHECK_VERSION(1,0,0)
-+ g_str_has_prefix(elementName, "decodebin")) {
-+#else
-+ g_str_has_prefix(elementName, "decodebin2")) {
-+#endif
- if (g_str_has_prefix(elementName, "uridecodebin")) {
- // Add video/x-surface (VAAPI) to default raw formats
- g_object_set(G_OBJECT(element), "caps", gst_static_caps_get(&static_RawCaps), NULL);
- // listen for uridecodebin autoplug-select to skip VAAPI usage when the current
- // video sink doesn't support it
-+#if !(GST_CHECK_VERSION(1,0,0))
- g_signal_connect(element, "autoplug-select", G_CALLBACK(handleAutoplugSelect), session);
-+#endif
- }
-
- //listen for queue2 element added to uridecodebin/decodebin2 as well.
-@@ -1727,7 +1798,27 @@ void QGstreamerPlayerSession::removeProbe(QGstreamerVideoProbeControl* probe)
- // Assume user releases any outstanding references to video frames.
- }
-
--gboolean QGstreamerPlayerSession::padVideoBufferProbe(GstPad *pad, GstBuffer *buffer, gpointer user_data)
-+#if GST_CHECK_VERSION(1,0,0)
-+GstPadProbeReturn QGstreamerPlayerSession::padVideoBufferProbe(GstPad *pad, GstPadProbeInfo *info, gpointer user_data)
-+{
-+ Q_UNUSED(pad);
-+ GstBuffer* buffer = GST_PAD_PROBE_INFO_BUFFER(info);
-+
-+ QGstreamerPlayerSession *session = reinterpret_cast<QGstreamerPlayerSession*>(user_data);
-+ QMutexLocker locker(&session->m_videoProbeMutex);
-+
-+ if (session->m_videoProbes.isEmpty())
-+ return GST_PAD_PROBE_OK;
-+
-+ foreach (QGstreamerVideoProbeControl* probe, session->m_videoProbes)
-+ probe->bufferProbed(buffer, gst_pad_get_current_caps(pad));
-+
-+ return GST_PAD_PROBE_OK;
-+}
-+
-+#else
-+
-+static gboolean QGstreamerPlayerSession::padVideoBufferProbe(GstPad *pad, GstBuffer *buffer, gpointer user_data)
- {
- Q_UNUSED(pad);
-
-@@ -1742,6 +1833,7 @@ gboolean QGstreamerPlayerSession::padVideoBufferProbe(GstPad *pad, GstBuffer *bu
-
- return TRUE;
- }
-+#endif
-
- void QGstreamerPlayerSession::addProbe(QGstreamerAudioProbeControl* probe)
- {
-@@ -1759,6 +1851,24 @@ void QGstreamerPlayerSession::removeProbe(QGstreamerAudioProbeControl* probe)
- m_audioProbes.removeOne(probe);
- }
-
-+#if GST_CHECK_VERSION(1,0,0)
-+GstPadProbeReturn QGstreamerPlayerSession::padAudioBufferProbe(GstPad *pad, GstPadProbeInfo* info, gpointer user_data)
-+{
-+ Q_UNUSED(pad);
-+ GstBuffer* buffer = GST_PAD_PROBE_INFO_BUFFER(info);
-+
-+ QGstreamerPlayerSession *session = reinterpret_cast<QGstreamerPlayerSession*>(user_data);
-+ QMutexLocker locker(&session->m_audioProbeMutex);
-+
-+ if (session->m_audioProbes.isEmpty())
-+ return GST_PAD_PROBE_OK;
-+
-+ foreach (QGstreamerAudioProbeControl* probe, session->m_audioProbes)
-+ probe->bufferProbed(buffer, gst_pad_get_current_caps(pad));
-+
-+ return GST_PAD_PROBE_OK;
-+}
-+#else
- gboolean QGstreamerPlayerSession::padAudioBufferProbe(GstPad *pad, GstBuffer *buffer, gpointer user_data)
- {
- Q_UNUSED(pad);
-@@ -1774,7 +1884,7 @@ gboolean QGstreamerPlayerSession::padAudioBufferProbe(GstPad *pad, GstBuffer *bu
-
- return TRUE;
- }
--
-+#endif
- // This function is similar to stop(),
- // but does not set m_everPlayed, m_lastPosition,
- // and setSeekable() values.
-@@ -1807,7 +1917,11 @@ void QGstreamerPlayerSession::removeVideoBufferProbe()
-
- GstPad *pad = gst_element_get_static_pad(m_videoSink, "sink");
- if (pad) {
-+#if GST_CHECK_VERSION(1,0,0)
-+ gst_pad_remove_probe(pad, m_videoBufferProbeId);
-+#else
- gst_pad_remove_buffer_probe(pad, m_videoBufferProbeId);
-+#endif
- gst_object_unref(GST_OBJECT(pad));
- }
-
-@@ -1822,7 +1936,11 @@ void QGstreamerPlayerSession::addVideoBufferProbe()
-
- GstPad *pad = gst_element_get_static_pad(m_videoSink, "sink");
- if (pad) {
-+#if GST_CHECK_VERSION(1,0,0)
-+ m_videoBufferProbeId = gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_BUFFER, padVideoBufferProbe, this, NULL);
-+#else
- m_videoBufferProbeId = gst_pad_add_buffer_probe(pad, G_CALLBACK(padVideoBufferProbe), this);
-+#endif
- gst_object_unref(GST_OBJECT(pad));
- }
- }
-@@ -1839,7 +1957,11 @@ void QGstreamerPlayerSession::removeAudioBufferProbe()
-
- GstPad *pad = gst_element_get_static_pad(m_audioSink, "sink");
- if (pad) {
-+#if GST_CHECK_VERSION(1,0,0)
-+ gst_pad_remove_probe(pad, m_audioBufferProbeId);
-+#else
- gst_pad_remove_buffer_probe(pad, m_audioBufferProbeId);
-+#endif
- gst_object_unref(GST_OBJECT(pad));
- }
-
-@@ -1854,7 +1976,11 @@ void QGstreamerPlayerSession::addAudioBufferProbe()
-
- GstPad *pad = gst_element_get_static_pad(m_audioSink, "sink");
- if (pad) {
-+#if GST_CHECK_VERSION(1,0,0)
-+ m_audioBufferProbeId = gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_BUFFER, padAudioBufferProbe, this, NULL);
-+#else
- m_audioBufferProbeId = gst_pad_add_buffer_probe(pad, G_CALLBACK(padAudioBufferProbe), this);
-+#endif
- gst_object_unref(GST_OBJECT(pad));
- }
- }
-@@ -1887,7 +2013,7 @@ void QGstreamerPlayerSession::playlistTypeFindFunction(GstTypeFind *find, gpoint
- length = qMin(length, guint64(1024));
-
- while (length > 0) {
-- guint8 *data = gst_type_find_peek(find, 0, length);
-+ const guint8 *data = gst_type_find_peek(find, 0, length);
- if (data) {
- session->m_isPlaylist = (QPlaylistFileParser::findPlaylistType(QString::fromUtf8(uri), 0, data, length) != QPlaylistFileParser::UNKNOWN);
- return;
-diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.h b/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.h
-index f2e760a..50bda3d 100644
---- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.h
-+++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.h
-@@ -119,11 +119,19 @@ public:
-
- void addProbe(QGstreamerVideoProbeControl* probe);
- void removeProbe(QGstreamerVideoProbeControl* probe);
-+#if GST_CHECK_VERSION(1,0,0)
-+ static GstPadProbeReturn padVideoBufferProbe(GstPad *pad, GstPadProbeInfo *info, gpointer user_data);
-+#else
- static gboolean padVideoBufferProbe(GstPad *pad, GstBuffer *buffer, gpointer user_data);
-+#endif
-
- void addProbe(QGstreamerAudioProbeControl* probe);
- void removeProbe(QGstreamerAudioProbeControl* probe);
-+#if GST_CHECK_VERSION(1,0,0)
-+ static GstPadProbeReturn padAudioBufferProbe(GstPad *pad, GstPadProbeInfo* info, gpointer user_data);
-+#else
- static gboolean padAudioBufferProbe(GstPad *pad, GstBuffer *buffer, gpointer user_data);
-+#endif
-
- void endOfMediaReset();
-
-@@ -252,6 +260,7 @@ private:
- bool m_isLiveSource;
-
- bool m_isPlaylist;
-+ gulong pad_probe_id;
- };
-
- QT_END_NAMESPACE
---
-2.1.3
-
--
2.1.4
More information about the Openembedded-devel
mailing list