From bc3c17e0f880585512a616220508b7998bfa6f33 Mon Sep 17 00:00:00 2001 From: Rex Dieter Date: Thu, 22 Oct 2015 10:20:09 -0500 Subject: [PATCH 1/6] try to el6's gstreamer-0.10.29 (QTBUG-48939) --- qt5-qtmultimedia.spec | 6 ++ qtmultimedia-opensource-src-5.5.1-el6.patch | 97 +++++++++++++++++++++ 2 files changed, 103 insertions(+) create mode 100644 qtmultimedia-opensource-src-5.5.1-el6.patch diff --git a/qt5-qtmultimedia.spec b/qt5-qtmultimedia.spec index f7f768f..7f81b13 100644 --- a/qt5-qtmultimedia.spec +++ b/qt5-qtmultimedia.spec @@ -34,6 +34,10 @@ License: LGPLv2 with exceptions or GPLv3 with exceptions Url: http://www.qt.io Source0: http://download.qt.io/official_releases/qt/5.5/%{version}%{?prerelease:-%{prerelease}}/submodules/%{qt_module}-opensource-src-%{version}%{?prerelease:-%{prerelease}}.tar.xz +# try to support el6's older gstreamer-0.10.29 +# https://bugreports.qt.io/browse/QTBUG-48939 +Patch1: qtmultimedia-opensource-src-5.5.1-el6.patch + BuildRequires: qt5-qtbase-devel >= %{version} BuildRequires: qt5-qtdeclarative-devel >= %{version} BuildRequires: pkgconfig(alsa) @@ -90,6 +94,8 @@ Requires: %{name}%{?_isa} = %{version}-%{release} %prep %setup -q -n %{qt_module}-opensource-src-%{version}%{?prerelease:-%{prerelease}} +%patch1 -p1 -b .el6 + %build mkdir %{_target_platform} diff --git a/qtmultimedia-opensource-src-5.5.1-el6.patch b/qtmultimedia-opensource-src-5.5.1-el6.patch new file mode 100644 index 0000000..4126544 --- /dev/null +++ b/qtmultimedia-opensource-src-5.5.1-el6.patch @@ -0,0 +1,97 @@ +diff -up qtmultimedia-opensource-src-5.5.1/src/gsttools/qgstreamervideooverlay.cpp.el6 qtmultimedia-opensource-src-5.5.1/src/gsttools/qgstreamervideooverlay.cpp +--- qtmultimedia-opensource-src-5.5.1/src/gsttools/qgstreamervideooverlay.cpp.el6 2015-10-12 23:35:43.000000000 -0500 ++++ qtmultimedia-opensource-src-5.5.1/src/gsttools/qgstreamervideooverlay.cpp 2015-10-22 10:14:22.129635875 -0500 +@@ -146,6 +146,7 @@ GstElement *QGstreamerVideoOverlay::find + } + } + ++#if GST_CHECK_VERSION(0,10,31) + // If none of the known video sinks are available, try to find one that implements the + // GstVideoOverlay interface and has autoplugging rank. + GList *list = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_SINK | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO, +@@ -170,6 +171,7 @@ GstElement *QGstreamerVideoOverlay::find + gst_plugin_feature_list_free(list); + + return choice; ++#endif + } + + GstElement *QGstreamerVideoOverlay::videoSink() const +diff -up qtmultimedia-opensource-src-5.5.1/src/gsttools/qgstutils.cpp.el6 qtmultimedia-opensource-src-5.5.1/src/gsttools/qgstutils.cpp +--- qtmultimedia-opensource-src-5.5.1/src/gsttools/qgstutils.cpp.el6 2015-10-12 23:35:43.000000000 -0500 ++++ qtmultimedia-opensource-src-5.5.1/src/gsttools/qgstutils.cpp 2015-10-22 09:49:55.726563754 -0500 +@@ -782,7 +782,9 @@ 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 }, ++#if GST_CHECK_VERSION(0,30,0) + { QImage::Format_RGB16 , GST_VIDEO_FORMAT_RGB16 } ++#endif + }; + + } +@@ -1212,6 +1214,7 @@ void QGstUtils::setMetaData(GstElement * + tagValue.toDouble(), + NULL); + break; ++#if GST_CHECK_VERSION(0,10,31) + case QVariant::DateTime: { + QDateTime date = tagValue.toDateTime().toLocalTime(); + gst_tag_setter_add_tags(GST_TAG_SETTER(element), +@@ -1223,6 +1226,7 @@ void QGstUtils::setMetaData(GstElement * + NULL); + break; + } ++#endif + default: + break; + } +diff -up qtmultimedia-opensource-src-5.5.1/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderserviceplugin.cpp.el6 qtmultimedia-opensource-src-5.5.1/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderserviceplugin.cpp +--- qtmultimedia-opensource-src-5.5.1/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderserviceplugin.cpp.el6 2015-10-12 23:35:43.000000000 -0500 ++++ qtmultimedia-opensource-src-5.5.1/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderserviceplugin.cpp 2015-10-22 09:49:55.726563754 -0500 +@@ -70,9 +70,13 @@ QMultimedia::SupportEstimate QGstreamerA + + static bool isDecoderOrDemuxer(GstElementFactory *factory) + { ++#if GST_CHECK_VERSION(0,10,31) + 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); ++#else ++ return false; ++#endif + } + + void QGstreamerAudioDecoderServicePlugin::updateSupportedMimeTypes() const +diff -up qtmultimedia-opensource-src-5.5.1/src/plugins/gstreamer/mediacapture/qgstreamercaptureserviceplugin.cpp.el6 qtmultimedia-opensource-src-5.5.1/src/plugins/gstreamer/mediacapture/qgstreamercaptureserviceplugin.cpp +--- qtmultimedia-opensource-src-5.5.1/src/plugins/gstreamer/mediacapture/qgstreamercaptureserviceplugin.cpp.el6 2015-10-12 23:35:42.000000000 -0500 ++++ qtmultimedia-opensource-src-5.5.1/src/plugins/gstreamer/mediacapture/qgstreamercaptureserviceplugin.cpp 2015-10-22 09:53:38.620573847 -0500 +@@ -113,8 +113,12 @@ QMultimedia::SupportEstimate QGstreamerC + + static bool isEncoderOrMuxer(GstElementFactory *factory) + { ++#if GST_CHECK_VERSION(0,10,31) + 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); ++#else ++ return false; ++#endif + } + + void QGstreamerCaptureServicePlugin::updateSupportedMimeTypes() const +diff -up qtmultimedia-opensource-src-5.5.1/src/plugins/gstreamer/mediaplayer/qgstreamerplayerserviceplugin.cpp.el6 qtmultimedia-opensource-src-5.5.1/src/plugins/gstreamer/mediaplayer/qgstreamerplayerserviceplugin.cpp +--- qtmultimedia-opensource-src-5.5.1/src/plugins/gstreamer/mediaplayer/qgstreamerplayerserviceplugin.cpp.el6 2015-10-12 23:35:42.000000000 -0500 ++++ qtmultimedia-opensource-src-5.5.1/src/plugins/gstreamer/mediaplayer/qgstreamerplayerserviceplugin.cpp 2015-10-22 09:52:40.403569549 -0500 +@@ -83,8 +83,12 @@ QMultimedia::SupportEstimate QGstreamerP + + static bool isDecoderOrDemuxer(GstElementFactory *factory) + { ++#if GST_CHECK_VERSION(0,10,31) + 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); ++#else ++ return false; ++#endif + } + + void QGstreamerPlayerServicePlugin::updateSupportedMimeTypes() const From 66ee2634358b3e8d530fd88daa19404ede30476f Mon Sep 17 00:00:00 2001 From: Rex Dieter Date: Thu, 22 Oct 2015 13:26:13 -0500 Subject: [PATCH 2/6] drop unused patch --- 0006-GStreamer-port-to-1.0.patch | 7546 ------------------------------ 1 file changed, 7546 deletions(-) delete mode 100644 0006-GStreamer-port-to-1.0.patch diff --git a/0006-GStreamer-port-to-1.0.patch b/0006-GStreamer-port-to-1.0.patch deleted file mode 100644 index 1314294..0000000 --- a/0006-GStreamer-port-to-1.0.patch +++ /dev/null @@ -1,7546 +0,0 @@ -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 cf97e64..cf58d63 100644 ---- a/qtmultimedia.pro -+++ b/qtmultimedia.pro -@@ -17,11 +17,27 @@ win32 { - } else { - contains(QT_CONFIG, alsa):qtCompileTest(alsa) - contains(QT_CONFIG, pulseaudio):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 561a96f..178e118 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 - - #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(info.data), info.size); -+ gst_buffer_unmap(buffer, &info); -+ } else { -+ return true; -+ } -+#else -+ data = QByteArray(reinterpret_cast(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(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(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(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 -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+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(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(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(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(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::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(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(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(m_surface->property("GLContext").value()); -+ 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 -+ -+#include "qgstutils_p.h" - #include - - 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 - #include - #include -- --#include -+#include - - #include - -diff --git a/src/gsttools/qgstreamervideowidget.cpp b/src/gsttools/qgstreamervideowidget.cpp -index b26369a..72a5a12 100644 ---- a/src/gsttools/qgstreamervideowidget.cpp -+++ b/src/gsttools/qgstreamervideowidget.cpp -@@ -40,8 +40,13 @@ - #include - - #include -+ -+#if !GST_CHECK_VERSION(1,0,0) - #include - #include -+#else -+#include -+#endif - - QT_BEGIN_NAMESPACE - -@@ -161,9 +166,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; -@@ -191,17 +200,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) { -@@ -217,8 +233,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 - - #include -+ -+#if !GST_CHECK_VERSION(1,0,0) - #include - #include -+#else -+#include -+#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(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 465f439..3b1de44 100644 ---- a/src/gsttools/qgstutils.cpp -+++ b/src/gsttools/qgstutils.cpp -@@ -40,9 +40,17 @@ - #include - #include - #include -+#include - #include - #include - -+#include -+ -+#include -+#include -+ -+template static int lengthOf(const T (&)[N]) { return N; } -+ - #ifdef USE_V4L - # include - # include -@@ -83,15 +91,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); -@@ -170,6 +187,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. -@@ -177,9 +230,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) { - -@@ -250,16 +320,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); -@@ -270,7 +352,7 @@ QAudioFormat QGstUtils::audioFormatForBuffer(GstBuffer *buffer) - gst_caps_unref(caps); - return format; - } -- -+#endif - - /*! - Builds GstCaps for an audio format. -@@ -278,8 +360,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()) { -@@ -314,6 +420,7 @@ GstCaps *QGstUtils::capsForAudioFormat(QAudioFormat format) - } - - return caps; -+#endif - } - - void QGstUtils::initializeGst() -@@ -585,10 +692,629 @@ QByteArray QGstUtils::cameraDriver(const QString &device, GstElementFactory *fac - return QByteArray(); - } - -+QSet QGstUtils::supportedMimeTypes(bool (*isValidFactory)(GstElementFactory *factory)) -+{ -+ QSet 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(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(frame.data[0]), -+ static_cast(frame.data[1]), -+ static_cast(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; yformat) -+ continue; -+ -+ const QImage image( -+ static_cast(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 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 &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 &data) -+{ -+ if (!GST_IS_TAG_SETTER(element)) -+ return; -+ -+ gst_tag_setter_reset_tags(GST_TAG_SETTER(element)); -+ -+ QMapIterator 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 &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)); -@@ -604,4 +1330,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(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(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 -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include "qgstvideobuffer_p.h" -+ -+#include "qgstvideorenderersink_p.h" -+ -+#include -+ -+#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(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(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(s)) -+ -+QGstVideoRendererSink *QGstVideoRendererSink::createSink(QAbstractVideoSurface *surface) -+{ -+ QGstVideoRendererSink *sink = reinterpret_cast( -+ 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(g_type_class_peek_parent(g_class)); -+ -+ GstBaseSinkClass *base_sink_class = reinterpret_cast(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(g_class); -+ element_class->change_state = QGstVideoRendererSink::change_state; -+ -+ GObjectClass *object_class = reinterpret_cast(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 - #include "qgstvideobuffer_p.h" - -+#include "qgstutils_p.h" - #include "qvideosurfacegstsink_p.h" - -+#if GST_VERSION_MAJOR >=1 -+#include -+#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(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(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 supportedFormats; -@@ -503,6 +426,7 @@ GstCaps *QVideoSurfaceGstSink::get_caps(GstBaseSink *base) - QList 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 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 - #include -+ -+#if GST_VERSION_MAJOR < 1 - #include -+#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 - #include - #include -+#include -+ -+#include - - 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 -+ -+#include -+ -+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 -+#include -+#include -+#include -+ -+#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 m_surface; -+ QPointer 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 -+#include - #include - #include - #include -+#include -+ -+#include - - 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 -+#include - #include - - 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 - #include - #include -+#include - #include - #include -+#include -+#include -+#include -+ -+#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 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 &formats); -+ void setFrameTimeStamps(QVideoFrame *frame, GstBuffer *buffer); -+ -+ void setMetaData(GstElement *element, const QMap &data); -+ void setMetaData(GstBin *bin, const QMap &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 - - #include -+#include - - 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 -+#include -+#include -+#include -+ -+#include -+ -+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 -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#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 m_surface; -+ -+ QMutex m_mutex; -+ QWaitCondition m_setupCondition; -+ QWaitCondition m_renderCondition; -+ GstFlowReturn m_renderReturn; -+ QList 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 -+ -+#if GST_CHECK_VERSION(1,0,0) -+ -+#include "qgstvideorenderersink_p.h" -+ -+QT_BEGIN_NAMESPACE -+typedef QGstVideoRendererSink QVideoSurfaceGstSink; -+QT_END_NAMESPACE -+ -+#else -+ - #include - - #include -@@ -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(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 - -+#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 - -+#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 - #include - -+#include -+ -+#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(user_data); -+ if (event && GST_EVENT_TYPE(event) == GST_EVENT_TAG) { - GstTagList *gstTags; - gst_event_parse_tag(event, &gstTags); - QMap 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(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(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 - #include "camerabinsession.h" - -+#include -+ -+#include -+ -+#if GST_CHECK_VERSION(1,0,0) -+#include -+#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 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 -+#if GST_CHECK_VERSION(1,0,0) -+# include -+#else -+# include -+#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 - - #ifdef HAVE_GST_PHOTOGRAPHY --#include -+# include -+# if !GST_CHECK_VERSION(1,0,0) -+typedef GstWhiteBalanceMode GstPhotographyWhiteBalanceMode; -+# endif - #endif - - QT_BEGIN_NAMESPACE -@@ -73,7 +76,7 @@ private: - CameraBinSession *m_session; - QMap m_values; - #ifdef HAVE_GST_PHOTOGRAPHY -- QMap m_mappedWbValues; -+ QMap 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 e4aa594..e669a57 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 -+#include - - #include - #include - -- - #if defined(HAVE_WIDGETS) - #include - #endif -@@ -164,8 +164,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; -@@ -263,7 +261,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 1ed663b..b62fbbf 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 &rate = qMakePair(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,28 +289,29 @@ static GstCaps *resolutionToCaps(const QSize &resolution, const QPair - void CameraBinSession::setupCaptureResolution() - { - QSize resolution = m_imageEncodeControl->imageSettings().resolution(); -- if (!resolution.isEmpty()) { -+ 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); - } - - GstElement *mfw_v4lsrc = 0; -@@ -349,15 +325,14 @@ void CameraBinSession::setupCaptureResolution() - } - } - -- 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); -- - if (mfw_v4lsrc) { - int capMode = 0; - if (resolution == QSize(320, 240)) -@@ -372,8 +347,8 @@ void CameraBinSession::setupCaptureResolution() - capMode = 5; - g_object_set(G_OBJECT(mfw_v4lsrc), "capture-mode", capMode, NULL); - } -- } else { -- g_object_set(m_camerabin, VIEWFINDER_CAPS_PROPERTY, NULL, NULL); -+ if (caps) -+ gst_caps_unref(caps); - } - - const qreal maxFps = m_viewfinderSettingsControl->maximumFrameRate(); -@@ -399,13 +374,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) -@@ -796,7 +775,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; -@@ -831,129 +810,57 @@ void CameraBinSession::setMetaData(const QMap &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 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 - } -@@ -1145,20 +1052,12 @@ QList< QPair > 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); -@@ -1169,7 +1068,7 @@ QList< QPair > CameraBinSession::supportedFrameRates(const QSize &frame - caps = gst_caps_make_writable(caps); - for (uint i=0; i > 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 > 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 - -@@ -1249,31 +1151,24 @@ QList CameraBinSession::supportedResolutions(QPair 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); - } -@@ -1283,7 +1178,7 @@ QList CameraBinSession::supportedResolutions(QPair rate, - caps = gst_caps_make_writable(caps); - for (uint i=0; i CameraBinSession::supportedResolutions(QPair 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 - - #include - -@@ -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 e77feeb..04e2966 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); - } -@@ -178,12 +176,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) { -@@ -209,17 +207,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(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 e5166d1..d6a5843 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; -@@ -87,6 +88,8 @@ private: - QGstreamerVideoWidgetControl *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 - #include -+#include - - #include - #include -@@ -52,7 +53,6 @@ - #include - #include - #include -- - #include - - 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 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 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; ydata, -- 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(info.data), info.size); -+ gst_buffer_unmap(buffer, &info); -+ } -+#else -+ f.write(reinterpret_cast(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 &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 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(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 - - #include -+#include - - #include -+#include - - QT_BEGIN_NAMESPACE - -@@ -70,7 +72,10 @@ public: - virtual QList 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 m_metaData; - -- QList 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 - #include - - #include -@@ -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 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 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 ddc828e..1fee6bf 100644 ---- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayerservice.cpp -+++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayerservice.cpp -@@ -51,7 +51,11 @@ - #include - - #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 -@@ -129,23 +137,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) { -@@ -170,28 +178,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(control); -- if (videoProbe) { -- if (m_session) { -- m_session->removeProbe(videoProbe); -- decreaseVideoRef(); -- } -- delete videoProbe; -- return; -- } -- -- QGstreamerAudioProbeControl* audioProbe = qobject_cast(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 0c5b406..a5dbe98 100644 ---- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayerservice.h -+++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayerservice.h -@@ -53,6 +53,8 @@ class QGstreamerVideoRenderer; - class QGstreamerVideoWindow; - class QGstreamerVideoWidgetControl; - class QGStreamerAvailabilityControl; -+class QGstreamerAudioProbeControl; -+class QGstreamerVideoProbeControl; - - class QGstreamerPlayerService : public QMediaService - { -@@ -71,6 +73,9 @@ private: - QGstreamerStreamsControl *m_streamsControl; - QGStreamerAvailabilityControl *m_availabilityControl; - -+ QGstreamerAudioProbeControl *m_audioProbeControl; -+ QGstreamerVideoProbeControl *m_videoProbeControl; -+ - QMediaControl *m_videoOutput; - QMediaControl *m_videoRenderer; - QGstreamerVideoWindow *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 - #include - #include -+#if !GST_CHECK_VERSION(1,0,0) - #include -+#endif - #include - #include - #include -@@ -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(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(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(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 m_streamTypes; - QMap m_playbin2StreamOffset; - -- QList m_videoProbes; -- QMutex m_videoProbeMutex; -- int m_videoBufferProbeId; -- -- QList 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 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(), 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); From 3970daa7f5cfcadaae3af55cac7d0c79f81bf120 Mon Sep 17 00:00:00 2001 From: Rex Dieter Date: Thu, 22 Oct 2015 13:46:10 -0500 Subject: [PATCH 3/6] drop gst support on el6 (QTBUG-48939) --- qt5-qtmultimedia.spec | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/qt5-qtmultimedia.spec b/qt5-qtmultimedia.spec index 7f81b13..1dc9246 100644 --- a/qt5-qtmultimedia.spec +++ b/qt5-qtmultimedia.spec @@ -19,15 +19,18 @@ ## define prerelease rc1 -%define gst 0.10 +%if (0%{?fedora} && 0%{?fedora} < 21) || (0%{?rhel} && 0%{?rhel} > 6) +%global gst 0.10 +%endif + %if 0%{?fedora} > 20 -%define gst 1.0 +%global gst 1.0 %endif Summary: Qt5 - Multimedia support Name: qt5-%{qt_module} Version: 5.5.1 -Release: 2%{?dist} +Release: 3%{?dist} # See LGPL_EXCEPTIONS.txt, LICENSE.GPL3, respectively, for exception details License: LGPLv2 with exceptions or GPLv3 with exceptions @@ -41,16 +44,18 @@ Patch1: qtmultimedia-opensource-src-5.5.1-el6.patch BuildRequires: qt5-qtbase-devel >= %{version} BuildRequires: qt5-qtdeclarative-devel >= %{version} BuildRequires: pkgconfig(alsa) +%if 0%{?gst:1} %if "%{?gst}" == "0.10" BuildRequires: pkgconfig(gstreamer-interfaces-0.10) %endif -BuildRequires: pkgconfig(gstreamer-%{gst}) +BuildRequires: pkgconfig(gstreamer-%{gst}) >= 0.10.31 BuildRequires: pkgconfig(gstreamer-app-%{gst}) BuildRequires: pkgconfig(gstreamer-audio-%{gst}) BuildRequires: pkgconfig(gstreamer-base-%{gst}) BuildRequires: pkgconfig(gstreamer-pbutils-%{gst}) BuildRequires: pkgconfig(gstreamer-plugins-bad-%{gst}) BuildRequires: pkgconfig(gstreamer-video-%{gst}) +%endif BuildRequires: pkgconfig(libpulse) pkgconfig(libpulse-mainloop-glib) %if 0%{?openal} BuildRequires: pkgconfig(openal) @@ -140,7 +145,9 @@ popd %{_qt5_libdir}/libQt5Multimedia.so.5* %{_qt5_libdir}/libQt5MultimediaQuick_p.so.5* %{_qt5_libdir}/libQt5MultimediaWidgets.so.5* +%if 0%{?gst:1} %{_qt5_libdir}/libqgsttools_p.so.1* +%endif %if 0%{?openal} %{_qt5_archdatadir}/qml/QtAudioEngine/ %endif @@ -162,8 +169,10 @@ popd %{_qt5_libdir}/libQt5MultimediaQuick_p.prl %{_qt5_libdir}/libQt5MultimediaWidgets.so %{_qt5_libdir}/libQt5MultimediaWidgets.prl +%if 0%{?gst:1} %{_qt5_libdir}/libqgsttools_p.so %{_qt5_libdir}/libqgsttools_p.prl +%endif %{_qt5_libdir}/cmake/Qt5Multimedia/Qt5MultimediaConfig*.cmake %{_qt5_libdir}/cmake/Qt5MultimediaWidgets/Qt5MultimediaWidgetsConfig*.cmake %{_qt5_libdir}/pkgconfig/Qt5Multimedia.pc @@ -187,6 +196,9 @@ popd %changelog +* Thu Oct 22 2015 Rex Dieter 5.5.1-3 +- drop gst support on el6 (QTBUG-48939) + * Thu Oct 15 2015 Helio Chissini de Castro - 5.5.1-2 - Update to final release 5.5.1 From 33f109595af4ca2ac21987229bf819ec730b09be Mon Sep 17 00:00:00 2001 From: Rex Dieter Date: Mon, 26 Oct 2015 07:00:57 -0500 Subject: [PATCH 4/6] pull in upstream fixes, QTBUG-48939 in particular --- ...sions-of-camera-related-meta-objects.patch | 100 ++++ ...declaration-in-QVideoOutputOrientati.patch | 32 ++ ...fix-compilation-with-version-0.10.31.patch | 445 ++++++++++++++++++ qt5-qtmultimedia.spec | 20 +- qtmultimedia-opensource-src-5.5.1-el6.patch | 97 ---- 5 files changed, 589 insertions(+), 105 deletions(-) create mode 100644 0007-Fixed-revisions-of-camera-related-meta-objects.patch create mode 100644 0010-Fix-signal-slot-declaration-in-QVideoOutputOrientati.patch create mode 100644 0011-GStreamer-fix-compilation-with-version-0.10.31.patch delete mode 100644 qtmultimedia-opensource-src-5.5.1-el6.patch diff --git a/0007-Fixed-revisions-of-camera-related-meta-objects.patch b/0007-Fixed-revisions-of-camera-related-meta-objects.patch new file mode 100644 index 0000000..5b0699b --- /dev/null +++ b/0007-Fixed-revisions-of-camera-related-meta-objects.patch @@ -0,0 +1,100 @@ +From 99f6cf5f282c0d3d7192d5e87b745873e159c93d Mon Sep 17 00:00:00 2001 +From: Marco Benelli +Date: Tue, 15 Sep 2015 13:37:57 +0200 +Subject: [PATCH 07/11] Fixed revisions of camera-related meta objects. + +Change-Id: I91fe90122d53ce12322cecac8282ef9622869b71 +Reviewed-by: Yoann Lopes +--- + src/imports/multimedia/multimedia.cpp | 6 +++--- + src/imports/multimedia/plugins.qmltypes | 20 ++++++++++++++------ + 2 files changed, 17 insertions(+), 9 deletions(-) + +diff --git a/src/imports/multimedia/multimedia.cpp b/src/imports/multimedia/multimedia.cpp +index 652359f..4b31068 100644 +--- a/src/imports/multimedia/multimedia.cpp ++++ b/src/imports/multimedia/multimedia.cpp +@@ -97,7 +97,7 @@ public: + trUtf8("CameraImageProcessing is provided by Camera")); + + // 5.2 types +- qmlRegisterRevision(uri, 5, 2); ++ qmlRegisterType(uri, 5, 2, "VideoOutput"); + + // 5.3 types + // Nothing changed, but adding "import QtMultimedia 5.3" in QML will fail unless at +@@ -106,13 +106,13 @@ public: + + // 5.4 types + qmlRegisterSingletonType(uri, 5, 4, "QtMultimedia", multimedia_global_object); +- qmlRegisterRevision(uri, 5, 4); ++ qmlRegisterType(uri, 5, 4, "Camera"); + qmlRegisterUncreatableType(uri, 5, 4, "CameraViewfinder", + trUtf8("CameraViewfinder is provided by Camera")); + + // 5.5 types + qmlRegisterUncreatableType(uri, 5, 5, "CameraImageProcessing", trUtf8("CameraImageProcessing is provided by Camera")); +- qmlRegisterRevision(uri, 5, 5); ++ qmlRegisterType(uri, 5, 5, "Camera"); + + qmlRegisterType(); + qmlRegisterType(); +diff --git a/src/imports/multimedia/plugins.qmltypes b/src/imports/multimedia/plugins.qmltypes +index d01c988..53d7cb4 100644 +--- a/src/imports/multimedia/plugins.qmltypes ++++ b/src/imports/multimedia/plugins.qmltypes +@@ -1,4 +1,4 @@ +-import QtQuick.tooling 1.1 ++import QtQuick.tooling 1.2 + + // This file describes the plugin-supplied types contained in the library. + // It is used for QML tooling purposes only. +@@ -7,6 +7,7 @@ import QtQuick.tooling 1.1 + // 'qmlplugindump -nonrelocatable QtMultimedia 5.5' + + Module { ++ dependencies: ["QtQuick 2.0"] + Component { + name: "QAbstractVideoFilter" + prototype: "QObject" +@@ -244,8 +245,12 @@ Module { + Component { + name: "QDeclarativeCamera" + prototype: "QObject" +- exports: ["QtMultimedia/Camera 5.0"] +- exportMetaObjectRevisions: [0] ++ exports: [ ++ "QtMultimedia/Camera 5.0", ++ "QtMultimedia/Camera 5.4", ++ "QtMultimedia/Camera 5.5" ++ ] ++ exportMetaObjectRevisions: [0, 1, 2] + Enum { + name: "Position" + values: { +@@ -517,7 +522,7 @@ Module { + name: "supportedViewfinderFrameRateRanges" + revision: 2 + type: "QJSValue" +- Parameter { name: "resolution"; type: "QSize" } ++ Parameter { name: "resolution"; type: "QJSValue" } + } + Method { name: "supportedViewfinderFrameRateRanges"; revision: 2; type: "QJSValue" } + } +@@ -1497,8 +1502,11 @@ Module { + name: "QDeclarativeVideoOutput" + defaultProperty: "data" + prototype: "QQuickItem" +- exports: ["QtMultimedia/VideoOutput 5.0"] +- exportMetaObjectRevisions: [0] ++ exports: [ ++ "QtMultimedia/VideoOutput 5.0", ++ "QtMultimedia/VideoOutput 5.2" ++ ] ++ exportMetaObjectRevisions: [0, 2] + Enum { + name: "FillMode" + values: { +-- +1.9.3 + diff --git a/0010-Fix-signal-slot-declaration-in-QVideoOutputOrientati.patch b/0010-Fix-signal-slot-declaration-in-QVideoOutputOrientati.patch new file mode 100644 index 0000000..ee8e688 --- /dev/null +++ b/0010-Fix-signal-slot-declaration-in-QVideoOutputOrientati.patch @@ -0,0 +1,32 @@ +From 0cf41ef53f7b336509ed7d1ae6518655276af70f Mon Sep 17 00:00:00 2001 +From: Yoann Lopes +Date: Tue, 29 Sep 2015 16:03:15 +0200 +Subject: [PATCH 10/11] Fix signal/slot declaration in + QVideoOutputOrientationHandler. + +Change-Id: I03cdd677feaf06ac2d61682cab46232f983e6494 +Reviewed-by: Christian Stromme +--- + src/multimedia/video/qvideooutputorientationhandler_p.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/multimedia/video/qvideooutputorientationhandler_p.h b/src/multimedia/video/qvideooutputorientationhandler_p.h +index 14a0c4a..28629ad 100644 +--- a/src/multimedia/video/qvideooutputorientationhandler_p.h ++++ b/src/multimedia/video/qvideooutputorientationhandler_p.h +@@ -48,10 +48,10 @@ public: + + int currentOrientation() const; + +-signals: ++Q_SIGNALS: + void orientationChanged(int angle); + +-private slots: ++private Q_SLOTS: + void screenOrientationChanged(Qt::ScreenOrientation orientation); + + private: +-- +1.9.3 + diff --git a/0011-GStreamer-fix-compilation-with-version-0.10.31.patch b/0011-GStreamer-fix-compilation-with-version-0.10.31.patch new file mode 100644 index 0000000..b66338d --- /dev/null +++ b/0011-GStreamer-fix-compilation-with-version-0.10.31.patch @@ -0,0 +1,445 @@ +From 3d3d2a4967ba079a3e6df82cdc89f839865e6649 Mon Sep 17 00:00:00 2001 +From: Yoann Lopes +Date: Fri, 16 Oct 2015 14:15:23 +0200 +Subject: [PATCH 11/11] GStreamer: fix compilation with version < 0.10.31. + +Qt 5.4 and earlier required GStreamer 0.10.24 as minimum version. +Qt 5.5 added code that requires 0.10.31, this code is now ifdef'd +and we now support again 0.10.24. + +Task-number: QTBUG-48353 +Change-Id: Ie708a33c0515874b003ce26a3400475075d316ca +Reviewed-by: Christian Stromme +--- + src/gsttools/qgstreamervideooverlay.cpp | 15 +++-- + src/gsttools/qgstutils.cpp | 69 +++++++++++++++++++++- + src/gsttools/qvideosurfacegstsink.cpp | 31 +++++++++- + src/multimedia/gsttools_headers/qgstutils_p.h | 2 + + .../gsttools_headers/qvideosurfacegstsink_p.h | 5 ++ + .../qgstreameraudiodecoderserviceplugin.cpp | 10 +++- + .../qgstreamercapturemetadatacontrol.cpp | 2 - + .../qgstreamercaptureserviceplugin.cpp | 7 +++ + .../mediacapture/qgstreamercapturesession.cpp | 16 ++--- + .../mediaplayer/qgstreamermetadataprovider.cpp | 5 +- + .../mediaplayer/qgstreamerplayerserviceplugin.cpp | 7 +++ + .../mediaplayer/qgstreamerplayersession.cpp | 8 +-- + 12 files changed, 147 insertions(+), 30 deletions(-) + +diff --git a/src/gsttools/qgstreamervideooverlay.cpp b/src/gsttools/qgstreamervideooverlay.cpp +index 1dcedbc..06f93ef 100644 +--- a/src/gsttools/qgstreamervideooverlay.cpp ++++ b/src/gsttools/qgstreamervideooverlay.cpp +@@ -148,9 +148,7 @@ GstElement *QGstreamerVideoOverlay::findBestVideoSink() const + + // If none of the known video sinks are available, try to find one that implements the + // GstVideoOverlay interface and has autoplugging rank. +- GList *list = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_SINK | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO, +- GST_RANK_MARGINAL); +- ++ GList *list = qt_gst_video_sinks(); + for (GList *item = list; item != NULL; item = item->next) { + GstElementFactory *f = GST_ELEMENT_FACTORY(item->data); + +@@ -242,12 +240,17 @@ void QGstreamerVideoOverlay::setRenderRectangle(const QRect &rect) + h = rect.height(); + } + +-#if !GST_CHECK_VERSION(1,0,0) ++#if GST_CHECK_VERSION(1,0,0) ++ if (m_videoSink && GST_IS_VIDEO_OVERLAY(m_videoSink)) ++ gst_video_overlay_set_render_rectangle(GST_VIDEO_OVERLAY(m_videoSink), x, y, w, h); ++#elif GST_CHECK_VERSION(0, 10, 29) + if (m_videoSink && GST_IS_X_OVERLAY(m_videoSink)) + gst_x_overlay_set_render_rectangle(GST_X_OVERLAY(m_videoSink), x, y , w , h); + #else +- if (m_videoSink && GST_IS_VIDEO_OVERLAY(m_videoSink)) +- gst_video_overlay_set_render_rectangle(GST_VIDEO_OVERLAY(m_videoSink), x, y, w, h); ++ Q_UNUSED(x) ++ Q_UNUSED(y) ++ Q_UNUSED(w) ++ Q_UNUSED(h) + #endif + } + +diff --git a/src/gsttools/qgstutils.cpp b/src/gsttools/qgstutils.cpp +index b13038c..50a5623 100644 +--- a/src/gsttools/qgstutils.cpp ++++ b/src/gsttools/qgstutils.cpp +@@ -774,6 +774,7 @@ QSet QGstUtils::supportedMimeTypes(bool (*isValidFactory)(GstElementFac + return supportedMimeTypes; + } + ++#if GST_CHECK_VERSION(1, 0, 0) + namespace { + + struct ColorFormat { QImage::Format imageFormat; GstVideoFormat gstFormat; }; +@@ -786,6 +787,7 @@ static const ColorFormat qt_colorLookup[] = + }; + + } ++#endif + + #if GST_CHECK_VERSION(1,0,0) + QImage QGstUtils::bufferToImage(GstBuffer *buffer, const GstVideoInfo &videoInfo) +@@ -1212,6 +1214,7 @@ void QGstUtils::setMetaData(GstElement *element, const QMap(g_type_class_peek_parent(g_class)); + +- GstVideoSinkClass *video_sink_class = reinterpret_cast(g_class); +- video_sink_class->show_frame = QVideoSurfaceGstSink::show_frame; +- + GstBaseSinkClass *base_sink_class = reinterpret_cast(g_class); + base_sink_class->get_caps = QVideoSurfaceGstSink::get_caps; + base_sink_class->set_caps = QVideoSurfaceGstSink::set_caps; +@@ -387,6 +384,14 @@ void QVideoSurfaceGstSink::class_init(gpointer g_class, gpointer class_data) + base_sink_class->stop = QVideoSurfaceGstSink::stop; + base_sink_class->unlock = QVideoSurfaceGstSink::unlock; + ++#if GST_CHECK_VERSION(0, 10, 25) ++ GstVideoSinkClass *video_sink_class = reinterpret_cast(g_class); ++ video_sink_class->show_frame = QVideoSurfaceGstSink::show_frame; ++#else ++ base_sink_class->preroll = QVideoSurfaceGstSink::preroll; ++ base_sink_class->render = QVideoSurfaceGstSink::render; ++#endif ++ + GstElementClass *element_class = reinterpret_cast(g_class); + element_class->change_state = QVideoSurfaceGstSink::change_state; + +@@ -674,10 +679,30 @@ gboolean QVideoSurfaceGstSink::unlock(GstBaseSink *base) + return TRUE; + } + ++#if GST_CHECK_VERSION(0, 10, 25) + GstFlowReturn QVideoSurfaceGstSink::show_frame(GstVideoSink *base, GstBuffer *buffer) + { + VO_SINK(base); + return sink->delegate->render(buffer); + } ++#else ++GstFlowReturn QVideoSurfaceGstSink::preroll(GstBaseSink *base, GstBuffer *buffer) ++{ ++ VO_SINK(base); ++ gboolean showPrerollFrame = true; ++ g_object_get(G_OBJECT(sink), "show-preroll-frame", &showPrerollFrame, NULL); ++ ++ if (showPrerollFrame) ++ return sink->delegate->render(buffer); ++ ++ return GST_FLOW_OK; ++} ++ ++GstFlowReturn QVideoSurfaceGstSink::render(GstBaseSink *base, GstBuffer *buffer) ++{ ++ VO_SINK(base); ++ return sink->delegate->render(buffer); ++} ++#endif + + QT_END_NAMESPACE +diff --git a/src/multimedia/gsttools_headers/qgstutils_p.h b/src/multimedia/gsttools_headers/qgstutils_p.h +index 31fb858..cf677c3 100644 +--- a/src/multimedia/gsttools_headers/qgstutils_p.h ++++ b/src/multimedia/gsttools_headers/qgstutils_p.h +@@ -150,6 +150,8 @@ gboolean qt_gst_element_query_position(GstElement *element, GstFormat format, gi + gboolean qt_gst_element_query_duration(GstElement *element, GstFormat format, gint64 *cur); + GstCaps *qt_gst_caps_normalize(GstCaps *caps); + const gchar *qt_gst_element_get_factory_name(GstElement *element); ++gboolean qt_gst_caps_can_intersect(const GstCaps * caps1, const GstCaps * caps2); ++GList *qt_gst_video_sinks(); + + QDebug operator <<(QDebug debug, GstCaps *caps); + +diff --git a/src/multimedia/gsttools_headers/qvideosurfacegstsink_p.h b/src/multimedia/gsttools_headers/qvideosurfacegstsink_p.h +index a1ef561..9c04b98 100644 +--- a/src/multimedia/gsttools_headers/qvideosurfacegstsink_p.h ++++ b/src/multimedia/gsttools_headers/qvideosurfacegstsink_p.h +@@ -157,7 +157,12 @@ private: + + static gboolean unlock(GstBaseSink *sink); + ++#if GST_CHECK_VERSION(0, 10, 25) + static GstFlowReturn show_frame(GstVideoSink *sink, GstBuffer *buffer); ++#else ++ static GstFlowReturn preroll(GstBaseSink *sink, GstBuffer *buffer); ++ static GstFlowReturn render(GstBaseSink *sink, GstBuffer *buffer); ++#endif + + private: + QVideoSurfaceGstDelegate *delegate; +diff --git a/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderserviceplugin.cpp b/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderserviceplugin.cpp +index 6afee94..f919bb1 100644 +--- a/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderserviceplugin.cpp ++++ b/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderserviceplugin.cpp +@@ -70,9 +70,15 @@ QMultimedia::SupportEstimate QGstreamerAudioDecoderServicePlugin::hasSupport(con + + static bool isDecoderOrDemuxer(GstElementFactory *factory) + { ++#if GST_CHECK_VERSION(0, 10, 31) + 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); ++ || gst_element_factory_list_is_type(factory, GST_ELEMENT_FACTORY_TYPE_DECODER ++ | GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO); ++#else ++ return (factory ++ && (qstrcmp(factory->details.klass, "Codec/Decoder/Audio") == 0 ++ || qstrcmp(factory->details.klass, "Codec/Demux") == 0)); ++#endif + } + + void QGstreamerAudioDecoderServicePlugin::updateSupportedMimeTypes() const +diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercapturemetadatacontrol.cpp b/src/plugins/gstreamer/mediacapture/qgstreamercapturemetadatacontrol.cpp +index 0018209..fca38ec 100644 +--- a/src/plugins/gstreamer/mediacapture/qgstreamercapturemetadatacontrol.cpp ++++ b/src/plugins/gstreamer/mediacapture/qgstreamercapturemetadatacontrol.cpp +@@ -77,9 +77,7 @@ static const QGstreamerMetaDataKeyLookup *qt_gstreamerMetaDataKeys() + metadataKeys->insert(QMediaMetaData::AlbumTitle, GST_TAG_ALBUM); + metadataKeys->insert(QMediaMetaData::AlbumArtist, GST_TAG_ARTIST); + metadataKeys->insert(QMediaMetaData::ContributingArtist, GST_TAG_PERFORMER); +-#if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 19) + metadataKeys->insert(QMediaMetaData::Composer, GST_TAG_COMPOSER); +-#endif + //metadataKeys->insert(QMediaMetaData::Conductor, 0); + //metadataKeys->insert(QMediaMetaData::Lyrics, 0); + //metadataKeys->insert(QMediaMetaData::Mood, 0); +diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercaptureserviceplugin.cpp b/src/plugins/gstreamer/mediacapture/qgstreamercaptureserviceplugin.cpp +index a9c66f8..8cbdb67 100644 +--- a/src/plugins/gstreamer/mediacapture/qgstreamercaptureserviceplugin.cpp ++++ b/src/plugins/gstreamer/mediacapture/qgstreamercaptureserviceplugin.cpp +@@ -113,8 +113,15 @@ QMultimedia::SupportEstimate QGstreamerCaptureServicePlugin::hasSupport(const QS + + static bool isEncoderOrMuxer(GstElementFactory *factory) + { ++#if GST_CHECK_VERSION(0, 10, 31) + 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); ++#else ++ return (factory ++ && (qstrcmp(factory->details.klass, "Codec/Encoder/Audio") == 0 ++ || qstrcmp(factory->details.klass, "Codec/Encoder/Video") == 0 ++ || qstrcmp(factory->details.klass, "Codec/Muxer") == 0 )); ++#endif + } + + void QGstreamerCaptureServicePlugin::updateSupportedMimeTypes() const +diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp b/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp +index 77d8987..31ffa50 100644 +--- a/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp ++++ b/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp +@@ -628,12 +628,12 @@ bool QGstreamerCaptureSession::rebuildGraph(QGstreamerCaptureSession::PipelineMo + } + + dumpGraph( QString("rebuild_graph_%1_%2").arg(m_pipelineMode).arg(newMode) ); ++#ifdef QT_GST_CAPTURE_DEBUG + if (m_encodeBin) { + QString fileName = QString("rebuild_graph_encode_%1_%2").arg(m_pipelineMode).arg(newMode); +-#if !(GST_DISABLE_GST_DEBUG) && (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 19) +- _gst_debug_bin_to_dot_file(GST_BIN(m_encodeBin), GST_DEBUG_GRAPH_SHOW_ALL, fileName.toLatin1()); +-#endif ++ GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(m_encodeBin), GST_DEBUG_GRAPH_SHOW_ALL, fileName.toLatin1()); + } ++#endif + + if (ok) { + addAudioBufferProbe(); +@@ -657,12 +657,12 @@ bool QGstreamerCaptureSession::rebuildGraph(QGstreamerCaptureSession::PipelineMo + + void QGstreamerCaptureSession::dumpGraph(const QString &fileName) + { +-#if !(GST_DISABLE_GST_DEBUG) && (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 19) +- _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()); ++#ifdef QT_GST_CAPTURE_DEBUG ++ 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); ++ Q_UNUSED(fileName) + #endif + } + +diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp b/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp +index ac0fe2a..fdf4306 100644 +--- a/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp ++++ b/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp +@@ -76,13 +76,10 @@ static const QGstreamerMetaDataKeyLookup *qt_gstreamerMetaDataKeys() + + // Music + metadataKeys->insert(GST_TAG_ALBUM, QMediaMetaData::AlbumTitle); +-#if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 25) ++#if GST_CHECK_VERSION(0, 10, 25) + metadataKeys->insert(GST_TAG_ALBUM_ARTIST, QMediaMetaData::AlbumArtist); + #endif + metadataKeys->insert(GST_TAG_ARTIST, QMediaMetaData::ContributingArtist); +-#if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 19) +- metadataKeys->insert(GST_TAG_COMPOSER, QMediaMetaData::Composer); +-#endif + //metadataKeys->insert(0, QMediaMetaData::Conductor); + //metadataKeys->insert(0, QMediaMetaData::Lyrics); + //metadataKeys->insert(0, QMediaMetaData::Mood); +diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayerserviceplugin.cpp b/src/plugins/gstreamer/mediaplayer/qgstreamerplayerserviceplugin.cpp +index 004d561..b895c4d 100644 +--- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayerserviceplugin.cpp ++++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayerserviceplugin.cpp +@@ -83,8 +83,15 @@ QMultimedia::SupportEstimate QGstreamerPlayerServicePlugin::hasSupport(const QSt + + static bool isDecoderOrDemuxer(GstElementFactory *factory) + { ++#if GST_CHECK_VERSION(0, 10 ,31) + 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); ++#else ++ return (factory ++ && (qstrcmp(factory->details.klass, "Codec/Decoder/Audio") == 0 ++ || qstrcmp(factory->details.klass, "Codec/Decoder/Video") == 0 ++ || qstrcmp(factory->details.klass, "Codec/Demux") == 0 )); ++#endif + } + + void QGstreamerPlayerServicePlugin::updateSupportedMimeTypes() const +diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp b/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp +index 4dce341..c3d20e7 100644 +--- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp ++++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp +@@ -388,7 +388,7 @@ QMediaTimeRange QGstreamerPlayerSession::availablePlaybackRanges() const + if (duration() <= 0) + return ranges; + +-#if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 31) ++#if GST_CHECK_VERSION(0, 10, 31) + //GST_FORMAT_TIME would be more appropriate, but unfortunately it's not supported. + //with GST_FORMAT_PERCENT media is treated as encoded with constant bitrate. + GstQuery* query = gst_query_new_buffering(GST_FORMAT_PERCENT); +@@ -1637,7 +1637,7 @@ void QGstreamerPlayerSession::updateMuted() + } + } + +-#if (GST_VERSION_MAJOR == 0) && ((GST_VERSION_MINOR < 10) || (GST_VERSION_MICRO < 33)) ++#if !GST_CHECK_VERSION(0, 10, 33) + static gboolean factory_can_src_any_caps (GstElementFactory *factory, const GstCaps *caps) + { + GList *templates; +@@ -1653,7 +1653,7 @@ static gboolean factory_can_src_any_caps (GstElementFactory *factory, const GstC + if (templ->direction == GST_PAD_SRC) { + GstCaps *templcaps = gst_static_caps_get(&templ->static_caps); + +- if (gst_caps_can_intersect(caps, templcaps)) { ++ if (qt_gst_caps_can_intersect(caps, templcaps)) { + gst_caps_unref(templcaps); + return TRUE; + } +@@ -1685,7 +1685,7 @@ GstAutoplugSelectResult QGstreamerPlayerSession::handleAutoplugSelect(GstBin *bi + GstCaps *sinkCaps = gst_pad_get_caps(sinkPad); + #endif + +-#if (GST_VERSION_MAJOR == 0) && ((GST_VERSION_MINOR < 10) || (GST_VERSION_MICRO < 33)) ++#if !GST_CHECK_VERSION(0, 10, 33) + if (!factory_can_src_any_caps(factory, sinkCaps)) + #else + if (!gst_element_factory_can_src_any_caps(factory, sinkCaps)) +-- +1.9.3 + diff --git a/qt5-qtmultimedia.spec b/qt5-qtmultimedia.spec index 1dc9246..8e199d1 100644 --- a/qt5-qtmultimedia.spec +++ b/qt5-qtmultimedia.spec @@ -19,9 +19,7 @@ ## define prerelease rc1 -%if (0%{?fedora} && 0%{?fedora} < 21) || (0%{?rhel} && 0%{?rhel} > 6) %global gst 0.10 -%endif %if 0%{?fedora} > 20 %global gst 1.0 @@ -30,16 +28,17 @@ Summary: Qt5 - Multimedia support Name: qt5-%{qt_module} Version: 5.5.1 -Release: 3%{?dist} +Release: 4%{?dist} # See LGPL_EXCEPTIONS.txt, LICENSE.GPL3, respectively, for exception details License: LGPLv2 with exceptions or GPLv3 with exceptions Url: http://www.qt.io Source0: http://download.qt.io/official_releases/qt/5.5/%{version}%{?prerelease:-%{prerelease}}/submodules/%{qt_module}-opensource-src-%{version}%{?prerelease:-%{prerelease}}.tar.xz -# try to support el6's older gstreamer-0.10.29 -# https://bugreports.qt.io/browse/QTBUG-48939 -Patch1: qtmultimedia-opensource-src-5.5.1-el6.patch +## upstream patches +Patch7: 0007-Fixed-revisions-of-camera-related-meta-objects.patch +Patch10: 0010-Fix-signal-slot-declaration-in-QVideoOutputOrientati.patch +Patch11: 0011-GStreamer-fix-compilation-with-version-0.10.31.patch BuildRequires: qt5-qtbase-devel >= %{version} BuildRequires: qt5-qtdeclarative-devel >= %{version} @@ -48,7 +47,7 @@ BuildRequires: pkgconfig(alsa) %if "%{?gst}" == "0.10" BuildRequires: pkgconfig(gstreamer-interfaces-0.10) %endif -BuildRequires: pkgconfig(gstreamer-%{gst}) >= 0.10.31 +BuildRequires: pkgconfig(gstreamer-%{gst}) >= 0.10.24 BuildRequires: pkgconfig(gstreamer-app-%{gst}) BuildRequires: pkgconfig(gstreamer-audio-%{gst}) BuildRequires: pkgconfig(gstreamer-base-%{gst}) @@ -99,7 +98,9 @@ Requires: %{name}%{?_isa} = %{version}-%{release} %prep %setup -q -n %{qt_module}-opensource-src-%{version}%{?prerelease:-%{prerelease}} -%patch1 -p1 -b .el6 +%patch7 -p1 -b .0007 +%patch10 -p1 -b .0010 +%patch11 -p1 -b .0011 %build @@ -196,6 +197,9 @@ popd %changelog +* Mon Oct 26 2015 Rex Dieter 5.5.1-4 +- pull in upstream fixes, QTBUG-48939 in particular + * Thu Oct 22 2015 Rex Dieter 5.5.1-3 - drop gst support on el6 (QTBUG-48939) diff --git a/qtmultimedia-opensource-src-5.5.1-el6.patch b/qtmultimedia-opensource-src-5.5.1-el6.patch deleted file mode 100644 index 4126544..0000000 --- a/qtmultimedia-opensource-src-5.5.1-el6.patch +++ /dev/null @@ -1,97 +0,0 @@ -diff -up qtmultimedia-opensource-src-5.5.1/src/gsttools/qgstreamervideooverlay.cpp.el6 qtmultimedia-opensource-src-5.5.1/src/gsttools/qgstreamervideooverlay.cpp ---- qtmultimedia-opensource-src-5.5.1/src/gsttools/qgstreamervideooverlay.cpp.el6 2015-10-12 23:35:43.000000000 -0500 -+++ qtmultimedia-opensource-src-5.5.1/src/gsttools/qgstreamervideooverlay.cpp 2015-10-22 10:14:22.129635875 -0500 -@@ -146,6 +146,7 @@ GstElement *QGstreamerVideoOverlay::find - } - } - -+#if GST_CHECK_VERSION(0,10,31) - // If none of the known video sinks are available, try to find one that implements the - // GstVideoOverlay interface and has autoplugging rank. - GList *list = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_SINK | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO, -@@ -170,6 +171,7 @@ GstElement *QGstreamerVideoOverlay::find - gst_plugin_feature_list_free(list); - - return choice; -+#endif - } - - GstElement *QGstreamerVideoOverlay::videoSink() const -diff -up qtmultimedia-opensource-src-5.5.1/src/gsttools/qgstutils.cpp.el6 qtmultimedia-opensource-src-5.5.1/src/gsttools/qgstutils.cpp ---- qtmultimedia-opensource-src-5.5.1/src/gsttools/qgstutils.cpp.el6 2015-10-12 23:35:43.000000000 -0500 -+++ qtmultimedia-opensource-src-5.5.1/src/gsttools/qgstutils.cpp 2015-10-22 09:49:55.726563754 -0500 -@@ -782,7 +782,9 @@ 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 }, -+#if GST_CHECK_VERSION(0,30,0) - { QImage::Format_RGB16 , GST_VIDEO_FORMAT_RGB16 } -+#endif - }; - - } -@@ -1212,6 +1214,7 @@ void QGstUtils::setMetaData(GstElement * - tagValue.toDouble(), - NULL); - break; -+#if GST_CHECK_VERSION(0,10,31) - case QVariant::DateTime: { - QDateTime date = tagValue.toDateTime().toLocalTime(); - gst_tag_setter_add_tags(GST_TAG_SETTER(element), -@@ -1223,6 +1226,7 @@ void QGstUtils::setMetaData(GstElement * - NULL); - break; - } -+#endif - default: - break; - } -diff -up qtmultimedia-opensource-src-5.5.1/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderserviceplugin.cpp.el6 qtmultimedia-opensource-src-5.5.1/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderserviceplugin.cpp ---- qtmultimedia-opensource-src-5.5.1/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderserviceplugin.cpp.el6 2015-10-12 23:35:43.000000000 -0500 -+++ qtmultimedia-opensource-src-5.5.1/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderserviceplugin.cpp 2015-10-22 09:49:55.726563754 -0500 -@@ -70,9 +70,13 @@ QMultimedia::SupportEstimate QGstreamerA - - static bool isDecoderOrDemuxer(GstElementFactory *factory) - { -+#if GST_CHECK_VERSION(0,10,31) - 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); -+#else -+ return false; -+#endif - } - - void QGstreamerAudioDecoderServicePlugin::updateSupportedMimeTypes() const -diff -up qtmultimedia-opensource-src-5.5.1/src/plugins/gstreamer/mediacapture/qgstreamercaptureserviceplugin.cpp.el6 qtmultimedia-opensource-src-5.5.1/src/plugins/gstreamer/mediacapture/qgstreamercaptureserviceplugin.cpp ---- qtmultimedia-opensource-src-5.5.1/src/plugins/gstreamer/mediacapture/qgstreamercaptureserviceplugin.cpp.el6 2015-10-12 23:35:42.000000000 -0500 -+++ qtmultimedia-opensource-src-5.5.1/src/plugins/gstreamer/mediacapture/qgstreamercaptureserviceplugin.cpp 2015-10-22 09:53:38.620573847 -0500 -@@ -113,8 +113,12 @@ QMultimedia::SupportEstimate QGstreamerC - - static bool isEncoderOrMuxer(GstElementFactory *factory) - { -+#if GST_CHECK_VERSION(0,10,31) - 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); -+#else -+ return false; -+#endif - } - - void QGstreamerCaptureServicePlugin::updateSupportedMimeTypes() const -diff -up qtmultimedia-opensource-src-5.5.1/src/plugins/gstreamer/mediaplayer/qgstreamerplayerserviceplugin.cpp.el6 qtmultimedia-opensource-src-5.5.1/src/plugins/gstreamer/mediaplayer/qgstreamerplayerserviceplugin.cpp ---- qtmultimedia-opensource-src-5.5.1/src/plugins/gstreamer/mediaplayer/qgstreamerplayerserviceplugin.cpp.el6 2015-10-12 23:35:42.000000000 -0500 -+++ qtmultimedia-opensource-src-5.5.1/src/plugins/gstreamer/mediaplayer/qgstreamerplayerserviceplugin.cpp 2015-10-22 09:52:40.403569549 -0500 -@@ -83,8 +83,12 @@ QMultimedia::SupportEstimate QGstreamerP - - static bool isDecoderOrDemuxer(GstElementFactory *factory) - { -+#if GST_CHECK_VERSION(0,10,31) - 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); -+#else -+ return false; -+#endif - } - - void QGstreamerPlayerServicePlugin::updateSupportedMimeTypes() const From 809294c0c410684271295457ddaf76fe41854a3d Mon Sep 17 00:00:00 2001 From: Jan Grulich Date: Mon, 7 Dec 2015 13:29:50 +0100 Subject: [PATCH 5/6] 5.6.0 (sync with qt5 copr) --- .gitignore | 1 + ...sions-of-camera-related-meta-objects.patch | 100 ---- ...declaration-in-QVideoOutputOrientati.patch | 32 -- ...fix-compilation-with-version-0.10.31.patch | 445 ------------------ qt5-qtmultimedia.spec | 34 +- sources | 2 +- 6 files changed, 13 insertions(+), 601 deletions(-) delete mode 100644 0007-Fixed-revisions-of-camera-related-meta-objects.patch delete mode 100644 0010-Fix-signal-slot-declaration-in-QVideoOutputOrientati.patch delete mode 100644 0011-GStreamer-fix-compilation-with-version-0.10.31.patch diff --git a/.gitignore b/.gitignore index 3837b1a..6c2c08b 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ /qtmultimedia-opensource-src-5.5.0.tar.xz /qtmultimedia-opensource-src-5.5.1-rc1.tar.xz /qtmultimedia-opensource-src-5.5.1.tar.xz +/qtmultimedia-opensource-src-5.6.0-beta1.tar.xz diff --git a/0007-Fixed-revisions-of-camera-related-meta-objects.patch b/0007-Fixed-revisions-of-camera-related-meta-objects.patch deleted file mode 100644 index 5b0699b..0000000 --- a/0007-Fixed-revisions-of-camera-related-meta-objects.patch +++ /dev/null @@ -1,100 +0,0 @@ -From 99f6cf5f282c0d3d7192d5e87b745873e159c93d Mon Sep 17 00:00:00 2001 -From: Marco Benelli -Date: Tue, 15 Sep 2015 13:37:57 +0200 -Subject: [PATCH 07/11] Fixed revisions of camera-related meta objects. - -Change-Id: I91fe90122d53ce12322cecac8282ef9622869b71 -Reviewed-by: Yoann Lopes ---- - src/imports/multimedia/multimedia.cpp | 6 +++--- - src/imports/multimedia/plugins.qmltypes | 20 ++++++++++++++------ - 2 files changed, 17 insertions(+), 9 deletions(-) - -diff --git a/src/imports/multimedia/multimedia.cpp b/src/imports/multimedia/multimedia.cpp -index 652359f..4b31068 100644 ---- a/src/imports/multimedia/multimedia.cpp -+++ b/src/imports/multimedia/multimedia.cpp -@@ -97,7 +97,7 @@ public: - trUtf8("CameraImageProcessing is provided by Camera")); - - // 5.2 types -- qmlRegisterRevision(uri, 5, 2); -+ qmlRegisterType(uri, 5, 2, "VideoOutput"); - - // 5.3 types - // Nothing changed, but adding "import QtMultimedia 5.3" in QML will fail unless at -@@ -106,13 +106,13 @@ public: - - // 5.4 types - qmlRegisterSingletonType(uri, 5, 4, "QtMultimedia", multimedia_global_object); -- qmlRegisterRevision(uri, 5, 4); -+ qmlRegisterType(uri, 5, 4, "Camera"); - qmlRegisterUncreatableType(uri, 5, 4, "CameraViewfinder", - trUtf8("CameraViewfinder is provided by Camera")); - - // 5.5 types - qmlRegisterUncreatableType(uri, 5, 5, "CameraImageProcessing", trUtf8("CameraImageProcessing is provided by Camera")); -- qmlRegisterRevision(uri, 5, 5); -+ qmlRegisterType(uri, 5, 5, "Camera"); - - qmlRegisterType(); - qmlRegisterType(); -diff --git a/src/imports/multimedia/plugins.qmltypes b/src/imports/multimedia/plugins.qmltypes -index d01c988..53d7cb4 100644 ---- a/src/imports/multimedia/plugins.qmltypes -+++ b/src/imports/multimedia/plugins.qmltypes -@@ -1,4 +1,4 @@ --import QtQuick.tooling 1.1 -+import QtQuick.tooling 1.2 - - // This file describes the plugin-supplied types contained in the library. - // It is used for QML tooling purposes only. -@@ -7,6 +7,7 @@ import QtQuick.tooling 1.1 - // 'qmlplugindump -nonrelocatable QtMultimedia 5.5' - - Module { -+ dependencies: ["QtQuick 2.0"] - Component { - name: "QAbstractVideoFilter" - prototype: "QObject" -@@ -244,8 +245,12 @@ Module { - Component { - name: "QDeclarativeCamera" - prototype: "QObject" -- exports: ["QtMultimedia/Camera 5.0"] -- exportMetaObjectRevisions: [0] -+ exports: [ -+ "QtMultimedia/Camera 5.0", -+ "QtMultimedia/Camera 5.4", -+ "QtMultimedia/Camera 5.5" -+ ] -+ exportMetaObjectRevisions: [0, 1, 2] - Enum { - name: "Position" - values: { -@@ -517,7 +522,7 @@ Module { - name: "supportedViewfinderFrameRateRanges" - revision: 2 - type: "QJSValue" -- Parameter { name: "resolution"; type: "QSize" } -+ Parameter { name: "resolution"; type: "QJSValue" } - } - Method { name: "supportedViewfinderFrameRateRanges"; revision: 2; type: "QJSValue" } - } -@@ -1497,8 +1502,11 @@ Module { - name: "QDeclarativeVideoOutput" - defaultProperty: "data" - prototype: "QQuickItem" -- exports: ["QtMultimedia/VideoOutput 5.0"] -- exportMetaObjectRevisions: [0] -+ exports: [ -+ "QtMultimedia/VideoOutput 5.0", -+ "QtMultimedia/VideoOutput 5.2" -+ ] -+ exportMetaObjectRevisions: [0, 2] - Enum { - name: "FillMode" - values: { --- -1.9.3 - diff --git a/0010-Fix-signal-slot-declaration-in-QVideoOutputOrientati.patch b/0010-Fix-signal-slot-declaration-in-QVideoOutputOrientati.patch deleted file mode 100644 index ee8e688..0000000 --- a/0010-Fix-signal-slot-declaration-in-QVideoOutputOrientati.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0cf41ef53f7b336509ed7d1ae6518655276af70f Mon Sep 17 00:00:00 2001 -From: Yoann Lopes -Date: Tue, 29 Sep 2015 16:03:15 +0200 -Subject: [PATCH 10/11] Fix signal/slot declaration in - QVideoOutputOrientationHandler. - -Change-Id: I03cdd677feaf06ac2d61682cab46232f983e6494 -Reviewed-by: Christian Stromme ---- - src/multimedia/video/qvideooutputorientationhandler_p.h | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/src/multimedia/video/qvideooutputorientationhandler_p.h b/src/multimedia/video/qvideooutputorientationhandler_p.h -index 14a0c4a..28629ad 100644 ---- a/src/multimedia/video/qvideooutputorientationhandler_p.h -+++ b/src/multimedia/video/qvideooutputorientationhandler_p.h -@@ -48,10 +48,10 @@ public: - - int currentOrientation() const; - --signals: -+Q_SIGNALS: - void orientationChanged(int angle); - --private slots: -+private Q_SLOTS: - void screenOrientationChanged(Qt::ScreenOrientation orientation); - - private: --- -1.9.3 - diff --git a/0011-GStreamer-fix-compilation-with-version-0.10.31.patch b/0011-GStreamer-fix-compilation-with-version-0.10.31.patch deleted file mode 100644 index b66338d..0000000 --- a/0011-GStreamer-fix-compilation-with-version-0.10.31.patch +++ /dev/null @@ -1,445 +0,0 @@ -From 3d3d2a4967ba079a3e6df82cdc89f839865e6649 Mon Sep 17 00:00:00 2001 -From: Yoann Lopes -Date: Fri, 16 Oct 2015 14:15:23 +0200 -Subject: [PATCH 11/11] GStreamer: fix compilation with version < 0.10.31. - -Qt 5.4 and earlier required GStreamer 0.10.24 as minimum version. -Qt 5.5 added code that requires 0.10.31, this code is now ifdef'd -and we now support again 0.10.24. - -Task-number: QTBUG-48353 -Change-Id: Ie708a33c0515874b003ce26a3400475075d316ca -Reviewed-by: Christian Stromme ---- - src/gsttools/qgstreamervideooverlay.cpp | 15 +++-- - src/gsttools/qgstutils.cpp | 69 +++++++++++++++++++++- - src/gsttools/qvideosurfacegstsink.cpp | 31 +++++++++- - src/multimedia/gsttools_headers/qgstutils_p.h | 2 + - .../gsttools_headers/qvideosurfacegstsink_p.h | 5 ++ - .../qgstreameraudiodecoderserviceplugin.cpp | 10 +++- - .../qgstreamercapturemetadatacontrol.cpp | 2 - - .../qgstreamercaptureserviceplugin.cpp | 7 +++ - .../mediacapture/qgstreamercapturesession.cpp | 16 ++--- - .../mediaplayer/qgstreamermetadataprovider.cpp | 5 +- - .../mediaplayer/qgstreamerplayerserviceplugin.cpp | 7 +++ - .../mediaplayer/qgstreamerplayersession.cpp | 8 +-- - 12 files changed, 147 insertions(+), 30 deletions(-) - -diff --git a/src/gsttools/qgstreamervideooverlay.cpp b/src/gsttools/qgstreamervideooverlay.cpp -index 1dcedbc..06f93ef 100644 ---- a/src/gsttools/qgstreamervideooverlay.cpp -+++ b/src/gsttools/qgstreamervideooverlay.cpp -@@ -148,9 +148,7 @@ GstElement *QGstreamerVideoOverlay::findBestVideoSink() const - - // If none of the known video sinks are available, try to find one that implements the - // GstVideoOverlay interface and has autoplugging rank. -- GList *list = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_SINK | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO, -- GST_RANK_MARGINAL); -- -+ GList *list = qt_gst_video_sinks(); - for (GList *item = list; item != NULL; item = item->next) { - GstElementFactory *f = GST_ELEMENT_FACTORY(item->data); - -@@ -242,12 +240,17 @@ void QGstreamerVideoOverlay::setRenderRectangle(const QRect &rect) - h = rect.height(); - } - --#if !GST_CHECK_VERSION(1,0,0) -+#if GST_CHECK_VERSION(1,0,0) -+ if (m_videoSink && GST_IS_VIDEO_OVERLAY(m_videoSink)) -+ gst_video_overlay_set_render_rectangle(GST_VIDEO_OVERLAY(m_videoSink), x, y, w, h); -+#elif GST_CHECK_VERSION(0, 10, 29) - if (m_videoSink && GST_IS_X_OVERLAY(m_videoSink)) - gst_x_overlay_set_render_rectangle(GST_X_OVERLAY(m_videoSink), x, y , w , h); - #else -- if (m_videoSink && GST_IS_VIDEO_OVERLAY(m_videoSink)) -- gst_video_overlay_set_render_rectangle(GST_VIDEO_OVERLAY(m_videoSink), x, y, w, h); -+ Q_UNUSED(x) -+ Q_UNUSED(y) -+ Q_UNUSED(w) -+ Q_UNUSED(h) - #endif - } - -diff --git a/src/gsttools/qgstutils.cpp b/src/gsttools/qgstutils.cpp -index b13038c..50a5623 100644 ---- a/src/gsttools/qgstutils.cpp -+++ b/src/gsttools/qgstutils.cpp -@@ -774,6 +774,7 @@ QSet QGstUtils::supportedMimeTypes(bool (*isValidFactory)(GstElementFac - return supportedMimeTypes; - } - -+#if GST_CHECK_VERSION(1, 0, 0) - namespace { - - struct ColorFormat { QImage::Format imageFormat; GstVideoFormat gstFormat; }; -@@ -786,6 +787,7 @@ static const ColorFormat qt_colorLookup[] = - }; - - } -+#endif - - #if GST_CHECK_VERSION(1,0,0) - QImage QGstUtils::bufferToImage(GstBuffer *buffer, const GstVideoInfo &videoInfo) -@@ -1212,6 +1214,7 @@ void QGstUtils::setMetaData(GstElement *element, const QMap(g_type_class_peek_parent(g_class)); - -- GstVideoSinkClass *video_sink_class = reinterpret_cast(g_class); -- video_sink_class->show_frame = QVideoSurfaceGstSink::show_frame; -- - GstBaseSinkClass *base_sink_class = reinterpret_cast(g_class); - base_sink_class->get_caps = QVideoSurfaceGstSink::get_caps; - base_sink_class->set_caps = QVideoSurfaceGstSink::set_caps; -@@ -387,6 +384,14 @@ void QVideoSurfaceGstSink::class_init(gpointer g_class, gpointer class_data) - base_sink_class->stop = QVideoSurfaceGstSink::stop; - base_sink_class->unlock = QVideoSurfaceGstSink::unlock; - -+#if GST_CHECK_VERSION(0, 10, 25) -+ GstVideoSinkClass *video_sink_class = reinterpret_cast(g_class); -+ video_sink_class->show_frame = QVideoSurfaceGstSink::show_frame; -+#else -+ base_sink_class->preroll = QVideoSurfaceGstSink::preroll; -+ base_sink_class->render = QVideoSurfaceGstSink::render; -+#endif -+ - GstElementClass *element_class = reinterpret_cast(g_class); - element_class->change_state = QVideoSurfaceGstSink::change_state; - -@@ -674,10 +679,30 @@ gboolean QVideoSurfaceGstSink::unlock(GstBaseSink *base) - return TRUE; - } - -+#if GST_CHECK_VERSION(0, 10, 25) - GstFlowReturn QVideoSurfaceGstSink::show_frame(GstVideoSink *base, GstBuffer *buffer) - { - VO_SINK(base); - return sink->delegate->render(buffer); - } -+#else -+GstFlowReturn QVideoSurfaceGstSink::preroll(GstBaseSink *base, GstBuffer *buffer) -+{ -+ VO_SINK(base); -+ gboolean showPrerollFrame = true; -+ g_object_get(G_OBJECT(sink), "show-preroll-frame", &showPrerollFrame, NULL); -+ -+ if (showPrerollFrame) -+ return sink->delegate->render(buffer); -+ -+ return GST_FLOW_OK; -+} -+ -+GstFlowReturn QVideoSurfaceGstSink::render(GstBaseSink *base, GstBuffer *buffer) -+{ -+ VO_SINK(base); -+ return sink->delegate->render(buffer); -+} -+#endif - - QT_END_NAMESPACE -diff --git a/src/multimedia/gsttools_headers/qgstutils_p.h b/src/multimedia/gsttools_headers/qgstutils_p.h -index 31fb858..cf677c3 100644 ---- a/src/multimedia/gsttools_headers/qgstutils_p.h -+++ b/src/multimedia/gsttools_headers/qgstutils_p.h -@@ -150,6 +150,8 @@ gboolean qt_gst_element_query_position(GstElement *element, GstFormat format, gi - gboolean qt_gst_element_query_duration(GstElement *element, GstFormat format, gint64 *cur); - GstCaps *qt_gst_caps_normalize(GstCaps *caps); - const gchar *qt_gst_element_get_factory_name(GstElement *element); -+gboolean qt_gst_caps_can_intersect(const GstCaps * caps1, const GstCaps * caps2); -+GList *qt_gst_video_sinks(); - - QDebug operator <<(QDebug debug, GstCaps *caps); - -diff --git a/src/multimedia/gsttools_headers/qvideosurfacegstsink_p.h b/src/multimedia/gsttools_headers/qvideosurfacegstsink_p.h -index a1ef561..9c04b98 100644 ---- a/src/multimedia/gsttools_headers/qvideosurfacegstsink_p.h -+++ b/src/multimedia/gsttools_headers/qvideosurfacegstsink_p.h -@@ -157,7 +157,12 @@ private: - - static gboolean unlock(GstBaseSink *sink); - -+#if GST_CHECK_VERSION(0, 10, 25) - static GstFlowReturn show_frame(GstVideoSink *sink, GstBuffer *buffer); -+#else -+ static GstFlowReturn preroll(GstBaseSink *sink, GstBuffer *buffer); -+ static GstFlowReturn render(GstBaseSink *sink, GstBuffer *buffer); -+#endif - - private: - QVideoSurfaceGstDelegate *delegate; -diff --git a/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderserviceplugin.cpp b/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderserviceplugin.cpp -index 6afee94..f919bb1 100644 ---- a/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderserviceplugin.cpp -+++ b/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderserviceplugin.cpp -@@ -70,9 +70,15 @@ QMultimedia::SupportEstimate QGstreamerAudioDecoderServicePlugin::hasSupport(con - - static bool isDecoderOrDemuxer(GstElementFactory *factory) - { -+#if GST_CHECK_VERSION(0, 10, 31) - 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); -+ || gst_element_factory_list_is_type(factory, GST_ELEMENT_FACTORY_TYPE_DECODER -+ | GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO); -+#else -+ return (factory -+ && (qstrcmp(factory->details.klass, "Codec/Decoder/Audio") == 0 -+ || qstrcmp(factory->details.klass, "Codec/Demux") == 0)); -+#endif - } - - void QGstreamerAudioDecoderServicePlugin::updateSupportedMimeTypes() const -diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercapturemetadatacontrol.cpp b/src/plugins/gstreamer/mediacapture/qgstreamercapturemetadatacontrol.cpp -index 0018209..fca38ec 100644 ---- a/src/plugins/gstreamer/mediacapture/qgstreamercapturemetadatacontrol.cpp -+++ b/src/plugins/gstreamer/mediacapture/qgstreamercapturemetadatacontrol.cpp -@@ -77,9 +77,7 @@ static const QGstreamerMetaDataKeyLookup *qt_gstreamerMetaDataKeys() - metadataKeys->insert(QMediaMetaData::AlbumTitle, GST_TAG_ALBUM); - metadataKeys->insert(QMediaMetaData::AlbumArtist, GST_TAG_ARTIST); - metadataKeys->insert(QMediaMetaData::ContributingArtist, GST_TAG_PERFORMER); --#if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 19) - metadataKeys->insert(QMediaMetaData::Composer, GST_TAG_COMPOSER); --#endif - //metadataKeys->insert(QMediaMetaData::Conductor, 0); - //metadataKeys->insert(QMediaMetaData::Lyrics, 0); - //metadataKeys->insert(QMediaMetaData::Mood, 0); -diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercaptureserviceplugin.cpp b/src/plugins/gstreamer/mediacapture/qgstreamercaptureserviceplugin.cpp -index a9c66f8..8cbdb67 100644 ---- a/src/plugins/gstreamer/mediacapture/qgstreamercaptureserviceplugin.cpp -+++ b/src/plugins/gstreamer/mediacapture/qgstreamercaptureserviceplugin.cpp -@@ -113,8 +113,15 @@ QMultimedia::SupportEstimate QGstreamerCaptureServicePlugin::hasSupport(const QS - - static bool isEncoderOrMuxer(GstElementFactory *factory) - { -+#if GST_CHECK_VERSION(0, 10, 31) - 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); -+#else -+ return (factory -+ && (qstrcmp(factory->details.klass, "Codec/Encoder/Audio") == 0 -+ || qstrcmp(factory->details.klass, "Codec/Encoder/Video") == 0 -+ || qstrcmp(factory->details.klass, "Codec/Muxer") == 0 )); -+#endif - } - - void QGstreamerCaptureServicePlugin::updateSupportedMimeTypes() const -diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp b/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp -index 77d8987..31ffa50 100644 ---- a/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp -+++ b/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp -@@ -628,12 +628,12 @@ bool QGstreamerCaptureSession::rebuildGraph(QGstreamerCaptureSession::PipelineMo - } - - dumpGraph( QString("rebuild_graph_%1_%2").arg(m_pipelineMode).arg(newMode) ); -+#ifdef QT_GST_CAPTURE_DEBUG - if (m_encodeBin) { - QString fileName = QString("rebuild_graph_encode_%1_%2").arg(m_pipelineMode).arg(newMode); --#if !(GST_DISABLE_GST_DEBUG) && (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 19) -- _gst_debug_bin_to_dot_file(GST_BIN(m_encodeBin), GST_DEBUG_GRAPH_SHOW_ALL, fileName.toLatin1()); --#endif -+ GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(m_encodeBin), GST_DEBUG_GRAPH_SHOW_ALL, fileName.toLatin1()); - } -+#endif - - if (ok) { - addAudioBufferProbe(); -@@ -657,12 +657,12 @@ bool QGstreamerCaptureSession::rebuildGraph(QGstreamerCaptureSession::PipelineMo - - void QGstreamerCaptureSession::dumpGraph(const QString &fileName) - { --#if !(GST_DISABLE_GST_DEBUG) && (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 19) -- _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()); -+#ifdef QT_GST_CAPTURE_DEBUG -+ 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); -+ Q_UNUSED(fileName) - #endif - } - -diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp b/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp -index ac0fe2a..fdf4306 100644 ---- a/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp -+++ b/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp -@@ -76,13 +76,10 @@ static const QGstreamerMetaDataKeyLookup *qt_gstreamerMetaDataKeys() - - // Music - metadataKeys->insert(GST_TAG_ALBUM, QMediaMetaData::AlbumTitle); --#if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 25) -+#if GST_CHECK_VERSION(0, 10, 25) - metadataKeys->insert(GST_TAG_ALBUM_ARTIST, QMediaMetaData::AlbumArtist); - #endif - metadataKeys->insert(GST_TAG_ARTIST, QMediaMetaData::ContributingArtist); --#if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 19) -- metadataKeys->insert(GST_TAG_COMPOSER, QMediaMetaData::Composer); --#endif - //metadataKeys->insert(0, QMediaMetaData::Conductor); - //metadataKeys->insert(0, QMediaMetaData::Lyrics); - //metadataKeys->insert(0, QMediaMetaData::Mood); -diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayerserviceplugin.cpp b/src/plugins/gstreamer/mediaplayer/qgstreamerplayerserviceplugin.cpp -index 004d561..b895c4d 100644 ---- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayerserviceplugin.cpp -+++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayerserviceplugin.cpp -@@ -83,8 +83,15 @@ QMultimedia::SupportEstimate QGstreamerPlayerServicePlugin::hasSupport(const QSt - - static bool isDecoderOrDemuxer(GstElementFactory *factory) - { -+#if GST_CHECK_VERSION(0, 10 ,31) - 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); -+#else -+ return (factory -+ && (qstrcmp(factory->details.klass, "Codec/Decoder/Audio") == 0 -+ || qstrcmp(factory->details.klass, "Codec/Decoder/Video") == 0 -+ || qstrcmp(factory->details.klass, "Codec/Demux") == 0 )); -+#endif - } - - void QGstreamerPlayerServicePlugin::updateSupportedMimeTypes() const -diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp b/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp -index 4dce341..c3d20e7 100644 ---- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp -+++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp -@@ -388,7 +388,7 @@ QMediaTimeRange QGstreamerPlayerSession::availablePlaybackRanges() const - if (duration() <= 0) - return ranges; - --#if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 31) -+#if GST_CHECK_VERSION(0, 10, 31) - //GST_FORMAT_TIME would be more appropriate, but unfortunately it's not supported. - //with GST_FORMAT_PERCENT media is treated as encoded with constant bitrate. - GstQuery* query = gst_query_new_buffering(GST_FORMAT_PERCENT); -@@ -1637,7 +1637,7 @@ void QGstreamerPlayerSession::updateMuted() - } - } - --#if (GST_VERSION_MAJOR == 0) && ((GST_VERSION_MINOR < 10) || (GST_VERSION_MICRO < 33)) -+#if !GST_CHECK_VERSION(0, 10, 33) - static gboolean factory_can_src_any_caps (GstElementFactory *factory, const GstCaps *caps) - { - GList *templates; -@@ -1653,7 +1653,7 @@ static gboolean factory_can_src_any_caps (GstElementFactory *factory, const GstC - if (templ->direction == GST_PAD_SRC) { - GstCaps *templcaps = gst_static_caps_get(&templ->static_caps); - -- if (gst_caps_can_intersect(caps, templcaps)) { -+ if (qt_gst_caps_can_intersect(caps, templcaps)) { - gst_caps_unref(templcaps); - return TRUE; - } -@@ -1685,7 +1685,7 @@ GstAutoplugSelectResult QGstreamerPlayerSession::handleAutoplugSelect(GstBin *bi - GstCaps *sinkCaps = gst_pad_get_caps(sinkPad); - #endif - --#if (GST_VERSION_MAJOR == 0) && ((GST_VERSION_MINOR < 10) || (GST_VERSION_MICRO < 33)) -+#if !GST_CHECK_VERSION(0, 10, 33) - if (!factory_can_src_any_caps(factory, sinkCaps)) - #else - if (!gst_element_factory_can_src_any_caps(factory, sinkCaps)) --- -1.9.3 - diff --git a/qt5-qtmultimedia.spec b/qt5-qtmultimedia.spec index 8e199d1..9ab0ace 100644 --- a/qt5-qtmultimedia.spec +++ b/qt5-qtmultimedia.spec @@ -17,44 +17,37 @@ %global openal 1 %endif -## define prerelease rc1 - -%global gst 0.10 +%define prerelease beta1 +%define gst 0.10 %if 0%{?fedora} > 20 -%global gst 1.0 +%define gst 1.0 %endif Summary: Qt5 - Multimedia support Name: qt5-%{qt_module} -Version: 5.5.1 -Release: 4%{?dist} +Version: 5.6.0 +Release: 0.1%{?dist} # See LGPL_EXCEPTIONS.txt, LICENSE.GPL3, respectively, for exception details License: LGPLv2 with exceptions or GPLv3 with exceptions Url: http://www.qt.io Source0: http://download.qt.io/official_releases/qt/5.5/%{version}%{?prerelease:-%{prerelease}}/submodules/%{qt_module}-opensource-src-%{version}%{?prerelease:-%{prerelease}}.tar.xz -## upstream patches -Patch7: 0007-Fixed-revisions-of-camera-related-meta-objects.patch -Patch10: 0010-Fix-signal-slot-declaration-in-QVideoOutputOrientati.patch -Patch11: 0011-GStreamer-fix-compilation-with-version-0.10.31.patch - BuildRequires: qt5-qtbase-devel >= %{version} -BuildRequires: qt5-qtdeclarative-devel >= %{version} +BuildRequires: pkgconfig(Qt5Quick) >= %{version} BuildRequires: pkgconfig(alsa) -%if 0%{?gst:1} +BuildRequires: qt5-qdoc %if "%{?gst}" == "0.10" BuildRequires: pkgconfig(gstreamer-interfaces-0.10) %endif -BuildRequires: pkgconfig(gstreamer-%{gst}) >= 0.10.24 +BuildRequires: pkgconfig(gstreamer-%{gst}) BuildRequires: pkgconfig(gstreamer-app-%{gst}) BuildRequires: pkgconfig(gstreamer-audio-%{gst}) BuildRequires: pkgconfig(gstreamer-base-%{gst}) BuildRequires: pkgconfig(gstreamer-pbutils-%{gst}) BuildRequires: pkgconfig(gstreamer-plugins-bad-%{gst}) BuildRequires: pkgconfig(gstreamer-video-%{gst}) -%endif BuildRequires: pkgconfig(libpulse) pkgconfig(libpulse-mainloop-glib) %if 0%{?openal} BuildRequires: pkgconfig(openal) @@ -98,10 +91,6 @@ Requires: %{name}%{?_isa} = %{version}-%{release} %prep %setup -q -n %{qt_module}-opensource-src-%{version}%{?prerelease:-%{prerelease}} -%patch7 -p1 -b .0007 -%patch10 -p1 -b .0010 -%patch11 -p1 -b .0011 - %build mkdir %{_target_platform} @@ -146,9 +135,7 @@ popd %{_qt5_libdir}/libQt5Multimedia.so.5* %{_qt5_libdir}/libQt5MultimediaQuick_p.so.5* %{_qt5_libdir}/libQt5MultimediaWidgets.so.5* -%if 0%{?gst:1} %{_qt5_libdir}/libqgsttools_p.so.1* -%endif %if 0%{?openal} %{_qt5_archdatadir}/qml/QtAudioEngine/ %endif @@ -170,10 +157,8 @@ popd %{_qt5_libdir}/libQt5MultimediaQuick_p.prl %{_qt5_libdir}/libQt5MultimediaWidgets.so %{_qt5_libdir}/libQt5MultimediaWidgets.prl -%if 0%{?gst:1} %{_qt5_libdir}/libqgsttools_p.so %{_qt5_libdir}/libqgsttools_p.prl -%endif %{_qt5_libdir}/cmake/Qt5Multimedia/Qt5MultimediaConfig*.cmake %{_qt5_libdir}/cmake/Qt5MultimediaWidgets/Qt5MultimediaWidgetsConfig*.cmake %{_qt5_libdir}/pkgconfig/Qt5Multimedia.pc @@ -197,6 +182,9 @@ popd %changelog +* Tue Nov 03 2015 Helio Chissini de Castro - 5.6.0-0.1 +- Start to implement 5.6.0 beta + * Mon Oct 26 2015 Rex Dieter 5.5.1-4 - pull in upstream fixes, QTBUG-48939 in particular diff --git a/sources b/sources index 2d9473b..036049f 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -244baff13a02ebc697e5b5e2290088d0 qtmultimedia-opensource-src-5.5.1.tar.xz +6538a78d09638379384f2b639dee27b6 qtmultimedia-opensource-src-5.6.0-beta1.tar.xz From fd4ed5e29285a7afe1be8c8cf30c7247fcad9fbb Mon Sep 17 00:00:00 2001 From: Jan Grulich Date: Mon, 7 Dec 2015 13:45:19 +0100 Subject: [PATCH 6/6] Attempt to fix build failure --- qt5-qtmultimedia.spec | 1 - 1 file changed, 1 deletion(-) diff --git a/qt5-qtmultimedia.spec b/qt5-qtmultimedia.spec index 9ab0ace..dc541af 100644 --- a/qt5-qtmultimedia.spec +++ b/qt5-qtmultimedia.spec @@ -162,7 +162,6 @@ popd %{_qt5_libdir}/cmake/Qt5Multimedia/Qt5MultimediaConfig*.cmake %{_qt5_libdir}/cmake/Qt5MultimediaWidgets/Qt5MultimediaWidgetsConfig*.cmake %{_qt5_libdir}/pkgconfig/Qt5Multimedia.pc -%{_qt5_libdir}/pkgconfig/Qt5MultimediaQuick_p.pc %{_qt5_libdir}/pkgconfig/Qt5MultimediaWidgets.pc %{_qt5_archdatadir}/mkspecs/modules/*.pri