From da77331952f38992fbd4a650a02ad975a4efaa36 Mon Sep 17 00:00:00 2001 From: Niels Weber Date: Mon, 5 May 2014 16:16:05 +0200 Subject: Improve Magnify and Ripple effects on video shader example MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Re-enable Magnify shader. Use correct coordinates for Magnify and Ripple shader. Task-number: QTBUG-38121 Change-Id: Ie8d962ba841d074c9ebcf3b86f948848ad6a1812 Reviewed-by: Topi Reiniö --- examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectMagnify.qml | 4 +++- examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectRipple.qml | 4 +++- .../video/qmlvideofx/qml/qmlvideofx/EffectSelectionList.qml | 2 +- examples/multimedia/video/qmlvideofx/shaders/magnify.fsh | 3 +++ examples/multimedia/video/qmlvideofx/shaders/ripple.fsh | 3 ++- 5 files changed, 12 insertions(+), 4 deletions(-) diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectMagnify.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectMagnify.qml index 3fd35eaae..84ac4ce7f 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectMagnify.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectMagnify.qml @@ -39,7 +39,8 @@ ** ****************************************************************************/ -import QtQuick 2.0 +import QtQuick 2.1 +import QtQuick.Window 2.1 Effect { id: root @@ -57,6 +58,7 @@ Effect { property real posX: -1 property real posY: -1 + property real pixDens: Screen.pixelDensity QtObject { id: d diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectRipple.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectRipple.qml index e0a2b0227..d481fdfd9 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectRipple.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectRipple.qml @@ -39,7 +39,8 @@ ** ****************************************************************************/ -import QtQuick 2.0 +import QtQuick 2.1 +import QtQuick.Window 2.1 Effect { parameters: ListModel { @@ -56,6 +57,7 @@ Effect { // Transform slider values, and bind result to shader uniforms property real amplitude: parameters.get(0).value * 0.03 property real n: parameters.get(1).value * 7 + property real pixDens: Screen.pixelDensity property real time: 0 NumberAnimation on time { loops: Animation.Infinite; from: 0; to: Math.PI * 2; duration: 600 } diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectSelectionList.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectSelectionList.qml index fa92bb7ca..da9a96143 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectSelectionList.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectSelectionList.qml @@ -51,7 +51,7 @@ ListModel { ListElement { name: "Emboss"; source: "EffectEmboss.qml" } ListElement { name: "Glow"; source: "EffectGlow.qml" } ListElement { name: "Isolate"; source: "EffectIsolate.qml" } - //ListElement { name: "Magnify"; source: "EffectMagnify.qml" } + ListElement { name: "Magnify"; source: "EffectMagnify.qml" } ListElement { name: "Page curl"; source: "EffectPageCurl.qml" } ListElement { name: "Pixelate"; source: "EffectPixelate.qml" } ListElement { name: "Posterize"; source: "EffectPosterize.qml" } diff --git a/examples/multimedia/video/qmlvideofx/shaders/magnify.fsh b/examples/multimedia/video/qmlvideofx/shaders/magnify.fsh index 0387d25d6..fb7e2a047 100644 --- a/examples/multimedia/video/qmlvideofx/shaders/magnify.fsh +++ b/examples/multimedia/video/qmlvideofx/shaders/magnify.fsh @@ -50,12 +50,15 @@ uniform float targetWidth; uniform float targetHeight; uniform float posX; uniform float posY; +uniform float pixDens; void main() { vec2 tc = qt_TexCoord0; vec2 center = vec2(posX, posY); vec2 xy = gl_FragCoord.xy - center.xy; + xy.x -= (pixDens * 14.0); + xy.y -= (pixDens * 29.0); float r = sqrt(xy.x * xy.x + xy.y * xy.y); if (r < radius) { float h = diffractionIndex * 0.5 * radius; diff --git a/examples/multimedia/video/qmlvideofx/shaders/ripple.fsh b/examples/multimedia/video/qmlvideofx/shaders/ripple.fsh index b70f36d92..428c041c7 100644 --- a/examples/multimedia/video/qmlvideofx/shaders/ripple.fsh +++ b/examples/multimedia/video/qmlvideofx/shaders/ripple.fsh @@ -55,12 +55,13 @@ const int ITER = 7; const float RATE = 0.1; uniform float amplitude; uniform float n; +uniform float pixDens; void main() { vec2 uv = qt_TexCoord0.xy; vec2 tc = uv; - vec2 p = vec2(-1.0 + 2.0 * gl_FragCoord.x / targetWidth, -(-1.0 + 2.0 * gl_FragCoord.y / targetHeight)); + vec2 p = vec2(-1.0 + 2.0 * (gl_FragCoord.x - (pixDens * 14.0)) / targetWidth, -(-1.0 + 2.0 * (gl_FragCoord.y - (pixDens * 29.0)) / targetHeight)); float diffx = 0.0; float diffy = 0.0; vec4 col; -- cgit v1.2.3 From ff527de0133d597293459cc7d0f03f6203995cc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lisandro=20Dami=C3=A1n=20Nicanor=20P=C3=A9rez=20Meyer?= Date: Thu, 10 Jul 2014 19:19:37 -0300 Subject: Detect V4L availability MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Do not build related stuff if not found. Makes GStreamer support available on Hurd. Task-number: QTBUG-39762 Change-Id: I1f70b6975e5bef99ab2441aac4d90508bc8b64bd Reviewed-by: Lisandro Damián Nicanor Pérez Meyer Reviewed-by: Yoann Lopes --- config.tests/linux_v4l/linux_v4l.pro | 1 + config.tests/linux_v4l/main.cpp | 47 ++++++++++++++++++++++ qtmultimedia.pro | 1 + src/gsttools/gsttools.pro | 2 + src/gsttools/qgstreamervideoinputdevicecontrol.cpp | 5 +++ src/plugins/gstreamer/camerabin/camerabin.pro | 2 + .../gstreamer/camerabin/camerabinserviceplugin.cpp | 5 +++ .../gstreamer/mediacapture/mediacapture.pro | 21 +++++----- .../mediacapture/qgstreamercaptureservice.cpp | 9 ++++- .../mediacapture/qgstreamercaptureservice.h | 2 + .../qgstreamercaptureserviceplugin.cpp | 3 ++ src/plugins/plugins.pro | 4 +- 12 files changed, 91 insertions(+), 11 deletions(-) create mode 100644 config.tests/linux_v4l/linux_v4l.pro create mode 100644 config.tests/linux_v4l/main.cpp diff --git a/config.tests/linux_v4l/linux_v4l.pro b/config.tests/linux_v4l/linux_v4l.pro new file mode 100644 index 000000000..28dcadcbf --- /dev/null +++ b/config.tests/linux_v4l/linux_v4l.pro @@ -0,0 +1 @@ +SOURCES += main.cpp diff --git a/config.tests/linux_v4l/main.cpp b/config.tests/linux_v4l/main.cpp new file mode 100644 index 000000000..0a3040be5 --- /dev/null +++ b/config.tests/linux_v4l/main.cpp @@ -0,0 +1,47 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** 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 + +int main(int argc, char** argv) +{ + return 0; +} diff --git a/qtmultimedia.pro b/qtmultimedia.pro index c7f093ccc..bec5925b5 100644 --- a/qtmultimedia.pro +++ b/qtmultimedia.pro @@ -25,6 +25,7 @@ win32 { 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 15edd04d2..7c809a777 100644 --- a/src/gsttools/gsttools.pro +++ b/src/gsttools/gsttools.pro @@ -100,6 +100,8 @@ config_gstreamer_appsrc { LIBS_PRIVATE += -lgstapp-0.10 } +config_linux_v4l: DEFINES += USE_V4L + HEADERS += $$PRIVATE_HEADERS DESTDIR = $$QT.multimedia.libs diff --git a/src/gsttools/qgstreamervideoinputdevicecontrol.cpp b/src/gsttools/qgstreamervideoinputdevicecontrol.cpp index e4e202caf..dc008712e 100644 --- a/src/gsttools/qgstreamervideoinputdevicecontrol.cpp +++ b/src/gsttools/qgstreamervideoinputdevicecontrol.cpp @@ -45,7 +45,10 @@ #include #include + +#if defined(USE_V4L) #include +#endif QGstreamerVideoInputDeviceControl::QGstreamerVideoInputDeviceControl(QObject *parent) :QVideoDeviceSelectorControl(parent), m_source(0), m_selectedDevice(0) @@ -118,6 +121,7 @@ void QGstreamerVideoInputDeviceControl::update() return; } +#if defined(USE_V4L) QDir devDir("/dev"); devDir.setFilter(QDir::System); @@ -158,4 +162,5 @@ void QGstreamerVideoInputDeviceControl::update() } qt_safe_close(fd); } +#endif } diff --git a/src/plugins/gstreamer/camerabin/camerabin.pro b/src/plugins/gstreamer/camerabin/camerabin.pro index 9efa0812a..9ed821cb9 100644 --- a/src/plugins/gstreamer/camerabin/camerabin.pro +++ b/src/plugins/gstreamer/camerabin/camerabin.pro @@ -81,6 +81,8 @@ config_gstreamer_photography { DEFINES += GST_USE_UNSTABLE_API #prevents warnings because of unstable photography API } +config_linux_v4l: DEFINES += USE_V4L + OTHER_FILES += \ camerabin.json diff --git a/src/plugins/gstreamer/camerabin/camerabinserviceplugin.cpp b/src/plugins/gstreamer/camerabin/camerabinserviceplugin.cpp index 3decd6070..5fb419aae 100644 --- a/src/plugins/gstreamer/camerabin/camerabinserviceplugin.cpp +++ b/src/plugins/gstreamer/camerabin/camerabinserviceplugin.cpp @@ -51,7 +51,10 @@ #include #include + +#if defined(USE_V4L) #include +#endif QT_BEGIN_NAMESPACE @@ -132,6 +135,7 @@ void CameraBinServicePlugin::updateDevices() const m_cameraDevices.clear(); m_cameraDescriptions.clear(); +#if defined(USE_V4L) QDir devDir("/dev"); devDir.setFilter(QDir::System); @@ -173,6 +177,7 @@ void CameraBinServicePlugin::updateDevices() const if (!m_cameraDevices.isEmpty()) m_defaultCameraDevice = m_cameraDevices.first(); +#endif } QT_END_NAMESPACE diff --git a/src/plugins/gstreamer/mediacapture/mediacapture.pro b/src/plugins/gstreamer/mediacapture/mediacapture.pro index e8d039f8d..5baa0fd8f 100644 --- a/src/plugins/gstreamer/mediacapture/mediacapture.pro +++ b/src/plugins/gstreamer/mediacapture/mediacapture.pro @@ -15,7 +15,6 @@ HEADERS += $$PWD/qgstreamercaptureservice.h \ $$PWD/qgstreamerrecordercontrol.h \ $$PWD/qgstreamermediacontainercontrol.h \ $$PWD/qgstreamercameracontrol.h \ - $$PWD/qgstreamerv4l2input.h \ $$PWD/qgstreamercapturemetadatacontrol.h \ $$PWD/qgstreamerimagecapturecontrol.h \ $$PWD/qgstreamerimageencode.h \ @@ -28,7 +27,6 @@ SOURCES += $$PWD/qgstreamercaptureservice.cpp \ $$PWD/qgstreamerrecordercontrol.cpp \ $$PWD/qgstreamermediacontainercontrol.cpp \ $$PWD/qgstreamercameracontrol.cpp \ - $$PWD/qgstreamerv4l2input.cpp \ $$PWD/qgstreamercapturemetadatacontrol.cpp \ $$PWD/qgstreamerimagecapturecontrol.cpp \ $$PWD/qgstreamerimageencode.cpp \ @@ -37,13 +35,18 @@ SOURCES += $$PWD/qgstreamercaptureservice.cpp \ # Camera usage with gstreamer needs to have #CONFIG += use_gstreamer_camera -use_gstreamer_camera { -DEFINES += USE_GSTREAMER_CAMERA +use_gstreamer_camera:config_linux_v4l { + DEFINES += USE_GSTREAMER_CAMERA + + OTHER_FILES += \ + mediacapturecamera.json + + HEADERS += \ + $$PWD/qgstreamerv4l2input.h + SOURCES += \ + $$PWD/qgstreamerv4l2input.cpp -OTHER_FILES += \ - mediacapturecamera.json } else { -OTHER_FILES += \ - mediacapture.json + OTHER_FILES += \ + mediacapture.json } - diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.cpp b/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.cpp index 92b362fb8..2278f926f 100644 --- a/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.cpp +++ b/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.cpp @@ -48,9 +48,12 @@ #include "qgstreamerimageencode.h" #include "qgstreamercameracontrol.h" #include -#include "qgstreamerv4l2input.h" #include "qgstreamercapturemetadatacontrol.h" +#if defined(USE_GSTREAMER_CAMERA) +#include "qgstreamerv4l2input.h" +#endif + #include "qgstreamerimagecapturecontrol.h" #include #include @@ -74,7 +77,9 @@ QGstreamerCaptureService::QGstreamerCaptureService(const QString &service, QObje m_cameraControl = 0; m_metaDataControl = 0; +#if defined(USE_GSTREAMER_CAMERA) m_videoInput = 0; +#endif m_audioInputSelector = 0; m_videoInputDevice = 0; @@ -90,6 +95,7 @@ QGstreamerCaptureService::QGstreamerCaptureService(const QString &service, QObje m_captureSession = new QGstreamerCaptureSession(QGstreamerCaptureSession::Audio, this); } +#if defined(USE_GSTREAMER_CAMERA) if (service == Q_MEDIASERVICE_CAMERA) { m_captureSession = new QGstreamerCaptureSession(QGstreamerCaptureSession::AudioAndVideo, this); m_cameraControl = new QGstreamerCameraControl(m_captureSession); @@ -111,6 +117,7 @@ QGstreamerCaptureService::QGstreamerCaptureService(const QString &service, QObje #endif m_imageCaptureControl = new QGstreamerImageCaptureControl(m_captureSession); } +#endif m_audioInputSelector = new QGstreamerAudioInputSelector(this); connect(m_audioInputSelector, SIGNAL(activeInputChanged(QString)), m_captureSession, SLOT(setCaptureDevice(QString))); diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.h b/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.h index fc29b4f34..563c48c28 100644 --- a/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.h +++ b/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.h @@ -78,7 +78,9 @@ private: QGstreamerCaptureSession *m_captureSession; QGstreamerCameraControl *m_cameraControl; +#if defined(USE_GSTREAMER_CAMERA) QGstreamerV4L2Input *m_videoInput; +#endif QGstreamerCaptureMetaDataControl *m_metaDataControl; QAudioInputSelectorControl *m_audioInputSelector; diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercaptureserviceplugin.cpp b/src/plugins/gstreamer/mediacapture/qgstreamercaptureserviceplugin.cpp index 8b88fbb71..77a6c3650 100644 --- a/src/plugins/gstreamer/mediacapture/qgstreamercaptureserviceplugin.cpp +++ b/src/plugins/gstreamer/mediacapture/qgstreamercaptureserviceplugin.cpp @@ -52,7 +52,10 @@ #include #include + +#if defined(USE_GSTREAMER_CAMERA) #include +#endif QMediaService* QGstreamerCaptureServicePlugin::create(const QString &key) { diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro index 2677e269b..6a23fd2a3 100644 --- a/src/plugins/plugins.pro +++ b/src/plugins/plugins.pro @@ -43,7 +43,9 @@ unix:!mac:!android { } # v4l is turned off because it is not supported in Qt 5 - # !maemo*:SUBDIRS += v4l + # config_linux_v4l { + # !maemo*:SUBDIRS += v4l + # } } mac:!simulator { -- cgit v1.2.3 From c93c1d1dc30884b2c13bffdbc701efb5401b58b7 Mon Sep 17 00:00:00 2001 From: Dyami Caliri Date: Tue, 22 Jul 2014 11:19:14 -0700 Subject: CoreAudioOutput use timeout when waiting for render thread On Snow Leopard (at least), changing the default audio device while audio is playing can cause CoreAudioOutput to freeze in audioThreadStop(). It seems that the OS stops calling renderCallback when the device changes, so audioThreadStop() waits forever. Change-Id: If7244cc50f12295ff91a979ef50e3bee1273affd Reviewed-by: Andy Nichols --- src/plugins/coreaudio/coreaudiooutput.mm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/coreaudio/coreaudiooutput.mm b/src/plugins/coreaudio/coreaudiooutput.mm index e5e1c65e5..812d9dfe2 100644 --- a/src/plugins/coreaudio/coreaudiooutput.mm +++ b/src/plugins/coreaudio/coreaudiooutput.mm @@ -698,14 +698,14 @@ void CoreAudioOutput::audioThreadStop() { stopTimers(); if (m_audioThreadState.testAndSetAcquire(Running, Stopped)) - m_threadFinished.wait(&m_mutex); + m_threadFinished.wait(&m_mutex, 500); } void CoreAudioOutput::audioThreadDrain() { stopTimers(); if (m_audioThreadState.testAndSetAcquire(Running, Draining)) - m_threadFinished.wait(&m_mutex); + m_threadFinished.wait(&m_mutex, 500); } void CoreAudioOutput::audioDeviceStop() -- cgit v1.2.3 From 5195520a5a87ef8b5afdb980a808a5a95dad4e67 Mon Sep 17 00:00:00 2001 From: "Daniele E. Domenichelli" Date: Tue, 12 Aug 2014 15:07:23 +0200 Subject: Fix QSGVideoNode rendering of rgb frames with padding. Change-Id: I6870cfa51b01b648494e2068be06e52b67403739 Reviewed-by: Andrew den Exter Reviewed-by: Yoann Lopes --- src/qtmultimediaquicktools/qsgvideonode_rgb.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qtmultimediaquicktools/qsgvideonode_rgb.cpp b/src/qtmultimediaquicktools/qsgvideonode_rgb.cpp index ad01a08ae..1316be928 100644 --- a/src/qtmultimediaquicktools/qsgvideonode_rgb.cpp +++ b/src/qtmultimediaquicktools/qsgvideonode_rgb.cpp @@ -220,7 +220,7 @@ public: stride /= 4; } - m_width = qreal(m_frame.width() / stride); + m_width = qreal(m_frame.width()) / stride; textureSize.setWidth(stride); if (m_textureSize != textureSize) { -- cgit v1.2.3 From 18e665b5a611823de13159bbaacd2134e6727180 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Thu, 14 Aug 2014 15:37:28 +0200 Subject: Android: Remove api level test in qtmultimedia.pro ANDROID_API_VERSION env. var should take precedence, if set. Change-Id: I54325852ede27ff5c1bb19b81d3d649605607de9 Reviewed-by: Yoann Lopes --- qtmultimedia.pro | 4 ---- 1 file changed, 4 deletions(-) diff --git a/qtmultimedia.pro b/qtmultimedia.pro index bec5925b5..3cec526e8 100644 --- a/qtmultimedia.pro +++ b/qtmultimedia.pro @@ -12,10 +12,6 @@ win32 { qtCompileTest(evr) } else:mac { qtCompileTest(avfoundation) -} else:android:!android-no-sdk { - SDK_ROOT = $$(ANDROID_SDK_ROOT) - isEmpty(SDK_ROOT): SDK_ROOT = $$DEFAULT_ANDROID_SDK_ROOT - !exists($$SDK_ROOT/platforms/android-11/android.jar): error("QtMultimedia for Android requires API level 11") } else:qnx { qtCompileTest(mmrenderer) } else { -- cgit v1.2.3 From fb35f025e320ef1639adf9a5d7bee73faa44e442 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Tue, 12 Aug 2014 16:46:50 +0200 Subject: OpenSL: Fix QAudioOutput::setNotifyInterval(). It was not possible to change the notify interval after calling start(). Task-number: QTBUG-40208 Change-Id: I82a626003e3bdfe7b7fc88b2f97da492c788877e Reviewed-by: Yoann Lopes --- src/plugins/opensles/qopenslesaudiooutput.cpp | 36 +++++++++++++++++++++++---- src/plugins/opensles/qopenslesaudiooutput.h | 1 + 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/src/plugins/opensles/qopenslesaudiooutput.cpp b/src/plugins/opensles/qopenslesaudiooutput.cpp index 49bea0b36..9c62852de 100644 --- a/src/plugins/opensles/qopenslesaudiooutput.cpp +++ b/src/plugins/opensles/qopenslesaudiooutput.cpp @@ -78,7 +78,8 @@ QOpenSLESAudioOutput::QOpenSLESAudioOutput(const QByteArray &device) m_periodSize(0), m_elapsedTime(0), m_processedBytes(0), - m_availableBuffers(BUFFER_COUNT) + m_availableBuffers(BUFFER_COUNT), + m_eventMask(SL_PLAYEVENT_HEADATEND) { #ifndef ANDROID m_streamType = -1; @@ -198,7 +199,33 @@ int QOpenSLESAudioOutput::bufferSize() const void QOpenSLESAudioOutput::setNotifyInterval(int ms) { - m_notifyInterval = ms > 0 ? ms : 0; + const int newInterval = ms > 0 ? ms : 0; + + if (newInterval == m_notifyInterval) + return; + + const SLuint32 newEvenMask = newInterval == 0 ? m_eventMask & ~SL_PLAYEVENT_HEADATNEWPOS + : m_eventMask & SL_PLAYEVENT_HEADATNEWPOS; + + if (m_state == QAudio::StoppedState) { + m_eventMask = newEvenMask; + m_notifyInterval = newInterval; + return; + } + + if (newEvenMask != m_eventMask + && SL_RESULT_SUCCESS != (*m_playItf)->SetCallbackEventsMask(m_playItf, newEvenMask)) { + return; + } + + m_eventMask = newEvenMask; + + if (newInterval && SL_RESULT_SUCCESS != (*m_playItf)->SetPositionUpdatePeriod(m_playItf, + newInterval)) { + return; + } + + m_notifyInterval = newInterval; } int QOpenSLESAudioOutput::notifyInterval() const @@ -488,13 +515,12 @@ bool QOpenSLESAudioOutput::preparePlayer() return false; } - SLuint32 mask = SL_PLAYEVENT_HEADATEND; if (m_notifyInterval && SL_RESULT_SUCCESS == (*m_playItf)->SetPositionUpdatePeriod(m_playItf, m_notifyInterval)) { - mask |= SL_PLAYEVENT_HEADATNEWPOS; + m_eventMask |= SL_PLAYEVENT_HEADATNEWPOS; } - if (SL_RESULT_SUCCESS != (*m_playItf)->SetCallbackEventsMask(m_playItf, mask)) { + if (SL_RESULT_SUCCESS != (*m_playItf)->SetCallbackEventsMask(m_playItf, m_eventMask)) { setError(QAudio::FatalError); return false; } diff --git a/src/plugins/opensles/qopenslesaudiooutput.h b/src/plugins/opensles/qopenslesaudiooutput.h index b0f01fa22..16cbc50d0 100644 --- a/src/plugins/opensles/qopenslesaudiooutput.h +++ b/src/plugins/opensles/qopenslesaudiooutput.h @@ -120,6 +120,7 @@ private: qint64 m_elapsedTime; qint64 m_processedBytes; QAtomicInt m_availableBuffers; + SLuint32 m_eventMask; qint32 m_streamType; QTime m_clockStamp; -- cgit v1.2.3 From 341b86c63fbe9e9f284e2d6547cb639f487a2ec4 Mon Sep 17 00:00:00 2001 From: Yoann Lopes Date: Thu, 17 Jul 2014 18:41:44 +0200 Subject: Android: fix retrieving metadata from assets, qrc and remote files. We need the same logic as for the media player: local files and assets must be loaded with a FileDescriptor. Because of a bug in Android API level >= 14, remote files have to be loaded in different ways depending on the version. Task-number: QTBUG-40274 Change-Id: I6411b959064d22219cf981a4dc8f4f26cf16f65f Reviewed-by: Christian Stromme --- .../src/mediaplayer/qandroidmediaplayercontrol.cpp | 4 +- .../src/mediaplayer/qandroidmediaplayercontrol.h | 1 + .../src/mediaplayer/qandroidmediaservice.cpp | 4 +- .../mediaplayer/qandroidmetadatareadercontrol.cpp | 10 +- .../mediaplayer/qandroidmetadatareadercontrol.h | 4 +- .../wrappers/jni/androidmediametadataretriever.cpp | 133 +++++++++++++++------ .../wrappers/jni/androidmediametadataretriever.h | 4 +- 7 files changed, 113 insertions(+), 47 deletions(-) diff --git a/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.cpp b/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.cpp index 6817d65b0..90efcc503 100644 --- a/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.cpp +++ b/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.cpp @@ -325,8 +325,10 @@ void QAndroidMediaPlayerControl::setMedia(const QMediaContent &mediaContent, mMediaPlayer->setDataSource(mediaPath); mMediaPlayer->prepareAsync(); - if (!reloading) + if (!reloading) { Q_EMIT mediaChanged(mMediaContent); + Q_EMIT actualMediaLocationChanged(mediaPath); + } resetBufferingProgress(); } diff --git a/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.h b/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.h index 5744c11b8..1f61809cd 100644 --- a/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.h +++ b/src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.h @@ -80,6 +80,7 @@ public: Q_SIGNALS: void metaDataUpdated(); + void actualMediaLocationChanged(const QString &url); public Q_SLOTS: void setPosition(qint64 position) Q_DECL_OVERRIDE; diff --git a/src/plugins/android/src/mediaplayer/qandroidmediaservice.cpp b/src/plugins/android/src/mediaplayer/qandroidmediaservice.cpp index 175958676..c6a7d3c39 100644 --- a/src/plugins/android/src/mediaplayer/qandroidmediaservice.cpp +++ b/src/plugins/android/src/mediaplayer/qandroidmediaservice.cpp @@ -53,8 +53,8 @@ QAndroidMediaService::QAndroidMediaService(QObject *parent) { mMediaControl = new QAndroidMediaPlayerControl; mMetadataControl = new QAndroidMetaDataReaderControl; - connect(mMediaControl, SIGNAL(mediaChanged(QMediaContent)), - mMetadataControl, SLOT(onMediaChanged(QMediaContent))); + connect(mMediaControl, SIGNAL(actualMediaLocationChanged(QString)), + mMetadataControl, SLOT(onMediaChanged(QString))); connect(mMediaControl, SIGNAL(metaDataUpdated()), mMetadataControl, SLOT(onUpdateMetaData())); } diff --git a/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.cpp b/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.cpp index 82bd74997..7f68bc13c 100644 --- a/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.cpp +++ b/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.cpp @@ -101,18 +101,18 @@ QStringList QAndroidMetaDataReaderControl::availableMetaData() const return m_metadata.keys(); } -void QAndroidMetaDataReaderControl::onMediaChanged(const QMediaContent &media) +void QAndroidMetaDataReaderControl::onMediaChanged(const QString &url) { if (!m_retriever) return; - m_mediaContent = media; + m_mediaLocation = url; updateData(); } void QAndroidMetaDataReaderControl::onUpdateMetaData() { - if (!m_retriever || m_mediaContent.isNull()) + if (!m_retriever || m_mediaLocation.isEmpty()) return; updateData(); @@ -122,8 +122,8 @@ void QAndroidMetaDataReaderControl::updateData() { m_metadata.clear(); - if (!m_mediaContent.isNull()) { - if (m_retriever->setDataSource(m_mediaContent.canonicalUrl())) { + if (!m_mediaLocation.isEmpty()) { + if (m_retriever->setDataSource(m_mediaLocation)) { QString mimeType = m_retriever->extractMetadata(AndroidMediaMetadataRetriever::MimeType); if (!mimeType.isNull()) m_metadata.insert(QMediaMetaData::MediaType, mimeType); diff --git a/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.h b/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.h index 67b92f1eb..a8f1d92f2 100644 --- a/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.h +++ b/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.h @@ -62,13 +62,13 @@ public: QStringList availableMetaData() const Q_DECL_OVERRIDE; public Q_SLOTS: - void onMediaChanged(const QMediaContent &media); + void onMediaChanged(const QString &url); void onUpdateMetaData(); private: void updateData(); - QMediaContent m_mediaContent; + QString m_mediaLocation; bool m_available; QVariantMap m_metadata; diff --git a/src/plugins/android/src/wrappers/jni/androidmediametadataretriever.cpp b/src/plugins/android/src/wrappers/jni/androidmediametadataretriever.cpp index 7dfc6a6e3..83f12cb8c 100644 --- a/src/plugins/android/src/wrappers/jni/androidmediametadataretriever.cpp +++ b/src/plugins/android/src/wrappers/jni/androidmediametadataretriever.cpp @@ -43,9 +43,24 @@ #include #include +#include +#include QT_BEGIN_NAMESPACE +static bool exceptionCheckAndClear(JNIEnv *env) +{ + if (Q_UNLIKELY(env->ExceptionCheck())) { +#ifdef QT_DEBUG + env->ExceptionDescribe(); +#endif // QT_DEBUG + env->ExceptionClear(); + return true; + } + + return false; +} + AndroidMediaMetadataRetriever::AndroidMediaMetadataRetriever() { m_metadataRetriever = QJNIObjectPrivate("android/media/MediaMetadataRetriever"); @@ -76,55 +91,105 @@ void AndroidMediaMetadataRetriever::release() m_metadataRetriever.callMethod("release"); } -bool AndroidMediaMetadataRetriever::setDataSource(const QUrl &url) +bool AndroidMediaMetadataRetriever::setDataSource(const QString &urlString) { if (!m_metadataRetriever.isValid()) return false; QJNIEnvironmentPrivate env; + QUrl url(urlString); - bool loaded = false; + if (url.isLocalFile()) { // also includes qrc files (copied to a temp file) + QJNIObjectPrivate string = QJNIObjectPrivate::fromString(url.path()); + QJNIObjectPrivate fileInputStream("java/io/FileInputStream", + "(Ljava/lang/String;)V", + string.object()); - QJNIObjectPrivate string = QJNIObjectPrivate::fromString(url.toString()); + if (exceptionCheckAndClear(env)) + return false; + + QJNIObjectPrivate fd = fileInputStream.callObjectMethod("getFD", + "()Ljava/io/FileDescriptor;"); + if (exceptionCheckAndClear(env)) { + fileInputStream.callMethod("close"); + exceptionCheckAndClear(env); + return false; + } - QJNIObjectPrivate uri = m_metadataRetriever.callStaticObjectMethod("android/net/Uri", - "parse", - "(Ljava/lang/String;)Landroid/net/Uri;", - string.object()); - if (env->ExceptionCheck()) { - env->ExceptionClear(); - } else { m_metadataRetriever.callMethod("setDataSource", - "(Landroid/content/Context;Landroid/net/Uri;)V", - QtAndroidPrivate::activity(), - uri.object()); - if (env->ExceptionCheck()) - env->ExceptionClear(); - else - loaded = true; - } + "(Ljava/io/FileDescriptor;)V", + fd.object()); + + bool ok = !exceptionCheckAndClear(env); + + fileInputStream.callMethod("close"); + exceptionCheckAndClear(env); + + if (!ok) + return false; + } else if (url.scheme() == QLatin1String("assets")) { + QJNIObjectPrivate string = QJNIObjectPrivate::fromString(url.path().mid(1)); // remove first '/' + QJNIObjectPrivate activity(QtAndroidPrivate::activity()); + QJNIObjectPrivate assetManager = activity.callObjectMethod("getAssets", + "()Landroid/content/res/AssetManager;"); + QJNIObjectPrivate assetFd = assetManager.callObjectMethod("openFd", + "(Ljava/lang/String;)Landroid/content/res/AssetFileDescriptor;", + string.object()); + if (exceptionCheckAndClear(env)) + return false; + + QJNIObjectPrivate fd = assetFd.callObjectMethod("getFileDescriptor", + "()Ljava/io/FileDescriptor;"); + if (exceptionCheckAndClear(env)) { + assetFd.callMethod("close"); + exceptionCheckAndClear(env); + return false; + } - return loaded; -} + m_metadataRetriever.callMethod("setDataSource", + "(Ljava/io/FileDescriptor;JJ)V", + fd.object(), + assetFd.callMethod("getStartOffset"), + assetFd.callMethod("getLength")); -bool AndroidMediaMetadataRetriever::setDataSource(const QString &path) -{ - if (!m_metadataRetriever.isValid()) - return false; + bool ok = !exceptionCheckAndClear(env); - QJNIEnvironmentPrivate env; + assetFd.callMethod("close"); + exceptionCheckAndClear(env); - bool loaded = false; + if (!ok) + return false; + } else if (QtAndroidPrivate::androidSdkVersion() >= 14) { + // On API levels >= 14, only setDataSource(String, Map) accepts remote media + QJNIObjectPrivate string = QJNIObjectPrivate::fromString(urlString); + QJNIObjectPrivate hash("java/util/HashMap"); - m_metadataRetriever.callMethod("setDataSource", - "(Ljava/lang/String;)V", - QJNIObjectPrivate::fromString(path).object()); - if (env->ExceptionCheck()) - env->ExceptionClear(); - else - loaded = true; + m_metadataRetriever.callMethod("setDataSource", + "(Ljava/lang/String;Ljava/util/Map;)V", + string.object(), + hash.object()); + if (exceptionCheckAndClear(env)) + return false; + } else { + // While on API levels < 14, only setDataSource(Context, Uri) is available and works for + // remote media... + QJNIObjectPrivate string = QJNIObjectPrivate::fromString(urlString); + QJNIObjectPrivate uri = m_metadataRetriever.callStaticObjectMethod("android/net/Uri", + "parse", + "(Ljava/lang/String;)Landroid/net/Uri;", + string.object()); + if (exceptionCheckAndClear(env)) + return false; + + m_metadataRetriever.callMethod("setDataSource", + "(Landroid/content/Context;Landroid/net/Uri;)V", + QtAndroidPrivate::activity(), + uri.object()); + if (exceptionCheckAndClear(env)) + return false; + } - return loaded; + return true; } QT_END_NAMESPACE diff --git a/src/plugins/android/src/wrappers/jni/androidmediametadataretriever.h b/src/plugins/android/src/wrappers/jni/androidmediametadataretriever.h index f18cec11d..1a4a876ee 100644 --- a/src/plugins/android/src/wrappers/jni/androidmediametadataretriever.h +++ b/src/plugins/android/src/wrappers/jni/androidmediametadataretriever.h @@ -43,7 +43,6 @@ #define ANDROIDMEDIAMETADATARETRIEVER_H #include -#include QT_BEGIN_NAMESPACE @@ -81,8 +80,7 @@ public: QString extractMetadata(MetadataKey key); void release(); - bool setDataSource(const QUrl &url); - bool setDataSource(const QString &path); + bool setDataSource(const QString &url); private: QJNIObjectPrivate m_metadataRetriever; -- cgit v1.2.3 From bee6244e2428c4a2f4b62dd1e8896f310b2208c8 Mon Sep 17 00:00:00 2001 From: Yoann Lopes Date: Thu, 8 May 2014 15:22:11 +0200 Subject: AVFoundation: fix retrieving tracks information from live sources. For live sources, tracks information is available only after the AVPlayer changed its status to AVPlayerStatusReadyToPlay. It also seems to be available only from AVPlayerItem.tracks rather than AVAsset.tracks. The audioAvailableChanged() and videoAvailableChanged() signals are now correclty emitted and the video layer is correctly positioned for live sources. Task-number: QTBUG-38666 Change-Id: I8ee015a6ce81694c1fc1e44c679887cf7ccb0fd6 Reviewed-by: Andy Nichols --- .../mediaplayer/avfmediaplayersession.h | 3 + .../mediaplayer/avfmediaplayersession.mm | 103 +++++++++++---------- 2 files changed, 55 insertions(+), 51 deletions(-) diff --git a/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.h b/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.h index 58a2d84c9..18e923aec 100644 --- a/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.h +++ b/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.h @@ -156,6 +156,9 @@ private: QByteArray rawData; }; + void setAudioAvailable(bool available); + void setVideoAvailable(bool available); + AVFMediaPlayerService *m_service; AVFVideoOutput *m_videoOutput; diff --git a/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm b/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm index a73974ccd..106e81a37 100644 --- a/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm +++ b/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm @@ -70,15 +70,11 @@ static void *AVFMediaPlayerSessionObserverCurrentItemObservationContext = &AVFMe AVPlayerItem *m_playerItem; AVPlayerLayer *m_playerLayer; NSURL *m_URL; - bool m_audioAvailable; - bool m_videoAvailable; } @property (readonly, getter=player) AVPlayer* m_player; @property (readonly, getter=playerItem) AVPlayerItem* m_playerItem; @property (readonly, getter=playerLayer) AVPlayerLayer* m_playerLayer; -@property (readonly, getter=audioAvailable) bool m_audioAvailable; -@property (readonly, getter=videoAvailable) bool m_videoAvailable; @property (readonly, getter=session) AVFMediaPlayerSession* m_session; - (AVFMediaPlayerSessionObserver *) initWithMediaPlayerSession:(AVFMediaPlayerSession *)session; @@ -96,7 +92,7 @@ static void *AVFMediaPlayerSessionObserverCurrentItemObservationContext = &AVFMe @implementation AVFMediaPlayerSessionObserver -@synthesize m_player, m_playerItem, m_playerLayer, m_audioAvailable, m_videoAvailable, m_session; +@synthesize m_player, m_playerItem, m_playerLayer, m_session; - (AVFMediaPlayerSessionObserver *) initWithMediaPlayerSession:(AVFMediaPlayerSession *)session { @@ -186,18 +182,6 @@ static void *AVFMediaPlayerSessionObserverCurrentItemObservationContext = &AVFMe return; } - m_audioAvailable = false; - m_videoAvailable = false; - - //Check each track of asset for audio and video content - NSArray *tracks = [asset tracks]; - for (AVAssetTrack *track in tracks) { - if ([track hasMediaCharacteristic:AVMediaCharacteristicAudible]) - m_audioAvailable = true; - if ([track hasMediaCharacteristic:AVMediaCharacteristicVisual]) - m_videoAvailable = true; - } - //At this point we're ready to set up for playback of the asset. //Stop observing our prior AVPlayerItem, if we have one. if (m_playerItem) @@ -258,18 +242,7 @@ static void *AVFMediaPlayerSessionObserverCurrentItemObservationContext = &AVFMe m_playerLayer = [AVPlayerLayer playerLayerWithPlayer:m_player]; [m_playerLayer retain]; m_playerLayer.videoGravity = AVLayerVideoGravityResizeAspectFill; - - //Get the native size of the new item, and reset the bounds of the player layer - AVAsset *asset = m_playerItem.asset; - if (asset) { - NSArray *tracks = [asset tracksWithMediaType:AVMediaTypeVideo]; - if ([tracks count]) { - AVAssetTrack *videoTrack = [tracks objectAtIndex:0]; - m_playerLayer.anchorPoint = CGPointMake(0.0f, 0.0f); - m_playerLayer.bounds = CGRectMake(0.0f, 0.0f, videoTrack.naturalSize.width, videoTrack.naturalSize.height); - } - } - + m_playerLayer.anchorPoint = CGPointMake(0.0f, 0.0f); } //Observe the AVPlayer "currentItem" property to find out when any @@ -366,22 +339,8 @@ static void *AVFMediaPlayerSessionObserverCurrentItemObservationContext = &AVFMe { AVPlayerItem *newPlayerItem = [change objectForKey:NSKeyValueChangeNewKey]; if (m_playerItem != newPlayerItem) - { m_playerItem = newPlayerItem; - //Get the native size of the new item, and reset the bounds of the player layer - //AVAsset *asset = m_playerItem.asset; - AVAsset *asset = [m_playerItem asset]; - if (asset) { - NSArray *tracks = [asset tracksWithMediaType:AVMediaTypeVideo]; - if ([tracks count]) { - AVAssetTrack *videoTrack = [tracks objectAtIndex:0]; - m_playerLayer.anchorPoint = CGPointMake(0.0f, 0.0f); - m_playerLayer.bounds = CGRectMake(0.0f, 0.0f, videoTrack.naturalSize.width, videoTrack.naturalSize.height); - } - } - - } if (self.session) QMetaObject::invokeMethod(m_session, "processCurrentItemChanged", Qt::AutoConnection); } @@ -513,6 +472,9 @@ void AVFMediaPlayerSession::setMedia(const QMediaContent &content, QIODevice *st m_resources = content; m_mediaStream = stream; + setAudioAvailable(false); + setVideoAvailable(false); + QMediaPlayer::MediaStatus oldMediaStatus = m_mediaStatus; if (content.isNull() || content.canonicalUrl().isEmpty()) { @@ -582,14 +544,32 @@ bool AVFMediaPlayerSession::isMuted() const return m_muted; } +void AVFMediaPlayerSession::setAudioAvailable(bool available) +{ + if (m_audioAvailable == available) + return; + + m_audioAvailable = available; + Q_EMIT audioAvailableChanged(available); +} + bool AVFMediaPlayerSession::isAudioAvailable() const { - return [(AVFMediaPlayerSessionObserver*)m_observer audioAvailable]; + return m_audioAvailable; +} + +void AVFMediaPlayerSession::setVideoAvailable(bool available) +{ + if (m_videoAvailable == available) + return; + + m_videoAvailable = available; + Q_EMIT videoAvailableChanged(available); } bool AVFMediaPlayerSession::isVideoAvailable() const { - return [(AVFMediaPlayerSessionObserver*)m_observer videoAvailable]; + return m_videoAvailable; } bool AVFMediaPlayerSession::isSeekable() const @@ -802,16 +782,37 @@ void AVFMediaPlayerSession::processLoadStateChange() bool isPlaying = (m_state != QMediaPlayer::StoppedState); if (currentStatus == AVPlayerStatusReadyToPlay) { + AVPlayerItem *playerItem = [(AVFMediaPlayerSessionObserver*)m_observer playerItem]; + if (playerItem) { + // Check each track for audio and video content + AVAssetTrack *videoTrack = nil; + NSArray *tracks = playerItem.tracks; + for (AVPlayerItemTrack *track in tracks) { + AVAssetTrack *assetTrack = track.assetTrack; + if (assetTrack) { + if ([assetTrack.mediaType isEqualToString:AVMediaTypeAudio]) + setAudioAvailable(true); + if ([assetTrack.mediaType isEqualToString:AVMediaTypeVideo]) { + setVideoAvailable(true); + if (!videoTrack) + videoTrack = assetTrack; + } + } + } + + // Get the native size of the video, and reset the bounds of the player layer + AVPlayerLayer *playerLayer = [(AVFMediaPlayerSessionObserver*)m_observer playerLayer]; + if (videoTrack && playerLayer) { + playerLayer.bounds = CGRectMake(0.0f, 0.0f, + videoTrack.naturalSize.width, + videoTrack.naturalSize.height); + } + } + qint64 currentDuration = duration(); if (m_duration != currentDuration) Q_EMIT durationChanged(m_duration = currentDuration); - if (m_audioAvailable != isAudioAvailable()) - Q_EMIT audioAvailableChanged(m_audioAvailable = !m_audioAvailable); - - if (m_videoAvailable != isVideoAvailable()) - Q_EMIT videoAvailableChanged(m_videoAvailable = !m_videoAvailable); - newStatus = isPlaying ? QMediaPlayer::BufferedMedia : QMediaPlayer::LoadedMedia; if (m_state == QMediaPlayer::PlayingState && [(AVFMediaPlayerSessionObserver*)m_observer player]) { -- cgit v1.2.3 From 5f0f81bcc1b82ea3418e4e5ce939ce22b11af0af Mon Sep 17 00:00:00 2001 From: Yoann Lopes Date: Thu, 5 Jun 2014 15:25:55 +0200 Subject: AVFoundation: fix some controls not being correctly destroyed on iOS. This patch also makes sure AVF video layers are removed from their parent layer when their corresponding Qt video outputs are destroyed. Task-number: QTBUG-39385 Change-Id: I164cd0da7084f84c0473ed3e396e734acce2a22e Reviewed-by: Andy Nichols --- src/plugins/avfoundation/camera/avfcameraservice.mm | 4 ++-- src/plugins/avfoundation/mediaplayer/avfmediaplayerservice.mm | 5 +++-- src/plugins/avfoundation/mediaplayer/avfvideowidget.mm | 4 +++- src/plugins/avfoundation/mediaplayer/avfvideowindowcontrol.mm | 4 +++- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/plugins/avfoundation/camera/avfcameraservice.mm b/src/plugins/avfoundation/camera/avfcameraservice.mm index 25111c5cc..966202ede 100644 --- a/src/plugins/avfoundation/camera/avfcameraservice.mm +++ b/src/plugins/avfoundation/camera/avfcameraservice.mm @@ -135,9 +135,9 @@ QMediaControl *AVFCameraService::requestControl(const char *name) void AVFCameraService::releaseControl(QMediaControl *control) { if (m_videoOutput == control) { - m_videoOutput = 0; m_session->setVideoOutput(0); - delete control; + delete m_videoOutput; + m_videoOutput = 0; } } diff --git a/src/plugins/avfoundation/mediaplayer/avfmediaplayerservice.mm b/src/plugins/avfoundation/mediaplayer/avfmediaplayerservice.mm index e5549803f..bb75adb8b 100644 --- a/src/plugins/avfoundation/mediaplayer/avfmediaplayerservice.mm +++ b/src/plugins/avfoundation/mediaplayer/avfmediaplayerservice.mm @@ -118,14 +118,15 @@ void AVFMediaPlayerService::releaseControl(QMediaControl *control) #ifdef QT_DEBUG_AVF qDebug() << Q_FUNC_INFO << control; #endif -#if defined(Q_OS_OSX) if (m_videoOutput == control) { +#if defined(Q_OS_OSX) AVFVideoRendererControl *renderControl = qobject_cast(m_videoOutput); if (renderControl) renderControl->setSurface(0); +#endif m_videoOutput = 0; m_session->setVideoOutput(0); + delete control; } -#endif } diff --git a/src/plugins/avfoundation/mediaplayer/avfvideowidget.mm b/src/plugins/avfoundation/mediaplayer/avfvideowidget.mm index d4fa7c4c6..2893921f3 100644 --- a/src/plugins/avfoundation/mediaplayer/avfvideowidget.mm +++ b/src/plugins/avfoundation/mediaplayer/avfvideowidget.mm @@ -64,8 +64,10 @@ AVFVideoWidget::~AVFVideoWidget() qDebug() << Q_FUNC_INFO; #endif - if (m_playerLayer) + if (m_playerLayer) { + [m_playerLayer removeFromSuperlayer]; [m_playerLayer release]; + } } QSize AVFVideoWidget::sizeHint() const diff --git a/src/plugins/avfoundation/mediaplayer/avfvideowindowcontrol.mm b/src/plugins/avfoundation/mediaplayer/avfvideowindowcontrol.mm index 17fc94de7..8e96d732f 100644 --- a/src/plugins/avfoundation/mediaplayer/avfvideowindowcontrol.mm +++ b/src/plugins/avfoundation/mediaplayer/avfvideowindowcontrol.mm @@ -61,8 +61,10 @@ AVFVideoWindowControl::AVFVideoWindowControl(QObject *parent) AVFVideoWindowControl::~AVFVideoWindowControl() { - if (m_playerLayer) + if (m_playerLayer) { + [m_playerLayer removeFromSuperlayer]; [m_playerLayer release]; + } } WId AVFVideoWindowControl::winId() const -- cgit v1.2.3 From 20da381608c61930e2eea46fe0175a355eac9a73 Mon Sep 17 00:00:00 2001 From: Yoann Lopes Date: Mon, 14 Jul 2014 16:44:49 +0200 Subject: WMF: fix bufferStatus() and availablePlaybackRanges(). - Correctly initialize and clear PROPVARIANT structures - Return coherent data even when the information is not available Change-Id: I22b46f95f255cbb740a154c6296a5c3a91e64f67 Reviewed-by: Christian Stromme --- src/plugins/wmf/player/mfplayersession.cpp | 41 +++++++++++++++++++----------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/src/plugins/wmf/player/mfplayersession.cpp b/src/plugins/wmf/player/mfplayersession.cpp index f61f7aba2..09c5a8c52 100644 --- a/src/plugins/wmf/player/mfplayersession.cpp +++ b/src/plugins/wmf/player/mfplayersession.cpp @@ -1403,14 +1403,17 @@ int MFPlayerSession::bufferStatus() if (!m_netsourceStatistics) return 0; PROPVARIANT var; + PropVariantInit(&var); PROPERTYKEY key; key.fmtid = MFNETSOURCE_STATISTICS; key.pid = MFNETSOURCE_BUFFERPROGRESS_ID; int progress = -1; - if (SUCCEEDED(m_netsourceStatistics->GetValue(key, &var))) { + // GetValue returns S_FALSE if the property is not available, which has + // a value > 0. We therefore can't use the SUCCEEDED macro here. + if (m_netsourceStatistics->GetValue(key, &var) == S_OK) { progress = var.lVal; + PropVariantClear(&var); } - PropVariantClear(&var); #ifdef DEBUG_MEDIAFOUNDATION qDebug() << "bufferStatus: progress = " << progress; @@ -1421,22 +1424,30 @@ int MFPlayerSession::bufferStatus() QMediaTimeRange MFPlayerSession::availablePlaybackRanges() { - if (!m_netsourceStatistics) - return QMediaTimeRange(); + // defaults to the whole media + qint64 start = 0; + qint64 end = qint64(m_duration / 10000); - qint64 start = 0, end = 0; - PROPVARIANT var; - PROPERTYKEY key; - key.fmtid = MFNETSOURCE_STATISTICS; - key.pid = MFNETSOURCE_SEEKRANGESTART_ID; - if (SUCCEEDED(m_netsourceStatistics->GetValue(key, &var))) { - start = qint64(var.uhVal.QuadPart / 10000); - key.pid = MFNETSOURCE_SEEKRANGEEND_ID; - if (SUCCEEDED(m_netsourceStatistics->GetValue(key, &var))) { - end = qint64(var.uhVal.QuadPart / 10000); + if (m_netsourceStatistics) { + PROPVARIANT var; + PropVariantInit(&var); + PROPERTYKEY key; + key.fmtid = MFNETSOURCE_STATISTICS; + key.pid = MFNETSOURCE_SEEKRANGESTART_ID; + // GetValue returns S_FALSE if the property is not available, which has + // a value > 0. We therefore can't use the SUCCEEDED macro here. + if (m_netsourceStatistics->GetValue(key, &var) == S_OK) { + start = qint64(var.uhVal.QuadPart / 10000); + PropVariantClear(&var); + PropVariantInit(&var); + key.pid = MFNETSOURCE_SEEKRANGEEND_ID; + if (m_netsourceStatistics->GetValue(key, &var) == S_OK) { + end = qint64(var.uhVal.QuadPart / 10000); + PropVariantClear(&var); + } } } - PropVariantClear(&var); + return QMediaTimeRange(start, end); } -- cgit v1.2.3 From b3c2dca466042cf362ffb8d803bf05c9b8a0f95f Mon Sep 17 00:00:00 2001 From: Bjoern Breitmeyer Date: Fri, 22 Aug 2014 14:59:11 +0200 Subject: Restore QWindowsAudio support on wince. Enabled Audio playback with wave device on WindowsCE again. Change-Id: Ic7749821ef8f991a909cbeb29083219ea988f5dc Reviewed-by: Yoann Lopes --- config.tests/wmp/main.cpp | 5 +++- config.tests/wmp/wmp.pro | 3 ++- .../windowsaudio/qwindowsaudiodeviceinfo.cpp | 30 ++++++++++++++++++++++ src/plugins/windowsaudio/windowsaudio.pro | 3 ++- 4 files changed, 38 insertions(+), 3 deletions(-) diff --git a/config.tests/wmp/main.cpp b/config.tests/wmp/main.cpp index 1667ebc8a..50f4bf6c2 100644 --- a/config.tests/wmp/main.cpp +++ b/config.tests/wmp/main.cpp @@ -38,8 +38,11 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ - +#ifndef _WIN32_WCE #include +#else +#include +#endif int main(int, char**) { diff --git a/config.tests/wmp/wmp.pro b/config.tests/wmp/wmp.pro index b16509cc4..563de1453 100644 --- a/config.tests/wmp/wmp.pro +++ b/config.tests/wmp/wmp.pro @@ -3,4 +3,5 @@ CONFIG += console SOURCES += main.cpp -LIBS += -lstrmiids -lole32 -lOleaut32 -luser32 -lgdi32 +LIBS += -lstrmiids -lole32 -lOleaut32 +!wince*:LIBS += -luser32 -lgdi32 diff --git a/src/plugins/windowsaudio/qwindowsaudiodeviceinfo.cpp b/src/plugins/windowsaudio/qwindowsaudiodeviceinfo.cpp index d37056a5f..98c161ae5 100644 --- a/src/plugins/windowsaudio/qwindowsaudiodeviceinfo.cpp +++ b/src/plugins/windowsaudio/qwindowsaudiodeviceinfo.cpp @@ -412,6 +412,7 @@ QList QWindowsAudioDeviceInfo::availableDevices(QAudio::Mode mode) Q_UNUSED(mode) QList devices; +#ifndef Q_OS_WINCE //enumerate device fullnames through directshow api CoInitialize(NULL); ICreateDevEnum *pDevEnum = NULL; @@ -463,6 +464,35 @@ QList QWindowsAudioDeviceInfo::availableDevices(QAudio::Mode mode) } } CoUninitialize(); +#else // Q_OS_WINCE + if (mode == QAudio::AudioOutput) { + WAVEOUTCAPS woc; + unsigned long iNumDevs,i; + iNumDevs = waveOutGetNumDevs(); + for (i=0;i Date: Tue, 26 Aug 2014 13:53:55 +0200 Subject: Added 5.3.2 change file. Change-Id: I865ae833267c6e91bf61e15acf1acb4292e5c3b2 Reviewed-by: Jani Heikkinen Reviewed-by: Christian Stromme --- dist/changes-5.3.2 | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 dist/changes-5.3.2 diff --git a/dist/changes-5.3.2 b/dist/changes-5.3.2 new file mode 100644 index 000000000..b427bb809 --- /dev/null +++ b/dist/changes-5.3.2 @@ -0,0 +1,65 @@ +Qt 5.3.2 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.3.0 and 5.3.1. + +For more details, refer to the online documentation included in this +distribution. The documentation is also available online: + + http://qt-project.org/doc/qt-5.3 + +The Qt version 5.3 series is binary compatible with the 5.2.x series. +Applications compiled for 5.2 will continue to run with 5.3. + +Some of the changes listed in this file include issue tracking numbers +corresponding to tasks in the Qt Bug Tracker: + + http://bugreports.qt-project.org/ + +Each of these identifiers can be entered in the bug tracker to obtain more +information about a particular change. + +**************************************************************************** +* Platform Specific Changes * +**************************************************************************** + +Android +------- + + - Fixed regression causing videos recorded with the camera not to be registered with the Android + media scanner, making them invisible to media browsing apps. + - Fixed crash when unloading a QCamera while a recording is active. + - [QTBUG-39307] Setting camera parameters on the QML Camera type (e.g. digitalZoom, flashMode) + now works correctly when set before the camera is loaded. + - [QTBUG-40208] QAudioOutput::setNotifyInterval() can now be used when the output is active. + - [QTBUG-40274] Fixed metadata not being loaded by the MediaPlayer when playing a remote media, + from a qrc file or from assets. + +iOS +--- + + - [QTBUG-39036] Audio played using SoundEffect or QAudioOutput is now correctly muted when the + device is set to silent mode or when the screen is locked. + - [QTBUG-39385] The last video frame displayed in a QML VideoOutput doesn't remain on screen + anymore after destroying the VideoOutput. + +Linux +----- + + - MediaPlayer's loops property now works correctly when playing a media from a qrc file. + - [QTBUG-29742] Fixed Qt apps hanging when audio APIs are used and PulseAudio is not running. + - [QTBUG-39949] Fixed QMediaRecorder::setOutputLocation() not working with QUrl::fromLocalFile(). + +OS X +---- + + - Application doesn't freeze anymore when changing the system audio output device while audio + is being played with QSoundEffect or QAudioOutput. + - [QTBUG-38666] Video frames are now correctly positioned on screen when playing a live stream + in a QVideoWidget. This also applies to iOS. + - [QTBUG-38668] Fixed crash when setting QMediaRecorder's output location to a URL containing + nonstandard characters. + +Windows +------- + + - The DirectShow camera backend has been almost entirely rewritten. It doesn't provide any new + feature but it now works as it should. -- cgit v1.2.3