summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.qmake.conf2
-rw-r--r--config.tests/directshow/directshow.pro2
-rw-r--r--config.tests/directshow/main.cpp2
-rw-r--r--config.tests/wasapi/main.cpp53
-rw-r--r--config.tests/wasapi/wasapi.pro2
-rw-r--r--examples/multimedia/audioinput/audioinput.cpp14
-rw-r--r--examples/multimedia/audiooutput/audiooutput.cpp15
-rw-r--r--examples/multimediawidgets/player/playercontrols.cpp21
-rw-r--r--examples/multimediawidgets/player/playercontrols.h1
-rw-r--r--qtmultimedia.pro1
-rw-r--r--src/gsttools/gsttools.pro4
-rw-r--r--src/gsttools/qgstutils.cpp35
-rw-r--r--src/imports/audioengine/audioengine.cpp2
-rw-r--r--src/imports/multimedia/Video.qml12
-rw-r--r--src/imports/multimedia/multimedia.cpp5
-rw-r--r--src/imports/multimedia/plugins.qmltypes23
-rw-r--r--src/imports/multimedia/qdeclarativeaudio.cpp24
-rw-r--r--src/imports/multimedia/qdeclarativemultimediaglobal.cpp53
-rw-r--r--src/imports/multimedia/qdeclarativemultimediaglobal_p.h12
-rw-r--r--src/multimedia/audio/audio.pri3
-rw-r--r--src/multimedia/audio/qaudio.cpp154
-rw-r--r--src/multimedia/audio/qaudio.h11
-rw-r--r--src/multimedia/audio/qaudiodevicefactory.cpp73
-rw-r--r--src/multimedia/audio/qaudiodevicefactory_p.h3
-rw-r--r--src/multimedia/audio/qaudiodeviceinfo.cpp4
-rw-r--r--src/multimedia/audio/qaudioinput.cpp7
-rw-r--r--src/multimedia/audio/qaudiooutput.cpp13
-rw-r--r--src/multimedia/audio/qaudiosystemplugin.cpp31
-rw-r--r--src/multimedia/audio/qaudiosystempluginext_p.h71
-rw-r--r--src/multimedia/audio/qsoundeffect.cpp25
-rw-r--r--src/multimedia/controls/qmediaplayercontrol.cpp2
-rw-r--r--src/multimedia/controls/qmediarecordercontrol.cpp6
-rw-r--r--src/multimedia/doc/snippets/multimedia-snippets/audio.cpp16
-rw-r--r--src/multimedia/playback/qmediaplayer.cpp14
-rw-r--r--src/multimedia/qmediaopenglhelper_p.h4
-rw-r--r--src/multimedia/qmediastoragelocation.cpp2
-rw-r--r--src/multimedia/qmediatimerange.cpp11
-rw-r--r--src/multimedia/recording/qmediarecorder.cpp11
-rw-r--r--src/multimediawidgets/multimediawidgets.pro7
-rw-r--r--src/plugins/alsa/qalsaaudiodeviceinfo.cpp27
-rw-r--r--src/plugins/alsa/qalsaaudiodeviceinfo.h3
-rw-r--r--src/plugins/alsa/qalsaplugin.cpp5
-rw-r--r--src/plugins/alsa/qalsaplugin.h5
-rw-r--r--src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtAndroidMediaPlayer.java13
-rw-r--r--src/plugins/avfoundation/camera/avfcameraviewfindersettingscontrol.mm10
-rw-r--r--src/plugins/avfoundation/mediaplayer/mediaplayer.pro4
-rw-r--r--src/plugins/coreaudio/coreaudiodeviceinfo.h4
-rw-r--r--src/plugins/coreaudio/coreaudiodeviceinfo.mm53
-rw-r--r--src/plugins/coreaudio/coreaudioplugin.h7
-rw-r--r--src/plugins/coreaudio/coreaudioplugin.mm4
-rw-r--r--src/plugins/directshow/camera/camera.pri2
-rw-r--r--src/plugins/directshow/camera/directshowcameraglobal.h (renamed from src/plugins/directshow/camera/directshowglobal.h)4
-rw-r--r--src/plugins/directshow/camera/dscamerasession.cpp2
-rw-r--r--src/plugins/directshow/directshow.pro5
-rw-r--r--src/plugins/directshow/helpers/directshowbasefilter.cpp267
-rw-r--r--src/plugins/directshow/helpers/directshowbasefilter.h93
-rw-r--r--src/plugins/directshow/helpers/directshoweventloop.cpp (renamed from src/plugins/directshow/player/directshoweventloop.cpp)0
-rw-r--r--src/plugins/directshow/helpers/directshoweventloop.h (renamed from src/plugins/directshow/player/directshoweventloop.h)0
-rw-r--r--src/plugins/directshow/helpers/directshowglobal.h (renamed from src/plugins/directshow/player/directshowglobal.h)0
-rw-r--r--src/plugins/directshow/helpers/directshowmediatype.cpp (renamed from src/plugins/directshow/player/directshowmediatype.cpp)64
-rw-r--r--src/plugins/directshow/helpers/directshowmediatype.h (renamed from src/plugins/directshow/player/directshowmediatype.h)13
-rw-r--r--src/plugins/directshow/helpers/directshowmediatypeenum.cpp111
-rw-r--r--src/plugins/directshow/helpers/directshowmediatypeenum.h72
-rw-r--r--src/plugins/directshow/helpers/directshowobject.cpp (renamed from src/plugins/directshow/player/directshowmediatypelist.h)55
-rw-r--r--src/plugins/directshow/helpers/directshowobject.h74
-rw-r--r--src/plugins/directshow/helpers/directshowpin.cpp733
-rw-r--r--src/plugins/directshow/helpers/directshowpin.h184
-rw-r--r--src/plugins/directshow/helpers/directshowpinenum.cpp (renamed from src/plugins/directshow/player/directshowpinenum.cpp)52
-rw-r--r--src/plugins/directshow/helpers/directshowpinenum.h (renamed from src/plugins/directshow/player/directshowpinenum.h)30
-rw-r--r--src/plugins/directshow/helpers/directshowvideobuffer.cpp (renamed from src/plugins/directshow/player/mediasamplevideobuffer.cpp)12
-rw-r--r--src/plugins/directshow/helpers/directshowvideobuffer.h (renamed from src/plugins/directshow/player/mediasamplevideobuffer.h)10
-rw-r--r--src/plugins/directshow/helpers/helpers.pri22
-rw-r--r--src/plugins/directshow/player/directshowiosource.cpp22
-rw-r--r--src/plugins/directshow/player/directshowiosource.h5
-rw-r--r--src/plugins/directshow/player/directshowmediatypelist.cpp228
-rw-r--r--src/plugins/directshow/player/directshowplayercontrol.cpp29
-rw-r--r--src/plugins/directshow/player/directshowplayerservice.cpp28
-rw-r--r--src/plugins/directshow/player/directshowplayerservice.h4
-rw-r--r--src/plugins/directshow/player/directshowsamplescheduler.cpp435
-rw-r--r--src/plugins/directshow/player/directshowsamplescheduler.h115
-rw-r--r--src/plugins/directshow/player/player.pri32
-rw-r--r--src/plugins/directshow/player/videosurfacefilter.cpp919
-rw-r--r--src/plugins/directshow/player/videosurfacefilter.h170
-rw-r--r--src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp1
-rw-r--r--src/plugins/opensles/qopenslesaudiooutput.cpp4
-rw-r--r--src/plugins/opensles/qopenslesengine.cpp6
-rw-r--r--src/plugins/opensles/qopenslesengine.h1
-rw-r--r--src/plugins/opensles/qopenslesplugin.cpp5
-rw-r--r--src/plugins/opensles/qopenslesplugin.h7
-rw-r--r--src/plugins/plugins.pro11
-rw-r--r--src/plugins/pulseaudio/qpulseaudioengine.cpp5
-rw-r--r--src/plugins/pulseaudio/qpulseaudioengine.h3
-rw-r--r--src/plugins/pulseaudio/qpulseaudioplugin.cpp5
-rw-r--r--src/plugins/pulseaudio/qpulseaudioplugin.h7
-rw-r--r--src/plugins/qnx-audio/audio/qnxaudioplugin.cpp5
-rw-r--r--src/plugins/qnx-audio/audio/qnxaudioplugin.h7
-rw-r--r--src/plugins/videonode/videonode.pro3
-rw-r--r--src/plugins/wasapi/qwasapiplugin.cpp5
-rw-r--r--src/plugins/wasapi/qwasapiplugin.h7
-rw-r--r--src/plugins/wasapi/qwasapiutils.cpp66
-rw-r--r--src/plugins/wasapi/qwasapiutils.h1
-rw-r--r--src/plugins/windowsaudio/qwindowsaudiodeviceinfo.cpp46
-rw-r--r--src/plugins/windowsaudio/qwindowsaudiodeviceinfo.h3
-rw-r--r--src/plugins/windowsaudio/qwindowsaudioplugin.cpp5
-rw-r--r--src/plugins/windowsaudio/qwindowsaudioplugin.h5
-rw-r--r--src/plugins/windowsaudio/windowsaudio.pro3
-rw-r--r--src/plugins/winrt/qwinrtcameracontrol.cpp11
-rw-r--r--src/plugins/winrt/qwinrtcameracontrol.h2
-rw-r--r--src/plugins/winrt/qwinrtcameraflashcontrol.cpp191
-rw-r--r--src/plugins/winrt/qwinrtcameraflashcontrol.h76
-rw-r--r--src/plugins/winrt/qwinrtcamerafocuscontrol.cpp164
-rw-r--r--src/plugins/winrt/qwinrtcamerafocuscontrol.h3
-rw-r--r--src/plugins/winrt/qwinrtcameraservice.cpp4
-rw-r--r--src/plugins/winrt/qwinrtcameravideorenderercontrol.cpp3
-rw-r--r--src/plugins/winrt/winrt.pro2
-rw-r--r--src/qtmultimediaquicktools/qsgvideonode_texture.cpp2
-rw-r--r--src/qtmultimediaquicktools/qsgvideonode_yuv.cpp99
-rw-r--r--src/qtmultimediaquicktools/qtmultimediaquicktools.pro6
-rw-r--r--src/qtmultimediaquicktools/qtmultimediaquicktools.qrc4
-rw-r--r--src/qtmultimediaquicktools/shaders/monoplanarvideo.vert (renamed from src/qtmultimediaquicktools/shaders/rgbvideo.vert)0
-rw-r--r--src/qtmultimediaquicktools/shaders/uyvyvideo.frag22
-rw-r--r--src/qtmultimediaquicktools/shaders/yuyvvideo.frag22
-rw-r--r--src/src.pro2
-rw-r--r--tests/auto/integration/qaudiodeviceinfo/tst_qaudiodeviceinfo.cpp6
-rw-r--r--tests/auto/integration/qmediaplayerbackend/BLACKLIST7
-rw-r--r--tests/auto/integration/qsoundeffect/BLACKLIST2
-rw-r--r--tests/auto/integration/qsoundeffect/qsoundeffect.pro3
-rw-r--r--tests/auto/unit/multimediawidgets.pro2
-rw-r--r--tests/auto/unit/qaudionamespace/tst_qaudionamespace.cpp150
-rw-r--r--tests/auto/unit/qdeclarativemultimediaglobal/tst_qdeclarativemultimediaglobal.qml114
-rw-r--r--tests/auto/unit/qmediapluginloader/qmediapluginloader.pro7
-rw-r--r--tests/auto/unit/qpaintervideosurface/qpaintervideosurface.pro6
132 files changed, 3949 insertions, 1850 deletions
diff --git a/.qmake.conf b/.qmake.conf
index a2a0d4189..aefa1e701 100644
--- a/.qmake.conf
+++ b/.qmake.conf
@@ -1,3 +1,3 @@
load(qt_build_config)
-MODULE_VERSION = 5.7.1
+MODULE_VERSION = 5.8.0
diff --git a/config.tests/directshow/directshow.pro b/config.tests/directshow/directshow.pro
index 6dfc54a01..6493e54ab 100644
--- a/config.tests/directshow/directshow.pro
+++ b/config.tests/directshow/directshow.pro
@@ -3,4 +3,4 @@ CONFIG += console
SOURCES += main.cpp
-!wince: LIBS += -lstrmiids -ldmoguids -luuid -lmsdmo -lole32 -loleaut32
+LIBS += -lstrmiids -ldmoguids -luuid -lmsdmo -lole32 -loleaut32
diff --git a/config.tests/directshow/main.cpp b/config.tests/directshow/main.cpp
index bb9a304ec..25e36f966 100644
--- a/config.tests/directshow/main.cpp
+++ b/config.tests/directshow/main.cpp
@@ -27,10 +27,8 @@
****************************************************************************/
#include <dshow.h>
-#ifndef _WIN32_WCE
#include <d3d9.h>
#include <vmr9.h>
-#endif
int main(int, char**)
{
diff --git a/config.tests/wasapi/main.cpp b/config.tests/wasapi/main.cpp
new file mode 100644
index 000000000..85bef127b
--- /dev/null
+++ b/config.tests/wasapi/main.cpp
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtMultimedia module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <Audioclient.h>
+#include <wrl.h>
+#include <mmdeviceapi.h>
+
+class AudioInterface : public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags
+ <Microsoft::WRL::Delegate>, Microsoft::WRL::FtmBase, IActivateAudioInterfaceCompletionHandler>
+{
+public:
+ explicit AudioInterface() { }
+ ~AudioInterface() { }
+
+ virtual HRESULT STDMETHODCALLTYPE ActivateCompleted(IActivateAudioInterfaceAsyncOperation *) { }
+};
+
+int main(int, char**)
+{
+ IUnknown *aInterface = nullptr;
+ IAudioClient* client;
+ aInterface->QueryInterface(IID_PPV_ARGS(&client));
+
+ WAVEFORMATEX *format;
+ client->GetMixFormat(&format);
+
+ return 0;
+}
diff --git a/config.tests/wasapi/wasapi.pro b/config.tests/wasapi/wasapi.pro
new file mode 100644
index 000000000..4294c4775
--- /dev/null
+++ b/config.tests/wasapi/wasapi.pro
@@ -0,0 +1,2 @@
+SOURCES += main.cpp
+CONFIG += console
diff --git a/examples/multimedia/audioinput/audioinput.cpp b/examples/multimedia/audioinput/audioinput.cpp
index fd73d4f16..cdf56af99 100644
--- a/examples/multimedia/audioinput/audioinput.cpp
+++ b/examples/multimedia/audioinput/audioinput.cpp
@@ -315,7 +315,10 @@ void InputTest::initializeAudio()
void InputTest::createAudioInput()
{
m_audioInput = new QAudioInput(m_device, m_format, this);
- m_volumeSlider->setValue(m_audioInput->volume() * 100);
+ qreal initialVolume = QAudio::convertVolume(m_audioInput->volume(),
+ QAudio::LinearVolumeScale,
+ QAudio::LogarithmicVolumeScale);
+ m_volumeSlider->setValue(qRound(initialVolume * 100));
m_audioInfo->start();
m_audioInput->start(m_audioInfo);
}
@@ -386,6 +389,11 @@ void InputTest::deviceChanged(int index)
void InputTest::sliderChanged(int value)
{
- if (m_audioInput)
- m_audioInput->setVolume(qreal(value) / 100);
+ if (m_audioInput) {
+ qreal linearVolume = QAudio::convertVolume(value / qreal(100),
+ QAudio::LogarithmicVolumeScale,
+ QAudio::LinearVolumeScale);
+
+ m_audioInput->setVolume(linearVolume);
+ }
}
diff --git a/examples/multimedia/audiooutput/audiooutput.cpp b/examples/multimedia/audiooutput/audiooutput.cpp
index a00ffbb00..3e9ec7377 100644
--- a/examples/multimedia/audiooutput/audiooutput.cpp
+++ b/examples/multimedia/audiooutput/audiooutput.cpp
@@ -250,7 +250,11 @@ void AudioTest::createAudioOutput()
m_audioOutput = new QAudioOutput(m_device, m_format, this);
m_generator->start();
m_audioOutput->start(m_generator);
- m_volumeSlider->setValue(int(m_audioOutput->volume()*100.0f));
+
+ qreal initialVolume = QAudio::convertVolume(m_audioOutput->volume(),
+ QAudio::LinearVolumeScale,
+ QAudio::LogarithmicVolumeScale);
+ m_volumeSlider->setValue(qRound(initialVolume * 100));
}
AudioTest::~AudioTest()
@@ -270,8 +274,13 @@ void AudioTest::deviceChanged(int index)
void AudioTest::volumeChanged(int value)
{
- if (m_audioOutput)
- m_audioOutput->setVolume(qreal(value/100.0f));
+ if (m_audioOutput) {
+ qreal linearVolume = QAudio::convertVolume(value / qreal(100),
+ QAudio::LogarithmicVolumeScale,
+ QAudio::LinearVolumeScale);
+
+ m_audioOutput->setVolume(linearVolume);
+ }
}
void AudioTest::pushTimerExpired()
diff --git a/examples/multimediawidgets/player/playercontrols.cpp b/examples/multimediawidgets/player/playercontrols.cpp
index 07aa2e731..3d968b452 100644
--- a/examples/multimediawidgets/player/playercontrols.cpp
+++ b/examples/multimediawidgets/player/playercontrols.cpp
@@ -45,6 +45,7 @@
#include <QStyle>
#include <QToolButton>
#include <QComboBox>
+#include <QAudio>
PlayerControls::PlayerControls(QWidget *parent)
: QWidget(parent)
@@ -87,7 +88,7 @@ PlayerControls::PlayerControls(QWidget *parent)
volumeSlider = new QSlider(Qt::Horizontal, this);
volumeSlider->setRange(0, 100);
- connect(volumeSlider, SIGNAL(sliderMoved(int)), this, SIGNAL(changeVolume(int)));
+ connect(volumeSlider, SIGNAL(valueChanged(int)), this, SLOT(onVolumeSliderValueChanged()));
rateBox = new QComboBox(this);
rateBox->addItem("0.5x", QVariant(0.5));
@@ -138,13 +139,20 @@ void PlayerControls::setState(QMediaPlayer::State state)
int PlayerControls::volume() const
{
- return volumeSlider ? volumeSlider->value() : 0;
+ qreal linearVolume = QAudio::convertVolume(volumeSlider->value() / qreal(100),
+ QAudio::LogarithmicVolumeScale,
+ QAudio::LinearVolumeScale);
+
+ return qRound(linearVolume * 100);
}
void PlayerControls::setVolume(int volume)
{
- if (volumeSlider)
- volumeSlider->setValue(volume);
+ qreal logarithmicVolume = QAudio::convertVolume(volume / qreal(100),
+ QAudio::LinearVolumeScale,
+ QAudio::LogarithmicVolumeScale);
+
+ volumeSlider->setValue(qRound(logarithmicVolume * 100));
}
bool PlayerControls::isMuted() const
@@ -203,3 +211,8 @@ void PlayerControls::updateRate()
{
emit changeRate(playbackRate());
}
+
+void PlayerControls::onVolumeSliderValueChanged()
+{
+ emit changeVolume(volume());
+}
diff --git a/examples/multimediawidgets/player/playercontrols.h b/examples/multimediawidgets/player/playercontrols.h
index 0ab195faa..d29a06d6c 100644
--- a/examples/multimediawidgets/player/playercontrols.h
+++ b/examples/multimediawidgets/player/playercontrols.h
@@ -82,6 +82,7 @@ private slots:
void playClicked();
void muteClicked();
void updateRate();
+ void onVolumeSliderValueChanged();
private:
QMediaPlayer::State playerState;
diff --git a/qtmultimedia.pro b/qtmultimedia.pro
index 98bb3152f..8101d63eb 100644
--- a/qtmultimedia.pro
+++ b/qtmultimedia.pro
@@ -9,6 +9,7 @@ win32 {
qtCompileTest(evr)
qtCompileTest(wmsdk)
contains(QT_CONFIG, wmf-backend): qtCompileTest(wmf)
+ qtCompileTest(wasapi)
} else:mac {
qtCompileTest(avfoundation)
} else:qnx {
diff --git a/src/gsttools/gsttools.pro b/src/gsttools/gsttools.pro
index a5c1d9493..216189d9a 100644
--- a/src/gsttools/gsttools.pro
+++ b/src/gsttools/gsttools.pro
@@ -95,7 +95,7 @@ equals(GST_VERSION,"0.10") {
maemo6 {
PKGCONFIG_PRIVATE += qmsystem2
- contains(QT_CONFIG, opengles2):qtHaveModule(widgets) {
+ qtConfig(opengles2):qtHaveModule(widgets) {
PRIVATE_HEADERS += qgstreamergltexturerenderer_p.h
SOURCES += qgstreamergltexturerenderer.cpp
QT += opengl
@@ -113,7 +113,7 @@ equals(GST_VERSION,"0.10") {
}
mir: {
- contains(QT_CONFIG, opengles2):qtHaveModule(widgets) {
+ qtConfig(opengles2):qtHaveModule(widgets) {
PRIVATE_HEADERS += qgstreamermirtexturerenderer_p.h
SOURCES += qgstreamermirtexturerenderer.cpp
QT += opengl quick
diff --git a/src/gsttools/qgstutils.cpp b/src/gsttools/qgstutils.cpp
index b5299f151..a2b35073c 100644
--- a/src/gsttools/qgstutils.cpp
+++ b/src/gsttools/qgstutils.cpp
@@ -40,6 +40,7 @@
#include "qgstutils_p.h"
#include <QtCore/qdatetime.h>
+#include <QtCore/qtimezone.h>
#include <QtCore/qdir.h>
#include <QtCore/qbytearray.h>
#include <QtCore/qvariant.h>
@@ -123,6 +124,40 @@ static void addTagToMap(const GstTagList *list,
if (!map->contains("year"))
map->insert("year", year);
}
+#if GST_CHECK_VERSION(1,0,0)
+ } else if (G_VALUE_TYPE(&val) == GST_TYPE_DATE_TIME) {
+ const GstDateTime *dateTime = (const GstDateTime *)g_value_get_boxed(&val);
+ int year = gst_date_time_has_year(dateTime) ? gst_date_time_get_year(dateTime) : 0;
+ int month = gst_date_time_has_month(dateTime) ? gst_date_time_get_month(dateTime) : 0;
+ int day = gst_date_time_has_day(dateTime) ? gst_date_time_get_day(dateTime) : 0;
+ if (gst_date_time_has_time(dateTime)) {
+ int hour = gst_date_time_get_hour(dateTime);
+ int minute = gst_date_time_get_minute(dateTime);
+ int second = gst_date_time_get_second(dateTime);
+ float tz = gst_date_time_get_time_zone_offset(dateTime);
+ map->insert(QByteArray(tag), QDateTime(QDate(year,month,day), QTime(hour, minute, second), QTimeZone(tz * 60 * 60)));
+ } else if (year > 0 && month > 0 && day > 0) {
+ map->insert(QByteArray(tag), QDate(year,month,day));
+ }
+ if (!map->contains("year") && year > 0)
+ map->insert("year", year);
+ } else if (G_VALUE_TYPE(&val) == GST_TYPE_SAMPLE) {
+ GstSample *sample = (GstSample *)g_value_get_boxed(&val);
+ GstCaps* caps = gst_sample_get_caps(sample);
+ if (caps && !gst_caps_is_empty(caps)) {
+ GstStructure *structure = gst_caps_get_structure(caps, 0);
+ const gchar *name = gst_structure_get_name(structure);
+ if (QByteArray(name).startsWith("image/")) {
+ GstBuffer *buffer = gst_sample_get_buffer(sample);
+ if (buffer) {
+ GstMapInfo info;
+ gst_buffer_map(buffer, &info, GST_MAP_READ);
+ map->insert(QByteArray(tag), QImage::fromData(info.data, info.size, name));
+ gst_buffer_unmap(buffer, &info);
+ }
+ }
+ }
+#endif
} else if (G_VALUE_TYPE(&val) == GST_TYPE_FRACTION) {
int nom = gst_value_get_fraction_numerator(&val);
int denom = gst_value_get_fraction_denominator(&val);
diff --git a/src/imports/audioengine/audioengine.cpp b/src/imports/audioengine/audioengine.cpp
index 8eb2dea33..a132af49a 100644
--- a/src/imports/audioengine/audioengine.cpp
+++ b/src/imports/audioengine/audioengine.cpp
@@ -63,7 +63,7 @@ QT_BEGIN_NAMESPACE
class QAudioEngineDeclarativeModule : public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0")
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
QAudioEngineDeclarativeModule(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); }
diff --git a/src/imports/multimedia/Video.qml b/src/imports/multimedia/Video.qml
index 2188d17b9..b3fee7495 100644
--- a/src/imports/multimedia/Video.qml
+++ b/src/imports/multimedia/Video.qml
@@ -360,7 +360,17 @@ Item {
/*!
\qmlproperty real Video::volume
- This property holds the volume of the audio output, from 0.0 (silent) to 1.0 (maximum volume).
+ This property holds the audio volume.
+
+ The volume is scaled linearly from \c 0.0 (silence) to \c 1.0 (full volume). Values outside
+ this range will be clamped.
+
+ The default volume is \c 1.0.
+
+ UI volume controls should usually be scaled nonlinearly. For example, using a logarithmic
+ scale will produce linear changes in perceived loudness, which is what a user would normally
+ expect from a volume control. See \l {QtMultimedia::QtMultimedia::convertVolume()}{QtMultimedia.convertVolume()}
+ for more details.
*/
property alias volume: player.volume
diff --git a/src/imports/multimedia/multimedia.cpp b/src/imports/multimedia/multimedia.cpp
index 872b2ae61..b7ab473c7 100644
--- a/src/imports/multimedia/multimedia.cpp
+++ b/src/imports/multimedia/multimedia.cpp
@@ -81,7 +81,7 @@ static QObject *multimedia_global_object(QQmlEngine *qmlEngine, QJSEngine *jsEng
class QMultimediaDeclarativeModule : public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0")
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
QMultimediaDeclarativeModule(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); }
@@ -140,6 +140,9 @@ public:
qmlRegisterUncreatableType<QDeclarativeCameraImageProcessing, 2>(uri, 5, 7, "CameraImageProcessing",
trUtf8("CameraImageProcessing is provided by Camera"));
+ // 5.8 types (nothing new, re-register one of the types)
+ qmlRegisterType<QSoundEffect>(uri, 5, 8, "SoundEffect");
+
qmlRegisterType<QDeclarativeMediaMetaData>();
qmlRegisterType<QAbstractVideoFilter>();
}
diff --git a/src/imports/multimedia/plugins.qmltypes b/src/imports/multimedia/plugins.qmltypes
index 91fff02eb..20bbf7d3e 100644
--- a/src/imports/multimedia/plugins.qmltypes
+++ b/src/imports/multimedia/plugins.qmltypes
@@ -4,7 +4,7 @@ import QtQuick.tooling 1.2
// It is used for QML tooling purposes only.
//
// This file was auto-generated by:
-// 'qmlplugindump -nonrelocatable QtMultimedia 5.7'
+// 'qmlplugindump -nonrelocatable QtMultimedia 5.8'
Module {
dependencies: ["QtQuick 2.0"]
@@ -1248,8 +1248,24 @@ Module {
isCreatable: false
isSingleton: true
exportMetaObjectRevisions: [0]
+ Enum {
+ name: "VolumeScale"
+ values: {
+ "LinearVolumeScale": 0,
+ "CubicVolumeScale": 1,
+ "LogarithmicVolumeScale": 2,
+ "DecibelVolumeScale": 3
+ }
+ }
Property { name: "defaultCamera"; type: "QJSValue"; isReadonly: true }
Property { name: "availableCameras"; type: "QJSValue"; isReadonly: true }
+ Method {
+ name: "convertVolume"
+ type: "double"
+ Parameter { name: "volume"; type: "double" }
+ Parameter { name: "from"; type: "VolumeScale" }
+ Parameter { name: "to"; type: "VolumeScale" }
+ }
}
Component {
name: "QDeclarativePlaylist"
@@ -1794,9 +1810,10 @@ Module {
prototype: "QObject"
exports: [
"QtMultimedia/SoundEffect 5.0",
- "QtMultimedia/SoundEffect 5.3"
+ "QtMultimedia/SoundEffect 5.3",
+ "QtMultimedia/SoundEffect 5.8"
]
- exportMetaObjectRevisions: [0, 0]
+ exportMetaObjectRevisions: [0, 0, 0]
Enum {
name: "Loop"
values: {
diff --git a/src/imports/multimedia/qdeclarativeaudio.cpp b/src/imports/multimedia/qdeclarativeaudio.cpp
index 86f8f30ba..5a065072c 100644
--- a/src/imports/multimedia/qdeclarativeaudio.cpp
+++ b/src/imports/multimedia/qdeclarativeaudio.cpp
@@ -689,9 +689,17 @@ QDeclarativeAudio::PlaybackState QDeclarativeAudio::playbackState() const
/*!
\qmlproperty real QtMultimedia::Audio::volume
- This property holds the volume of the audio output, from 0.0 (silent) to 1.0 (maximum volume).
+ This property holds the audio volume.
- Defaults to 1.0.
+ The volume is scaled linearly from \c 0.0 (silence) to \c 1.0 (full volume). Values outside this
+ range will be clamped.
+
+ The default volume is \c 1.0.
+
+ UI volume controls should usually be scaled nonlinearly. For example, using a logarithmic scale
+ will produce linear changes in perceived loudness, which is what a user would normally expect
+ from a volume control. See \l {QtMultimedia::QtMultimedia::convertVolume()}{QtMultimedia.convertVolume()}
+ for more details.
*/
/*!
@@ -1310,9 +1318,17 @@ void QDeclarativeAudio::_q_mediaChanged(const QMediaContent &media)
/*!
\qmlproperty real QtMultimedia::MediaPlayer::volume
- This property holds the volume of the audio output, from 0.0 (silent) to 1.0 (maximum volume).
+ This property holds the audio volume of the media player.
- Defaults to 1.0.
+ The volume is scaled linearly from \c 0.0 (silence) to \c 1.0 (full volume). Values outside this
+ range will be clamped.
+
+ The default volume is \c 1.0.
+
+ UI volume controls should usually be scaled nonlinearly. For example, using a logarithmic scale
+ will produce linear changes in perceived loudness, which is what a user would normally expect
+ from a volume control. See \l {QtMultimedia::QtMultimedia::convertVolume()}{QtMultimedia.convertVolume()}
+ for more details.
*/
/*!
diff --git a/src/imports/multimedia/qdeclarativemultimediaglobal.cpp b/src/imports/multimedia/qdeclarativemultimediaglobal.cpp
index b2a1aed12..999f086d5 100644
--- a/src/imports/multimedia/qdeclarativemultimediaglobal.cpp
+++ b/src/imports/multimedia/qdeclarativemultimediaglobal.cpp
@@ -183,4 +183,57 @@ QJSValue QDeclarativeMultimediaGlobal::availableCameras() const
return availableCameras;
}
+/*!
+ \qmlmethod real QtMultimedia::QtMultimedia::convertVolume(real volume, VolumeScale from, VolumeScale to)
+
+ Converts an audio \a volume \a from a volume scale \a to another, and returns the result.
+
+ Depending on the context, different scales are used to represent audio volume. All Qt Multimedia
+ classes that have an audio volume use a linear scale, the reason is that the loudness of a
+ speaker is controlled by modulating its voltage on a linear scale. The human ear on the other
+ hand, perceives loudness in a logarithmic way. Using a logarithmic scale for volume controls
+ is therefore appropriate in most applications. The decibel scale is logarithmic by nature and
+ is commonly used to define sound levels, it is usually used for UI volume controls in
+ professional audio applications. The cubic scale is a computationally cheap approximation of a
+ logarithmic scale, it provides more control over lower volume levels.
+
+ Valid values for \a from and \a to are:
+ \list
+ \li QtMultimedia.LinearVolumeScale - Linear scale. \c 0.0 (0%) is silence and \c 1.0 (100%) is
+ full volume. All Qt Multimedia types that have an audio volume use a linear scale.
+ \li QtMultimedia.CubicVolumeScale - Cubic scale. \c 0.0 (0%) is silence and \c 1.0 (100%) is full
+ volume.
+ \li QtMultimedia.LogarithmicVolumeScale - Logarithmic scale. \c 0.0 (0%) is silence and \c 1.0
+ (100%) is full volume. UI volume controls should usually use a logarithmic scale.
+ \li QtMultimedia.DecibelVolumeScale - Decibel (dB, amplitude) logarithmic scale. \c -200 is
+ silence and \c 0 is full volume.
+ \endlist
+
+ The following example shows how the volume value from a UI volume control can be converted so
+ that the perceived increase in loudness is the same when increasing the volume control from 0.2
+ to 0.3 as it is from 0.5 to 0.6:
+
+ \code
+ Slider {
+ id: volumeSlider
+
+ property real volume: QtMultimedia.convertVolume(volumeSlider.value,
+ QtMultimedia.LogarithmicVolumeScale,
+ QtMultimedia.LinearVolumeScale)
+ }
+
+ MediaPlayer {
+ volume: volumeSlider.volume
+ }
+ \endcode
+
+ \since 5.8
+*/
+qreal QDeclarativeMultimediaGlobal::convertVolume(qreal volume,
+ QDeclarativeMultimediaGlobal::VolumeScale from,
+ QDeclarativeMultimediaGlobal::VolumeScale to) const
+{
+ return QAudio::convertVolume(volume, QAudio::VolumeScale(from), QAudio::VolumeScale(to));
+}
+
QT_END_NAMESPACE
diff --git a/src/imports/multimedia/qdeclarativemultimediaglobal_p.h b/src/imports/multimedia/qdeclarativemultimediaglobal_p.h
index 2374b560c..101bd899a 100644
--- a/src/imports/multimedia/qdeclarativemultimediaglobal_p.h
+++ b/src/imports/multimedia/qdeclarativemultimediaglobal_p.h
@@ -53,6 +53,7 @@
#include <QtQml/qqml.h>
#include <QtQml/qjsvalue.h>
+#include <QtMultimedia/qaudio.h>
QT_BEGIN_NAMESPACE
@@ -63,12 +64,23 @@ class QDeclarativeMultimediaGlobal : public QObject
Q_PROPERTY(QJSValue defaultCamera READ defaultCamera NOTIFY defaultCameraChanged)
Q_PROPERTY(QJSValue availableCameras READ availableCameras NOTIFY availableCamerasChanged)
+ Q_ENUMS(VolumeScale)
+
public:
+ enum VolumeScale {
+ LinearVolumeScale = QAudio::LinearVolumeScale,
+ CubicVolumeScale = QAudio::CubicVolumeScale,
+ LogarithmicVolumeScale = QAudio::LogarithmicVolumeScale,
+ DecibelVolumeScale = QAudio::DecibelVolumeScale
+ };
+
explicit QDeclarativeMultimediaGlobal(QJSEngine *engine, QObject *parent = 0);
QJSValue defaultCamera() const;
QJSValue availableCameras() const;
+ Q_INVOKABLE qreal convertVolume(qreal volume, VolumeScale from, VolumeScale to) const;
+
Q_SIGNALS:
// Unused at the moment. QCameraInfo doesn't notify when cameras are added or removed,
// but it might change in the future.
diff --git a/src/multimedia/audio/audio.pri b/src/multimedia/audio/audio.pri
index 96cfb1ce4..4706fd23e 100644
--- a/src/multimedia/audio/audio.pri
+++ b/src/multimedia/audio/audio.pri
@@ -19,7 +19,8 @@ PRIVATE_HEADERS += \
audio/qaudiodevicefactory_p.h \
audio/qwavedecoder_p.h \
audio/qsamplecache_p.h \
- audio/qaudiohelpers_p.h
+ audio/qaudiohelpers_p.h \
+ audio/qaudiosystempluginext_p.h
SOURCES += \
audio/qaudio.cpp \
diff --git a/src/multimedia/audio/qaudio.cpp b/src/multimedia/audio/qaudio.cpp
index c708fa4f8..d4f89e898 100644
--- a/src/multimedia/audio/qaudio.cpp
+++ b/src/multimedia/audio/qaudio.cpp
@@ -39,16 +39,20 @@
#include <qaudio.h>
+#include <qmath.h>
#include <QDebug>
QT_BEGIN_NAMESPACE
+#define LOG100 4.60517018599
+
static void qRegisterAudioMetaTypes()
{
qRegisterMetaType<QAudio::Error>();
qRegisterMetaType<QAudio::State>();
qRegisterMetaType<QAudio::Mode>();
qRegisterMetaType<QAudio::Role>();
+ qRegisterMetaType<QAudio::VolumeScale>();
}
Q_CONSTRUCTOR_FUNCTION(qRegisterAudioMetaTypes)
@@ -111,6 +115,134 @@ Q_CONSTRUCTOR_FUNCTION(qRegisterAudioMetaTypes)
\sa QMediaPlayer::setAudioRole()
*/
+/*!
+ \enum QAudio::VolumeScale
+
+ This enum defines the different audio volume scales.
+
+ \value LinearVolumeScale Linear scale. \c 0.0 (0%) is silence and \c 1.0 (100%) is full
+ volume. All Qt Multimedia classes that have an audio volume use
+ a linear scale.
+ \value CubicVolumeScale Cubic scale. \c 0.0 (0%) is silence and \c 1.0 (100%) is full
+ volume.
+ \value LogarithmicVolumeScale Logarithmic Scale. \c 0.0 (0%) is silence and \c 1.0 (100%) is
+ full volume. UI volume controls should usually use a logarithmic
+ scale.
+ \value DecibelVolumeScale Decibel (dB, amplitude) logarithmic scale. \c -200 is silence
+ and \c 0 is full volume.
+
+ \since 5.8
+ \sa QAudio::convertVolume()
+*/
+
+namespace QAudio
+{
+
+/*!
+ \fn qreal QAudio::convertVolume(qreal volume, VolumeScale from, VolumeScale to)
+
+ Converts an audio \a volume \a from a volume scale \a to another, and returns the result.
+
+ Depending on the context, different scales are used to represent audio volume. All Qt Multimedia
+ classes that have an audio volume use a linear scale, the reason is that the loudness of a
+ speaker is controlled by modulating its voltage on a linear scale. The human ear on the other
+ hand, perceives loudness in a logarithmic way. Using a logarithmic scale for volume controls
+ is therefore appropriate in most applications. The decibel scale is logarithmic by nature and
+ is commonly used to define sound levels, it is usually used for UI volume controls in
+ professional audio applications. The cubic scale is a computationally cheap approximation of a
+ logarithmic scale, it provides more control over lower volume levels.
+
+ The following example shows how to convert the volume value from a slider control before passing
+ it to a QMediaPlayer. As a result, the perceived increase in volume is the same when increasing
+ the volume slider from 20 to 30 as it is from 50 to 60:
+
+ \snippet multimedia-snippets/audio.cpp Volume conversion
+
+ \since 5.8
+ \sa VolumeScale, QMediaPlayer::setVolume(), QAudioOutput::setVolume(),
+ QAudioInput::setVolume(), QSoundEffect::setVolume(), QMediaRecorder::setVolume()
+*/
+qreal convertVolume(qreal volume, VolumeScale from, VolumeScale to)
+{
+ switch (from) {
+ case LinearVolumeScale:
+ volume = qMax(qreal(0), volume);
+ switch (to) {
+ case LinearVolumeScale:
+ return volume;
+ case CubicVolumeScale:
+ return qPow(volume, qreal(1 / 3.0));
+ case LogarithmicVolumeScale:
+ return 1 - std::exp(-volume * LOG100);
+ case DecibelVolumeScale:
+ if (volume < 0.001)
+ return qreal(-200);
+ else
+ return qreal(20.0) * std::log10(volume);
+ }
+ break;
+ case CubicVolumeScale:
+ volume = qMax(qreal(0), volume);
+ switch (to) {
+ case LinearVolumeScale:
+ return volume * volume * volume;
+ case CubicVolumeScale:
+ return volume;
+ case LogarithmicVolumeScale:
+ return 1 - std::exp(-volume * volume * volume * LOG100);
+ case DecibelVolumeScale:
+ if (volume < 0.001)
+ return qreal(-200);
+ else
+ return qreal(3.0 * 20.0) * std::log10(volume);
+ }
+ break;
+ case LogarithmicVolumeScale:
+ volume = qMax(qreal(0), volume);
+ switch (to) {
+ case LinearVolumeScale:
+ if (volume > 0.99)
+ return 1;
+ else
+ return -std::log(1 - volume) / LOG100;
+ case CubicVolumeScale:
+ if (volume > 0.99)
+ return 1;
+ else
+ return qPow(-std::log(1 - volume) / LOG100, qreal(1 / 3.0));
+ case LogarithmicVolumeScale:
+ return volume;
+ case DecibelVolumeScale:
+ if (volume < 0.001)
+ return qreal(-200);
+ else if (volume > 0.99)
+ return 0;
+ else
+ return qreal(20.0) * std::log10(-std::log(1 - volume) / LOG100);
+ }
+ break;
+ case DecibelVolumeScale:
+ switch (to) {
+ case LinearVolumeScale:
+ return qPow(qreal(10.0), volume / qreal(20.0));
+ case CubicVolumeScale:
+ return qPow(qreal(10.0), volume / qreal(3.0 * 20.0));
+ case LogarithmicVolumeScale:
+ if (qFuzzyIsNull(volume))
+ return 1;
+ else
+ return 1 - std::exp(-qPow(qreal(10.0), volume / qreal(20.0)) * LOG100);
+ case DecibelVolumeScale:
+ return volume;
+ }
+ break;
+ }
+
+ return volume;
+}
+
+}
+
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, QAudio::Error error)
{
@@ -210,6 +342,28 @@ QDebug operator<<(QDebug dbg, QAudio::Role role)
}
return dbg;
}
+
+QDebug operator<<(QDebug dbg, QAudio::VolumeScale scale)
+{
+ QDebugStateSaver saver(dbg);
+ dbg.nospace();
+ switch (scale) {
+ case QAudio::LinearVolumeScale:
+ dbg << "LinearVolumeScale";
+ break;
+ case QAudio::CubicVolumeScale:
+ dbg << "CubicVolumeScale";
+ break;
+ case QAudio::LogarithmicVolumeScale:
+ dbg << "LogarithmicVolumeScale";
+ break;
+ case QAudio::DecibelVolumeScale:
+ dbg << "DecibelVolumeScale";
+ break;
+ }
+ return dbg;
+}
+
#endif
diff --git a/src/multimedia/audio/qaudio.h b/src/multimedia/audio/qaudio.h
index 449ddefae..457a3b621 100644
--- a/src/multimedia/audio/qaudio.h
+++ b/src/multimedia/audio/qaudio.h
@@ -70,6 +70,15 @@ namespace QAudio
SonificationRole,
GameRole
};
+
+ enum VolumeScale {
+ LinearVolumeScale,
+ CubicVolumeScale,
+ LogarithmicVolumeScale,
+ DecibelVolumeScale
+ };
+
+ Q_MULTIMEDIA_EXPORT qreal convertVolume(qreal volume, VolumeScale from, VolumeScale to);
}
#ifndef QT_NO_DEBUG_STREAM
@@ -77,6 +86,7 @@ Q_MULTIMEDIA_EXPORT QDebug operator<<(QDebug dbg, QAudio::Error error);
Q_MULTIMEDIA_EXPORT QDebug operator<<(QDebug dbg, QAudio::State state);
Q_MULTIMEDIA_EXPORT QDebug operator<<(QDebug dbg, QAudio::Mode mode);
Q_MULTIMEDIA_EXPORT QDebug operator<<(QDebug dbg, QAudio::Role role);
+Q_MULTIMEDIA_EXPORT QDebug operator<<(QDebug dbg, QAudio::VolumeScale role);
#endif
QT_END_NAMESPACE
@@ -85,5 +95,6 @@ Q_DECLARE_METATYPE(QAudio::Error)
Q_DECLARE_METATYPE(QAudio::State)
Q_DECLARE_METATYPE(QAudio::Mode)
Q_DECLARE_METATYPE(QAudio::Role)
+Q_DECLARE_METATYPE(QAudio::VolumeScale)
#endif // QAUDIO_H
diff --git a/src/multimedia/audio/qaudiodevicefactory.cpp b/src/multimedia/audio/qaudiodevicefactory.cpp
index 83e1a6c0b..c3e4929b3 100644
--- a/src/multimedia/audio/qaudiodevicefactory.cpp
+++ b/src/multimedia/audio/qaudiodevicefactory.cpp
@@ -41,6 +41,7 @@
#include "qaudiosystem.h"
#include "qaudiosystemplugin.h"
+#include "qaudiosystempluginext_p.h"
#include "qmediapluginloader_p.h"
#include "qaudiodevicefactory_p.h"
@@ -139,41 +140,53 @@ QList<QAudioDeviceInfo> QAudioDeviceFactory::availableDevices(QAudio::Mode mode)
return devices;
}
-QAudioDeviceInfo QAudioDeviceFactory::defaultInputDevice()
+QAudioDeviceInfo QAudioDeviceFactory::defaultDevice(QAudio::Mode mode)
{
#if !defined (QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
- QAudioSystemFactoryInterface* plugin = qobject_cast<QAudioSystemFactoryInterface*>(audioLoader()->instance(defaultKey()));
- if (plugin) {
- QList<QByteArray> list = plugin->availableDevices(QAudio::AudioInput);
- if (list.size() > 0)
- return QAudioDeviceInfo(defaultKey(), list.at(0), QAudio::AudioInput);
- }
+ QMediaPluginLoader* l = audioLoader();
- // if no plugin is marked as default or if the default plugin doesn't have any input device,
- // return the first input available from other plugins.
- QList<QAudioDeviceInfo> inputDevices = availableDevices(QAudio::AudioInput);
- if (!inputDevices.isEmpty())
- return inputDevices.first();
-#endif
+ // Check if there is a default plugin.
+ QAudioSystemFactoryInterface *plugin = qobject_cast<QAudioSystemFactoryInterface *>(l->instance(defaultKey()));
+ if (plugin) {
+ // Check if the plugin has the extension interface.
+ QAudioSystemPluginExtension *pluginExt = qobject_cast<QAudioSystemPluginExtension *>(l->instance(defaultKey()));
+ // Ask for the default device.
+ if (pluginExt) {
+ const QByteArray &device = pluginExt->defaultDevice(mode);
+ if (!device.isEmpty())
+ return QAudioDeviceInfo(defaultKey(), device, mode);
+ }
- return QAudioDeviceInfo();
-}
+ // If there were no default devices, e.g., if the plugin did not implement the extent-ion interface,
+ // then just pick the first device that's available.
+ const auto &devices = plugin->availableDevices(mode);
+ if (!devices.isEmpty())
+ return QAudioDeviceInfo(defaultKey(), devices.first(), mode);
+ }
-QAudioDeviceInfo QAudioDeviceFactory::defaultOutputDevice()
-{
-#if !defined (QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
- QAudioSystemFactoryInterface* plugin = qobject_cast<QAudioSystemFactoryInterface*>(audioLoader()->instance(defaultKey()));
- if (plugin) {
- QList<QByteArray> list = plugin->availableDevices(QAudio::AudioOutput);
- if (list.size() > 0)
- return QAudioDeviceInfo(defaultKey(), list.at(0), QAudio::AudioOutput);
+ // If no plugin is marked as default, check the other plugins.
+ // Note: We're going to prioritize plugins that report a default device.
+ const auto &keys = l->keys();
+ QAudioDeviceInfo fallbackDevice;
+ for (const auto &key : keys) {
+ if (key == defaultKey())
+ continue;
+ QAudioSystemFactoryInterface* plugin = qobject_cast<QAudioSystemFactoryInterface*>(l->instance(key));
+ if (plugin) {
+ // Check if the plugin has the extent-ion interface.
+ QAudioSystemPluginExtension *pluginExt = qobject_cast<QAudioSystemPluginExtension *>(l->instance(key));
+ if (pluginExt) {
+ const QByteArray &device = pluginExt->defaultDevice(mode);
+ if (!device.isEmpty())
+ return QAudioDeviceInfo(key, device, mode);
+ } else if (fallbackDevice.isNull()) {
+ const auto &devices = plugin->availableDevices(mode);
+ if (!devices.isEmpty())
+ fallbackDevice = QAudioDeviceInfo(key, devices.first(), mode);
+ }
+ }
}
- // if no plugin is marked as default or if the default plugin doesn't have any output device,
- // return the first output available from other plugins.
- QList<QAudioDeviceInfo> outputDevices = availableDevices(QAudio::AudioOutput);
- if (!outputDevices.isEmpty())
- return outputDevices.first();
#endif
return QAudioDeviceInfo();
@@ -196,12 +209,12 @@ QAbstractAudioDeviceInfo* QAudioDeviceFactory::audioDeviceInfo(const QString &re
QAbstractAudioInput* QAudioDeviceFactory::createDefaultInputDevice(QAudioFormat const &format)
{
- return createInputDevice(defaultInputDevice(), format);
+ return createInputDevice(defaultDevice(QAudio::AudioInput), format);
}
QAbstractAudioOutput* QAudioDeviceFactory::createDefaultOutputDevice(QAudioFormat const &format)
{
- return createOutputDevice(defaultOutputDevice(), format);
+ return createOutputDevice(defaultDevice(QAudio::AudioOutput), format);
}
QAbstractAudioInput* QAudioDeviceFactory::createInputDevice(QAudioDeviceInfo const& deviceInfo, QAudioFormat const &format)
diff --git a/src/multimedia/audio/qaudiodevicefactory_p.h b/src/multimedia/audio/qaudiodevicefactory_p.h
index 833184075..7ad5e4e78 100644
--- a/src/multimedia/audio/qaudiodevicefactory_p.h
+++ b/src/multimedia/audio/qaudiodevicefactory_p.h
@@ -71,8 +71,7 @@ class QAudioDeviceFactory
public:
static QList<QAudioDeviceInfo> availableDevices(QAudio::Mode mode);
- static QAudioDeviceInfo defaultInputDevice();
- static QAudioDeviceInfo defaultOutputDevice();
+ static QAudioDeviceInfo defaultDevice(QAudio::Mode mode);
static QAbstractAudioDeviceInfo* audioDeviceInfo(const QString &realm, const QByteArray &handle, QAudio::Mode mode);
diff --git a/src/multimedia/audio/qaudiodeviceinfo.cpp b/src/multimedia/audio/qaudiodeviceinfo.cpp
index 945b415e8..f4f548017 100644
--- a/src/multimedia/audio/qaudiodeviceinfo.cpp
+++ b/src/multimedia/audio/qaudiodeviceinfo.cpp
@@ -419,7 +419,7 @@ QList<QAudioFormat::SampleType> QAudioDeviceInfo::supportedSampleTypes() const
*/
QAudioDeviceInfo QAudioDeviceInfo::defaultInputDevice()
{
- return QAudioDeviceFactory::defaultInputDevice();
+ return QAudioDeviceFactory::defaultDevice(QAudio::AudioInput);
}
/*!
@@ -428,7 +428,7 @@ QAudioDeviceInfo QAudioDeviceInfo::defaultInputDevice()
*/
QAudioDeviceInfo QAudioDeviceInfo::defaultOutputDevice()
{
- return QAudioDeviceFactory::defaultOutputDevice();
+ return QAudioDeviceFactory::defaultDevice(QAudio::AudioOutput);
}
/*!
diff --git a/src/multimedia/audio/qaudioinput.cpp b/src/multimedia/audio/qaudioinput.cpp
index bc6b6215b..ad54521fa 100644
--- a/src/multimedia/audio/qaudioinput.cpp
+++ b/src/multimedia/audio/qaudioinput.cpp
@@ -330,10 +330,15 @@ int QAudioInput::notifyInterval() const
/*!
Sets the input volume to \a volume.
+ The volume is scaled linearly from \c 0.0 (silence) to \c 1.0 (full volume). Values outside this
+ range will be clamped.
+
If the device does not support adjusting the input
volume then \a volume will be ignored and the input
volume will remain at 1.0.
+ The default volume is \c 1.0.
+
Note: Adjustments to the volume will change the volume of this audio stream, not the global volume.
*/
void QAudioInput::setVolume(qreal volume)
@@ -342,7 +347,7 @@ void QAudioInput::setVolume(qreal volume)
}
/*!
- Returns the input volume (gain).
+ Returns the input volume.
If the device does not support adjusting the input volume
the returned value will be 1.0.
diff --git a/src/multimedia/audio/qaudiooutput.cpp b/src/multimedia/audio/qaudiooutput.cpp
index 585855ace..670dca7bc 100644
--- a/src/multimedia/audio/qaudiooutput.cpp
+++ b/src/multimedia/audio/qaudiooutput.cpp
@@ -349,9 +349,18 @@ QAudio::State QAudioOutput::state() const
}
/*!
- Sets the volume.
- Where \a volume is between 0.0 and 1.0 inclusive.
+ Sets the output volume to \a volume.
+
+ The volume is scaled linearly from \c 0.0 (silence) to \c 1.0 (full volume). Values outside this
+ range will be clamped.
+
+ The default volume is \c 1.0.
+
Note: Adjustments to the volume will change the volume of this audio stream, not the global volume.
+
+ UI volume controls should usually be scaled nonlinearly. For example, using a logarithmic scale
+ will produce linear changes in perceived loudness, which is what a user would normally expect
+ from a volume control. See QAudio::convertVolume() for more details.
*/
void QAudioOutput::setVolume(qreal volume)
{
diff --git a/src/multimedia/audio/qaudiosystemplugin.cpp b/src/multimedia/audio/qaudiosystemplugin.cpp
index 904cb22e9..636b614d4 100644
--- a/src/multimedia/audio/qaudiosystemplugin.cpp
+++ b/src/multimedia/audio/qaudiosystemplugin.cpp
@@ -39,6 +39,7 @@
#include "qaudiosystemplugin.h"
+#include "qaudiosystempluginext_p.h"
QT_BEGIN_NAMESPACE
@@ -46,6 +47,10 @@ QAudioSystemFactoryInterface::~QAudioSystemFactoryInterface()
{
}
+QAudioSystemPluginExtension::~QAudioSystemPluginExtension()
+{
+}
+
/*!
\class QAudioSystemPlugin
\brief The QAudioSystemPlugin class provides an abstract base for audio plugins.
@@ -72,25 +77,15 @@ QAudioSystemFactoryInterface::~QAudioSystemFactoryInterface()
\sa QAbstractAudioDeviceInfo, QAbstractAudioOutput, QAbstractAudioInput
- Qt supports win32, linux(alsa) and \macos standard (builtin to the
- QtMultimedia library at compile time).
-
- You can support other backends other than these predefined ones by
- creating a plugin subclassing QAudioSystemPlugin, QAbstractAudioDeviceInfo,
- QAbstractAudioOutput and QAbstractAudioInput.
-
-
- -audio-backend configure option will force compiling in of the builtin backend
- into the QtMultimedia library at compile time. This is automatic by default
- and will only be compiled into the library if the dependencies are installed.
- eg. alsa-devel package installed for linux.
+ Qt comes with plugins for Windows (WinMM and WASAPI), Linux (ALSA and PulseAudio), \macos / iOS
+ (CoreAudio), Android (OpenSL ES) and QNX.
- If the builtin backend is not compiled into the QtMultimedia library and
- no audio plugins are available a fallback dummy backend will be used.
- This should print out warnings if this is the case when you try and use QAudioInput or QAudioOutput. To fix this problem
- reconfigure Qt using -audio-backend or create your own plugin with a default
- key to always override the dummy fallback. The easiest way to determine
- if you have only a dummy backend is to get a list of available audio devices.
+ If no audio plugins are available, a fallback dummy backend will be used.
+ This should print out warnings if this is the case when you try and use QAudioInput
+ or QAudioOutput. To fix this problem, make sure the dependencies for the Qt plugins are
+ installed on the system and reconfigure Qt (e.g. alsa-devel package on Linux), or create your
+ own plugin with a default key to always override the dummy fallback. The easiest way to
+ determine if you have only a dummy backend is to get a list of available audio devices.
QAudioDeviceInfo::availableDevices(QAudio::AudioOutput).size() = 0 (dummy backend)
*/
diff --git a/src/multimedia/audio/qaudiosystempluginext_p.h b/src/multimedia/audio/qaudiosystempluginext_p.h
new file mode 100644
index 000000000..380bc5afa
--- /dev/null
+++ b/src/multimedia/audio/qaudiosystempluginext_p.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QAUDIOSYSTEMPLUGINEXT_P_H
+#define QAUDIOSYSTEMPLUGINEXT_P_H
+
+#include <QtMultimedia/qtmultimediadefs.h>
+#include <QtMultimedia/qaudio.h>
+#include <QtCore/qplugin.h>
+
+QT_BEGIN_NAMESPACE
+
+//
+// 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.
+//
+
+struct Q_MULTIMEDIA_EXPORT QAudioSystemPluginExtension
+{
+ virtual QByteArray defaultDevice(QAudio::Mode) const = 0;
+ virtual ~QAudioSystemPluginExtension();
+};
+
+#define QAudioSystemPluginExtension_iid "org.qt-project.qt.audiosystempluginextension"
+Q_DECLARE_INTERFACE(QAudioSystemPluginExtension, QAudioSystemPluginExtension_iid)
+
+QT_END_NAMESPACE
+
+#endif // QAUDIOSYSTEMPLUGINEXT_P_H
diff --git a/src/multimedia/audio/qsoundeffect.cpp b/src/multimedia/audio/qsoundeffect.cpp
index f653de86e..d3b818073 100644
--- a/src/multimedia/audio/qsoundeffect.cpp
+++ b/src/multimedia/audio/qsoundeffect.cpp
@@ -258,12 +258,22 @@ int QSoundEffect::loopsRemaining() const
/*!
\qmlproperty qreal QtMultimedia::SoundEffect::volume
- This property holds the volume of the sound effect playback, from 0.0 (silent) to 1.0 (maximum volume).
+ This property holds the volume of the sound effect playback.
+
+ The volume is scaled linearly from \c 0.0 (silence) to \c 1.0 (full volume). Values outside this
+ range will be clamped.
+
+ The default volume is \c 1.0.
+
+ UI volume controls should usually be scaled nonlinearly. For example, using a logarithmic scale
+ will produce linear changes in perceived loudness, which is what a user would normally expect
+ from a volume control. See \l {QtMultimedia::QtMultimedia::convertVolume()}{QtMultimedia.convertVolume()}
+ for more details.
*/
/*!
\property QSoundEffect::volume
- This property holds the volume of the sound effect playback, from 0.0 (silent) to 1.0 (maximum volume).
+ This property holds the volume of the sound effect playback, from 0.0 (silence) to 1.0 (full volume).
*/
/*!
@@ -275,7 +285,16 @@ qreal QSoundEffect::volume() const
}
/*!
- Sets the volume to play the sound effect at to \a volume, from 0.0 (silent) to 1.0 (maximum volume).
+ Sets the sound effect volume to \a volume.
+
+ The volume is scaled linearly from \c 0.0 (silence) to \c 1.0 (full volume). Values outside this
+ range will be clamped.
+
+ The default volume is \c 1.0.
+
+ UI volume controls should usually be scaled nonlinearly. For example, using a logarithmic scale
+ will produce linear changes in perceived loudness, which is what a user would normally expect
+ from a volume control. See QAudio::convertVolume() for more details.
*/
void QSoundEffect::setVolume(qreal volume)
{
diff --git a/src/multimedia/controls/qmediaplayercontrol.cpp b/src/multimedia/controls/qmediaplayercontrol.cpp
index cd56dffcb..46de05b51 100644
--- a/src/multimedia/controls/qmediaplayercontrol.cpp
+++ b/src/multimedia/controls/qmediaplayercontrol.cpp
@@ -175,6 +175,8 @@ QMediaPlayerControl::QMediaPlayerControl(QObject *parent):
\fn QMediaPlayerControl::setVolume(int volume)
Sets the audio \a volume of a player control.
+
+ The volume is scaled linearly, ranging from \c 0 (silence) to \c 100 (full volume).
*/
/*!
diff --git a/src/multimedia/controls/qmediarecordercontrol.cpp b/src/multimedia/controls/qmediarecordercontrol.cpp
index 4654d16eb..611f1fdcc 100644
--- a/src/multimedia/controls/qmediarecordercontrol.cpp
+++ b/src/multimedia/controls/qmediarecordercontrol.cpp
@@ -160,13 +160,15 @@ QMediaRecorderControl::~QMediaRecorderControl()
/*!
\fn qreal QMediaRecorderControl::volume() const
- Returns the linear audio gain of media recorder.
+ Returns the audio volume of a media recorder control.
*/
/*!
\fn void QMediaRecorderControl::setVolume(qreal gain)
- Sets the linear audio \a gain of a media recorder.
+ Sets the audio \a volume of a media recorder control.
+
+ The volume is scaled linearly, ranging from \c 0 (silence) to \c 100 (full volume).
*/
/*!
diff --git a/src/multimedia/doc/snippets/multimedia-snippets/audio.cpp b/src/multimedia/doc/snippets/multimedia-snippets/audio.cpp
index 310206405..9646b708e 100644
--- a/src/multimedia/doc/snippets/multimedia-snippets/audio.cpp
+++ b/src/multimedia/doc/snippets/multimedia-snippets/audio.cpp
@@ -47,6 +47,7 @@
#include "qaudiooutput.h"
#include "qaudioprobe.h"
#include "qaudiodecoder.h"
+#include "qmediaplayer.h"
class AudioInputExample : public QObject {
Q_OBJECT
@@ -247,3 +248,18 @@ void AudioDecodingExample::decode()
// Now wait for bufferReady() signal and call decoder->read()
//! [Local audio decoding]
}
+
+QMediaPlayer player;
+
+//! [Volume conversion]
+void applyVolume(int volumeSliderValue)
+{
+ // volumeSliderValue is in the range [0..100]
+
+ qreal linearVolume = QAudio::convertVolume(volumeSliderValue / qreal(100.0),
+ QAudio::LogarithmicVolumeScale,
+ QAudio::LinearVolumeScale);
+
+ player.setVolume(qRound(linearVolume * 100));
+}
+//! [Volume conversion]
diff --git a/src/multimedia/playback/qmediaplayer.cpp b/src/multimedia/playback/qmediaplayer.cpp
index edccd30ef..648c13220 100644
--- a/src/multimedia/playback/qmediaplayer.cpp
+++ b/src/multimedia/playback/qmediaplayer.cpp
@@ -142,7 +142,7 @@ public:
QMediaContent rootMedia;
QMediaContent pendingPlaylist;
QMediaPlaylist *parentPlaylist(QMediaPlaylist *pls);
- bool isInChain(QUrl url);
+ bool isInChain(const QUrl &url);
int nestedPlaylists;
void setMedia(const QMediaContent &media, QIODevice *stream = 0);
@@ -175,7 +175,7 @@ QMediaPlaylist *QMediaPlayerPrivate::parentPlaylist(QMediaPlaylist *pls)
return 0;
}
-bool QMediaPlayerPrivate::isInChain(QUrl url)
+bool QMediaPlayerPrivate::isInChain(const QUrl &url)
{
// Check whether a URL is already in the chain of playlists.
// Also see a comment in parentPlaylist().
@@ -1372,8 +1372,14 @@ QList<QAudio::Role> QMediaPlayer::supportedAudioRoles() const
\property QMediaPlayer::volume
\brief the current playback volume.
- The playback volume is linear in effect and the value can range from 0 -
- 100, values outside this range will be clamped.
+ The playback volume is scaled linearly, ranging from \c 0 (silence) to \c 100 (full volume).
+ Values outside this range will be clamped.
+
+ By default the volume is \c 100.
+
+ UI volume controls should usually be scaled nonlinearly. For example, using a logarithmic scale
+ will produce linear changes in perceived loudness, which is what a user would normally expect
+ from a volume control. See QAudio::convertVolume() for more details.
*/
/*!
diff --git a/src/multimedia/qmediaopenglhelper_p.h b/src/multimedia/qmediaopenglhelper_p.h
index 602116976..0a65b9f53 100644
--- a/src/multimedia/qmediaopenglhelper_p.h
+++ b/src/multimedia/qmediaopenglhelper_p.h
@@ -72,7 +72,7 @@ inline bool QMediaOpenGLHelper::isANGLE()
#else
bool isANGLE = false;
-# if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && (defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC))
+# if defined(Q_OS_WIN) && (defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC))
if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES) {
// Although unlikely, technically LibGLES could mean a non-ANGLE EGL/GLES2 implementation too.
// Verify that it is indeed ANGLE.
@@ -104,7 +104,7 @@ inline bool QMediaOpenGLHelper::isANGLE()
# endif // QT_OPENGL_ES_2_ANGLE_STATIC
}
-# endif // Q_OS_WIN && !Q_OS_WINCE && (QT_OPENGL_ES_2 || QT_OPENGL_DYNAMIC)
+# endif // Q_OS_WIN && (QT_OPENGL_ES_2 || QT_OPENGL_DYNAMIC)
return isANGLE;
#endif // Q_OS_WINRT
diff --git a/src/multimedia/qmediastoragelocation.cpp b/src/multimedia/qmediastoragelocation.cpp
index 04aa79758..7bd1e84f4 100644
--- a/src/multimedia/qmediastoragelocation.cpp
+++ b/src/multimedia/qmediastoragelocation.cpp
@@ -131,7 +131,7 @@ QString QMediaStorageLocation::generateFileName(const QString &prefix,
.arg(extension);
const QString path = dir.absoluteFilePath(name);
- if (!QFileInfo(path).exists()) {
+ if (!QFileInfo::exists(path)) {
m_lastUsedIndex[lastMediaKey] = lastMediaIndex + 1;
return path;
}
diff --git a/src/multimedia/qmediatimerange.cpp b/src/multimedia/qmediatimerange.cpp
index 7739c704f..700dcd087 100644
--- a/src/multimedia/qmediatimerange.cpp
+++ b/src/multimedia/qmediatimerange.cpp
@@ -665,16 +665,7 @@ bool QMediaTimeRange::contains(qint64 time) const
*/
bool operator==(const QMediaTimeRange &a, const QMediaTimeRange &b)
{
- if (a.intervals().count() != b.intervals().count())
- return false;
-
- for (int i = 0; i < a.intervals().count(); i++)
- {
- if(a.intervals()[i] != b.intervals()[i])
- return false;
- }
-
- return true;
+ return a.intervals() == b.intervals();
}
/*!
diff --git a/src/multimedia/recording/qmediarecorder.cpp b/src/multimedia/recording/qmediarecorder.cpp
index a5f4c15ce..7b0234988 100644
--- a/src/multimedia/recording/qmediarecorder.cpp
+++ b/src/multimedia/recording/qmediarecorder.cpp
@@ -556,7 +556,16 @@ void QMediaRecorder::setMuted(bool muted)
/*!
\property QMediaRecorder::volume
- \brief the linear audio gain of media recorder.
+ \brief the current recording audio volume.
+
+ The volume is scaled linearly from \c 0.0 (silence) to \c 1.0 (full volume). Values outside this
+ range will be clamped.
+
+ The default volume is \c 1.0.
+
+ UI volume controls should usually be scaled nonlinearly. For example, using a logarithmic scale
+ will produce linear changes in perceived loudness, which is what a user would normally expect
+ from a volume control. See QAudio::convertVolume() for more details.
*/
qreal QMediaRecorder::volume() const
diff --git a/src/multimediawidgets/multimediawidgets.pro b/src/multimediawidgets/multimediawidgets.pro
index 60321fba8..29ec710f5 100644
--- a/src/multimediawidgets/multimediawidgets.pro
+++ b/src/multimediawidgets/multimediawidgets.pro
@@ -1,11 +1,8 @@
# distinct from Qt Multimedia
TARGET = QtMultimediaWidgets
QT = core gui multimedia-private widgets-private
-qtHaveModule(opengl):!contains(QT_CONFIG, opengles1) {
+qtHaveModule(opengl): \
QT_PRIVATE += opengl
-} else {
- DEFINES += QT_NO_OPENGL
-}
PRIVATE_HEADERS += \
qvideowidget_p.h \
@@ -25,7 +22,7 @@ SOURCES += \
qvideowidget.cpp
maemo6 {
- contains(QT_CONFIG, opengles2) {
+ qtConfig(opengles2) {
PRIVATE_HEADERS += qeglimagetexturesurface_p.h
SOURCES += qeglimagetexturesurface.cpp
diff --git a/src/plugins/alsa/qalsaaudiodeviceinfo.cpp b/src/plugins/alsa/qalsaaudiodeviceinfo.cpp
index 869e1897e..5e8edc3fc 100644
--- a/src/plugins/alsa/qalsaaudiodeviceinfo.cpp
+++ b/src/plugins/alsa/qalsaaudiodeviceinfo.cpp
@@ -140,6 +140,15 @@ QList<QAudioFormat::SampleType> QAlsaAudioDeviceInfo::supportedSampleTypes()
return typez;
}
+QByteArray QAlsaAudioDeviceInfo::defaultDevice(QAudio::Mode mode)
+{
+ const auto &devices = availableDevices(mode);
+ if (devices.size() == 0)
+ return QByteArray();
+
+ return devices.first();
+}
+
bool QAlsaAudioDeviceInfo::open()
{
int err = 0;
@@ -362,24 +371,6 @@ QList<QByteArray> QAlsaAudioDeviceInfo::availableDevices(QAudio::Mode mode)
return devices;
}
-QByteArray QAlsaAudioDeviceInfo::defaultInputDevice()
-{
- QList<QByteArray> devices = availableDevices(QAudio::AudioInput);
- if(devices.size() == 0)
- return QByteArray();
-
- return devices.first();
-}
-
-QByteArray QAlsaAudioDeviceInfo::defaultOutputDevice()
-{
- QList<QByteArray> devices = availableDevices(QAudio::AudioOutput);
- if(devices.size() == 0)
- return QByteArray();
-
- return devices.first();
-}
-
void QAlsaAudioDeviceInfo::checkSurround()
{
surround40 = false;
diff --git a/src/plugins/alsa/qalsaaudiodeviceinfo.h b/src/plugins/alsa/qalsaaudiodeviceinfo.h
index 97b59ebf3..21e30f49b 100644
--- a/src/plugins/alsa/qalsaaudiodeviceinfo.h
+++ b/src/plugins/alsa/qalsaaudiodeviceinfo.h
@@ -88,8 +88,7 @@ public:
QList<int> supportedSampleSizes();
QList<QAudioFormat::Endian> supportedByteOrders();
QList<QAudioFormat::SampleType> supportedSampleTypes();
- static QByteArray defaultInputDevice();
- static QByteArray defaultOutputDevice();
+ static QByteArray defaultDevice(QAudio::Mode mode);
static QList<QByteArray> availableDevices(QAudio::Mode);
static QString deviceFromCardName(const QString &card);
diff --git a/src/plugins/alsa/qalsaplugin.cpp b/src/plugins/alsa/qalsaplugin.cpp
index 79adbae59..e52e9ee83 100644
--- a/src/plugins/alsa/qalsaplugin.cpp
+++ b/src/plugins/alsa/qalsaplugin.cpp
@@ -49,6 +49,11 @@ QAlsaPlugin::QAlsaPlugin(QObject *parent)
{
}
+QByteArray QAlsaPlugin::defaultDevice(QAudio::Mode mode) const
+{
+ return QAlsaAudioDeviceInfo::defaultDevice(mode);
+}
+
QList<QByteArray> QAlsaPlugin::availableDevices(QAudio::Mode mode) const
{
return QAlsaAudioDeviceInfo::availableDevices(mode);
diff --git a/src/plugins/alsa/qalsaplugin.h b/src/plugins/alsa/qalsaplugin.h
index 74e3475b7..b3c530f88 100644
--- a/src/plugins/alsa/qalsaplugin.h
+++ b/src/plugins/alsa/qalsaplugin.h
@@ -41,19 +41,22 @@
#define QALSAPLUGIN_H
#include <QtMultimedia/qaudiosystemplugin.h>
+#include <QtMultimedia/private/qaudiosystempluginext_p.h>
QT_BEGIN_NAMESPACE
-class QAlsaPlugin : public QAudioSystemPlugin
+class QAlsaPlugin : public QAudioSystemPlugin, public QAudioSystemPluginExtension
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.qt.audiosystemfactory/5.0" FILE "alsa.json")
+ Q_INTERFACES(QAudioSystemPluginExtension)
public:
QAlsaPlugin(QObject *parent = 0);
~QAlsaPlugin() {}
+ QByteArray defaultDevice(QAudio::Mode mode) const Q_DECL_OVERRIDE;
QList<QByteArray> availableDevices(QAudio::Mode mode) const Q_DECL_OVERRIDE;
QAbstractAudioInput *createInput(const QByteArray &device) Q_DECL_OVERRIDE;
QAbstractAudioOutput *createOutput(const QByteArray &device) Q_DECL_OVERRIDE;
diff --git a/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtAndroidMediaPlayer.java b/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtAndroidMediaPlayer.java
index d0983d38a..6818b2909 100644
--- a/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtAndroidMediaPlayer.java
+++ b/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtAndroidMediaPlayer.java
@@ -449,17 +449,6 @@ public class QtAndroidMediaPlayer
return duration;
}
- private float adjustVolume(final int volume)
- {
- if (volume < 1)
- return 0.0f;
-
- if (volume > 98)
- return 1.0f;
-
- return (float) (1-(Math.log(100-volume)/Math.log(100)));
- }
-
public void setVolume(int volume)
{
if (volume < 0)
@@ -487,7 +476,7 @@ public class QtAndroidMediaPlayer
}
try {
- float newVolume = adjustVolume(volume);
+ float newVolume = (float)volume / 100;
mMediaPlayer.setVolume(newVolume, newVolume);
} catch (final IllegalStateException e) {
Log.d(TAG, "" + e.getMessage());
diff --git a/src/plugins/avfoundation/camera/avfcameraviewfindersettingscontrol.mm b/src/plugins/avfoundation/camera/avfcameraviewfindersettingscontrol.mm
index 6ac6325b4..23dd2a4aa 100644
--- a/src/plugins/avfoundation/camera/avfcameraviewfindersettingscontrol.mm
+++ b/src/plugins/avfoundation/camera/avfcameraviewfindersettingscontrol.mm
@@ -231,6 +231,10 @@ QVideoFrame::PixelFormat AVFCameraViewfinderSettingsControl2::QtPixelFormatFromC
case kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange:
case kCVPixelFormatType_420YpCbCr8BiPlanarFullRange:
return QVideoFrame::Format_NV12;
+ case kCVPixelFormatType_422YpCbCr8:
+ return QVideoFrame::Format_UYVY;
+ case kCVPixelFormatType_422YpCbCr8_yuvs:
+ return QVideoFrame::Format_YUYV;
default:
return QVideoFrame::Format_Invalid;
}
@@ -251,6 +255,12 @@ bool AVFCameraViewfinderSettingsControl2::CVPixelFormatFromQtFormat(QVideoFrame:
case QVideoFrame::Format_NV12:
conv = kCVPixelFormatType_420YpCbCr8BiPlanarFullRange;
break;
+ case QVideoFrame::Format_UYVY:
+ conv = kCVPixelFormatType_422YpCbCr8;
+ break;
+ case QVideoFrame::Format_YUYV:
+ conv = kCVPixelFormatType_422YpCbCr8_yuvs;
+ break;
// These two formats below are not supported
// by QSGVideoNodeFactory_RGB, so for now I have to
// disable them.
diff --git a/src/plugins/avfoundation/mediaplayer/mediaplayer.pro b/src/plugins/avfoundation/mediaplayer/mediaplayer.pro
index 779d5ff2d..29e231066 100644
--- a/src/plugins/avfoundation/mediaplayer/mediaplayer.pro
+++ b/src/plugins/avfoundation/mediaplayer/mediaplayer.pro
@@ -40,7 +40,7 @@ OBJECTIVE_SOURCES += \
}
ios|tvos {
- contains(QT_CONFIG, opengl.*) {
+ qtConfig(opengl) {
HEADERS += \
avfvideoframerenderer_ios.h \
avfvideorenderercontrol.h \
@@ -55,7 +55,7 @@ ios|tvos {
} else {
LIBS += -framework AppKit
- contains(QT_CONFIG, opengl.*) {
+ qtConfig(opengl) {
HEADERS += \
avfvideoframerenderer.h \
avfvideorenderercontrol.h \
diff --git a/src/plugins/coreaudio/coreaudiodeviceinfo.h b/src/plugins/coreaudio/coreaudiodeviceinfo.h
index fc8999850..08c3961e6 100644
--- a/src/plugins/coreaudio/coreaudiodeviceinfo.h
+++ b/src/plugins/coreaudio/coreaudiodeviceinfo.h
@@ -65,9 +65,7 @@ public:
QList<QAudioFormat::Endian> supportedByteOrders();
QList<QAudioFormat::SampleType> supportedSampleTypes();
- static QByteArray defaultInputDevice();
- static QByteArray defaultOutputDevice();
-
+ static QByteArray defaultDevice(QAudio::Mode mode);
static QList<QByteArray> availableDevices(QAudio::Mode mode);
private:
diff --git a/src/plugins/coreaudio/coreaudiodeviceinfo.mm b/src/plugins/coreaudio/coreaudiodeviceinfo.mm
index 66e8ed4d7..1a79438cb 100644
--- a/src/plugins/coreaudio/coreaudiodeviceinfo.mm
+++ b/src/plugins/coreaudio/coreaudiodeviceinfo.mm
@@ -280,47 +280,29 @@ static QByteArray get_device_info(AudioDeviceID audioDevice, QAudio::Mode mode)
}
#endif
-QByteArray CoreAudioDeviceInfo::defaultInputDevice()
+QByteArray CoreAudioDeviceInfo::defaultDevice(QAudio::Mode mode)
{
#if defined(Q_OS_OSX)
AudioDeviceID audioDevice;
UInt32 size = sizeof(audioDevice);
- AudioObjectPropertyAddress defaultInputDevicePropertyAddress = { kAudioHardwarePropertyDefaultInputDevice,
- kAudioObjectPropertyScopeGlobal,
- kAudioObjectPropertyElementMaster };
-
- if (AudioObjectGetPropertyData(kAudioObjectSystemObject,
- &defaultInputDevicePropertyAddress,
- 0, NULL, &size, &audioDevice) != noErr) {
- qWarning() << "QAudioDeviceInfo: Unable to find default input device";
- return QByteArray();
- }
-
- return get_device_info(audioDevice, QAudio::AudioInput);
-#else //iOS
- return CoreAudioSessionManager::instance().inputDevices().first();
-#endif
-}
-
-QByteArray CoreAudioDeviceInfo::defaultOutputDevice()
-{
-#if defined(Q_OS_OSX)
- AudioDeviceID audioDevice;
- UInt32 size = sizeof(audioDevice);
- AudioObjectPropertyAddress defaultOutputDevicePropertyAddress = { kAudioHardwarePropertyDefaultOutputDevice,
- kAudioObjectPropertyScopeGlobal,
- kAudioObjectPropertyElementMaster };
+ const AudioObjectPropertySelector selector = (mode == QAudio::AudioOutput) ? kAudioHardwarePropertyDefaultOutputDevice
+ : kAudioHardwarePropertyDefaultInputDevice;
+ AudioObjectPropertyAddress defaultDevicePropertyAddress = { selector,
+ kAudioObjectPropertyScopeGlobal,
+ kAudioObjectPropertyElementMaster };
if (AudioObjectGetPropertyData(kAudioObjectSystemObject,
- &defaultOutputDevicePropertyAddress,
+ &defaultDevicePropertyAddress,
0, NULL, &size, &audioDevice) != noErr) {
- qWarning() << "QAudioDeviceInfo: Unable to find default output device";
+ qWarning("QAudioDeviceInfo: Unable to find default %s device", (mode == QAudio::AudioOutput) ? "output" : "input");
return QByteArray();
}
- return get_device_info(audioDevice, QAudio::AudioOutput);
+ return get_device_info(audioDevice, mode);
#else //iOS
- return CoreAudioSessionManager::instance().outputDevices().first();
+ const auto &devices = (mode == QAudio::AudioOutput) ? CoreAudioSessionManager::instance().outputDevices()
+ : CoreAudioSessionManager::instance().inputDevices();
+ return !devices.isEmpty() ? devices.first() : QByteArray();
#endif
}
@@ -343,15 +325,10 @@ QList<QByteArray> CoreAudioDeviceInfo::availableDevices(QAudio::Mode mode)
AudioDeviceID* audioDevices = new AudioDeviceID[dc];
if (AudioObjectGetPropertyData(kAudioObjectSystemObject, &audioDevicesPropertyAddress, 0, NULL, &propSize, audioDevices) == noErr) {
- QByteArray defaultDevice = (mode == QAudio::AudioOutput) ? defaultOutputDevice() : defaultInputDevice();
for (int i = 0; i < dc; ++i) {
- QByteArray info = get_device_info(audioDevices[i], mode);
- if (!info.isNull()) {
- if (info == defaultDevice)
- devices.prepend(info);
- else
- devices << info;
- }
+ const QByteArray &info = get_device_info(audioDevices[i], mode);
+ if (!info.isNull())
+ devices << info;
}
}
diff --git a/src/plugins/coreaudio/coreaudioplugin.h b/src/plugins/coreaudio/coreaudioplugin.h
index 5868508d2..da18d8cfe 100644
--- a/src/plugins/coreaudio/coreaudioplugin.h
+++ b/src/plugins/coreaudio/coreaudioplugin.h
@@ -39,19 +39,22 @@
#ifndef IOSAUDIOPLUGIN_H
#define IOSAUDIOPLUGIN_H
-#include <qaudiosystemplugin.h>
+#include <QtMultimedia/qaudiosystemplugin.h>
+#include <QtMultimedia/private/qaudiosystempluginext_p.h>
QT_BEGIN_NAMESPACE
-class CoreAudioPlugin : public QAudioSystemPlugin
+class CoreAudioPlugin : public QAudioSystemPlugin, public QAudioSystemPluginExtension
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.qt.audiosystemfactory/5.0" FILE "coreaudio.json")
+ Q_INTERFACES(QAudioSystemPluginExtension)
public:
explicit CoreAudioPlugin(QObject *parent = 0);
~CoreAudioPlugin() {}
+ QByteArray defaultDevice(QAudio::Mode mode) const Q_DECL_OVERRIDE;
QList<QByteArray> availableDevices(QAudio::Mode mode) const Q_DECL_OVERRIDE;
QAbstractAudioInput *createInput(const QByteArray &device) Q_DECL_OVERRIDE;
QAbstractAudioOutput *createOutput(const QByteArray &device) Q_DECL_OVERRIDE;
diff --git a/src/plugins/coreaudio/coreaudioplugin.mm b/src/plugins/coreaudio/coreaudioplugin.mm
index 6d899fb67..ac51b9cd0 100644
--- a/src/plugins/coreaudio/coreaudioplugin.mm
+++ b/src/plugins/coreaudio/coreaudioplugin.mm
@@ -49,6 +49,10 @@ CoreAudioPlugin::CoreAudioPlugin(QObject *parent)
{
}
+QByteArray CoreAudioPlugin::defaultDevice(QAudio::Mode mode) const
+{
+ return CoreAudioDeviceInfo::defaultDevice(mode);
+}
QList<QByteArray> CoreAudioPlugin::availableDevices(QAudio::Mode mode) const
{
diff --git a/src/plugins/directshow/camera/camera.pri b/src/plugins/directshow/camera/camera.pri
index c6b16da59..6c67a8fe2 100644
--- a/src/plugins/directshow/camera/camera.pri
+++ b/src/plugins/directshow/camera/camera.pri
@@ -13,7 +13,7 @@ HEADERS += \
$$PWD/dsvideodevicecontrol.h \
$$PWD/dsimagecapturecontrol.h \
$$PWD/dscamerasession.h \
- $$PWD/directshowglobal.h \
+ $$PWD/directshowcameraglobal.h \
$$PWD/dscameraviewfindersettingscontrol.h \
$$PWD/dscameraimageprocessingcontrol.h
diff --git a/src/plugins/directshow/camera/directshowglobal.h b/src/plugins/directshow/camera/directshowcameraglobal.h
index 46d161336..75112a090 100644
--- a/src/plugins/directshow/camera/directshowglobal.h
+++ b/src/plugins/directshow/camera/directshowcameraglobal.h
@@ -37,8 +37,8 @@
**
****************************************************************************/
-#ifndef DIRECTSHOWGLOBAL_H
-#define DIRECTSHOWGLOBAL_H
+#ifndef DIRECTSHOWCAMERAGLOBAL_H
+#define DIRECTSHOWCAMERAGLOBAL_H
#include <QtCore/qglobal.h>
diff --git a/src/plugins/directshow/camera/dscamerasession.cpp b/src/plugins/directshow/camera/dscamerasession.cpp
index bfd18a556..5587b479c 100644
--- a/src/plugins/directshow/camera/dscamerasession.cpp
+++ b/src/plugins/directshow/camera/dscamerasession.cpp
@@ -47,7 +47,7 @@
#include "dscamerasession.h"
#include "dsvideorenderer.h"
-#include "directshowglobal.h"
+#include "directshowcameraglobal.h"
QT_BEGIN_NAMESPACE
diff --git a/src/plugins/directshow/directshow.pro b/src/plugins/directshow/directshow.pro
index 117b02ade..10c6fe2b6 100644
--- a/src/plugins/directshow/directshow.pro
+++ b/src/plugins/directshow/directshow.pro
@@ -1,5 +1,5 @@
TARGET = dsengine
-win32:!qtHaveModule(opengl)|contains(QT_CONFIG,dynamicgl) {
+win32:!qtHaveModule(opengl)|qtConfig(dynamicgl) {
LIBS_PRIVATE += -lgdi32 -luser32
}
@@ -12,8 +12,9 @@ SOURCES += dsserviceplugin.cpp
mingw: DEFINES += NO_DSHOW_STRSAFE
+include(helpers/helpers.pri)
!config_wmf: include(player/player.pri)
-!wince: include(camera/camera.pri)
+include(camera/camera.pri)
OTHER_FILES += \
directshow.json \
diff --git a/src/plugins/directshow/helpers/directshowbasefilter.cpp b/src/plugins/directshow/helpers/directshowbasefilter.cpp
new file mode 100644
index 000000000..fbf0f6204
--- /dev/null
+++ b/src/plugins/directshow/helpers/directshowbasefilter.cpp
@@ -0,0 +1,267 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "directshowbasefilter.h"
+
+#include "directshowpinenum.h"
+
+DirectShowBaseFilter::DirectShowBaseFilter()
+ : m_mutex(QMutex::Recursive)
+ , m_state(State_Stopped)
+ , m_graph(NULL)
+ , m_clock(NULL)
+ , m_sink(NULL)
+{
+
+}
+
+DirectShowBaseFilter::~DirectShowBaseFilter()
+{
+ if (m_clock) {
+ m_clock->Release();
+ m_clock = NULL;
+ }
+}
+
+HRESULT DirectShowBaseFilter::getInterface(REFIID riid, void **ppvObject)
+{
+ if (riid == IID_IPersist
+ || riid == IID_IMediaFilter
+ || riid == IID_IBaseFilter) {
+ return GetInterface(static_cast<IBaseFilter *>(this), ppvObject);
+ } else {
+ return DirectShowObject::getInterface(riid, ppvObject);
+ }
+}
+
+HRESULT DirectShowBaseFilter::GetClassID(CLSID *pClassID)
+{
+ *pClassID = CLSID_NULL;
+ return S_OK;
+}
+
+HRESULT DirectShowBaseFilter::NotifyEvent(long eventCode, LONG_PTR eventParam1, LONG_PTR eventParam2)
+{
+ IMediaEventSink *sink = m_sink;
+ if (sink) {
+ if (eventCode == EC_COMPLETE)
+ eventParam2 = (LONG_PTR)(IBaseFilter*)this;
+
+ return sink->Notify(eventCode, eventParam1, eventParam2);
+ } else {
+ return E_NOTIMPL;
+ }
+}
+
+HRESULT DirectShowBaseFilter::Run(REFERENCE_TIME tStart)
+{
+ Q_UNUSED(tStart)
+ QMutexLocker locker(&m_mutex);
+
+ m_startTime = tStart;
+
+ if (m_state == State_Stopped){
+ HRESULT hr = Pause();
+ if (FAILED(hr))
+ return hr;
+ }
+
+ m_state = State_Running;
+
+ return S_OK;
+}
+
+HRESULT DirectShowBaseFilter::Pause()
+{
+ QMutexLocker locker(&m_mutex);
+
+ if (m_state == State_Stopped) {
+ const QList<DirectShowPin *> pinList = pins();
+ for (DirectShowPin *pin : pinList) {
+ if (pin->isConnected()) {
+ HRESULT hr = pin->setActive(true);
+ if (FAILED(hr))
+ return hr;
+ }
+ }
+ }
+
+ m_state = State_Paused;
+
+ return S_OK;
+}
+
+HRESULT DirectShowBaseFilter::Stop()
+{
+ QMutexLocker locker(&m_mutex);
+
+ HRESULT hr = S_OK;
+
+ if (m_state != State_Stopped) {
+ const QList<DirectShowPin *> pinList = pins();
+ for (DirectShowPin *pin : pinList) {
+ if (pin->isConnected()) {
+ HRESULT hrTmp = pin->setActive(false);
+ if (FAILED(hrTmp) && SUCCEEDED(hr))
+ hr = hrTmp;
+ }
+ }
+ }
+
+ m_state = State_Stopped;
+
+ return hr;
+}
+
+HRESULT DirectShowBaseFilter::GetState(DWORD dwMilliSecsTimeout, FILTER_STATE *pState)
+{
+ Q_UNUSED(dwMilliSecsTimeout);
+
+ if (!pState) {
+ return E_POINTER;
+ } else {
+ QMutexLocker locker(&m_mutex);
+
+ *pState = m_state;
+
+ return S_OK;
+ }
+}
+
+HRESULT DirectShowBaseFilter::SetSyncSource(IReferenceClock *pClock)
+{
+ QMutexLocker locker(&m_mutex);
+
+ if (m_clock)
+ m_clock->Release();
+
+ m_clock = pClock;
+
+ if (m_clock)
+ m_clock->AddRef();
+
+ return S_OK;
+}
+
+HRESULT DirectShowBaseFilter::GetSyncSource(IReferenceClock **ppClock)
+{
+ if (!ppClock) {
+ return E_POINTER;
+ } else {
+ if (!m_clock) {
+ *ppClock = 0;
+
+ return S_FALSE;
+ } else {
+ m_clock->AddRef();
+
+ *ppClock = m_clock;
+
+ return S_OK;
+ }
+ }
+}
+
+HRESULT DirectShowBaseFilter::EnumPins(IEnumPins **ppEnum)
+{
+ if (!ppEnum) {
+ return E_POINTER;
+ } else {
+ *ppEnum = new DirectShowPinEnum(this);
+ return S_OK;
+ }
+}
+
+HRESULT DirectShowBaseFilter::FindPin(LPCWSTR Id, IPin **ppPin)
+{
+ if (!ppPin || !Id) {
+ return E_POINTER;
+ } else {
+ QMutexLocker locker(&m_mutex);
+ const QList<DirectShowPin *> pinList = pins();
+ for (DirectShowPin *pin : pinList) {
+ if (QString::fromWCharArray(Id) == pin->name()) {
+ pin->AddRef();
+ *ppPin = pin;
+ return S_OK;
+ }
+ }
+
+ *ppPin = 0;
+ return VFW_E_NOT_FOUND;
+ }
+}
+
+HRESULT DirectShowBaseFilter::JoinFilterGraph(IFilterGraph *pGraph, LPCWSTR pName)
+{
+ QMutexLocker locker(&m_mutex);
+
+ m_filterName = QString::fromWCharArray(pName);
+ m_graph = pGraph;
+ m_sink = NULL;
+
+ if (m_graph) {
+ if (SUCCEEDED(m_graph->QueryInterface(IID_PPV_ARGS(&m_sink))))
+ m_sink->Release(); // we don't keep a reference on it
+ }
+
+ return S_OK;
+}
+
+HRESULT DirectShowBaseFilter::QueryFilterInfo(FILTER_INFO *pInfo)
+{
+ if (!pInfo) {
+ return E_POINTER;
+ } else {
+ QString name = m_filterName;
+
+ if (name.length() >= MAX_FILTER_NAME)
+ name.truncate(MAX_FILTER_NAME - 1);
+
+ int length = name.toWCharArray(pInfo->achName);
+ pInfo->achName[length] = '\0';
+
+ if (m_graph)
+ m_graph->AddRef();
+
+ pInfo->pGraph = m_graph;
+
+ return S_OK;
+ }
+}
+
+HRESULT DirectShowBaseFilter::QueryVendorInfo(LPWSTR *pVendorInfo)
+{
+ Q_UNUSED(pVendorInfo);
+ return E_NOTIMPL;
+}
diff --git a/src/plugins/directshow/helpers/directshowbasefilter.h b/src/plugins/directshow/helpers/directshowbasefilter.h
new file mode 100644
index 000000000..cc8588044
--- /dev/null
+++ b/src/plugins/directshow/helpers/directshowbasefilter.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef DIRECTSHOWBASEFILTER_H
+#define DIRECTSHOWBASEFILTER_H
+
+#include "directshowpin.h"
+
+QT_USE_NAMESPACE
+
+class DirectShowBaseFilter : public DirectShowObject
+ , public IBaseFilter
+{
+ DIRECTSHOW_OBJECT
+
+public:
+ DirectShowBaseFilter();
+ virtual ~DirectShowBaseFilter();
+
+ FILTER_STATE state() const { return m_state; }
+ HRESULT NotifyEvent(long eventCode, LONG_PTR eventParam1, LONG_PTR eventParam2);
+
+ virtual QList<DirectShowPin *> pins() = 0;
+
+ // DirectShowObject
+ HRESULT getInterface(const IID &riid, void **ppvObject);
+
+ // IPersist
+ STDMETHODIMP GetClassID(CLSID *pClassID);
+
+ // IMediaFilter
+ STDMETHODIMP Run(REFERENCE_TIME tStart);
+ STDMETHODIMP Pause();
+ STDMETHODIMP Stop();
+
+ STDMETHODIMP GetState(DWORD dwMilliSecsTimeout, FILTER_STATE *pState);
+
+ STDMETHODIMP SetSyncSource(IReferenceClock *pClock);
+ STDMETHODIMP GetSyncSource(IReferenceClock **ppClock);
+
+ // IBaseFilter
+ STDMETHODIMP EnumPins(IEnumPins **ppEnum);
+ STDMETHODIMP FindPin(LPCWSTR Id, IPin **ppPin);
+
+ STDMETHODIMP JoinFilterGraph(IFilterGraph *pGraph, LPCWSTR pName);
+
+ STDMETHODIMP QueryFilterInfo(FILTER_INFO *pInfo);
+ STDMETHODIMP QueryVendorInfo(LPWSTR *pVendorInfo);
+
+protected:
+ QMutex m_mutex;
+ FILTER_STATE m_state;
+ IFilterGraph *m_graph;
+ IReferenceClock *m_clock;
+ IMediaEventSink *m_sink;
+ QString m_filterName;
+ REFERENCE_TIME m_startTime;
+
+private:
+ Q_DISABLE_COPY(DirectShowBaseFilter)
+};
+
+#endif // DIRECTSHOWBASEFILTER_H
diff --git a/src/plugins/directshow/player/directshoweventloop.cpp b/src/plugins/directshow/helpers/directshoweventloop.cpp
index 87f969e42..87f969e42 100644
--- a/src/plugins/directshow/player/directshoweventloop.cpp
+++ b/src/plugins/directshow/helpers/directshoweventloop.cpp
diff --git a/src/plugins/directshow/player/directshoweventloop.h b/src/plugins/directshow/helpers/directshoweventloop.h
index 09d986de7..09d986de7 100644
--- a/src/plugins/directshow/player/directshoweventloop.h
+++ b/src/plugins/directshow/helpers/directshoweventloop.h
diff --git a/src/plugins/directshow/player/directshowglobal.h b/src/plugins/directshow/helpers/directshowglobal.h
index f7890c52b..f7890c52b 100644
--- a/src/plugins/directshow/player/directshowglobal.h
+++ b/src/plugins/directshow/helpers/directshowglobal.h
diff --git a/src/plugins/directshow/player/directshowmediatype.cpp b/src/plugins/directshow/helpers/directshowmediatype.cpp
index cbe1753ae..60c0ee040 100644
--- a/src/plugins/directshow/player/directshowmediatype.cpp
+++ b/src/plugins/directshow/helpers/directshowmediatype.cpp
@@ -62,12 +62,48 @@ namespace
{ QVideoFrame::Format_IMC4, /*MEDIASUBTYPE_IMC4*/ {0x34434D49, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} },
{ QVideoFrame::Format_YV12, /*MEDIASUBTYPE_YV12*/ {0x32315659, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} },
{ QVideoFrame::Format_NV12, /*MEDIASUBTYPE_NV12*/ {0x3231564E, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} },
- { QVideoFrame::Format_YUV420P, /*MEDIASUBTYPE_IYUV*/ {0x56555949, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} }
+ { QVideoFrame::Format_YUV420P, /*MEDIASUBTYPE_IYUV*/ {0x56555949, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} },
+ { QVideoFrame::Format_YUV420P, /*MEDIASUBTYPE_I420*/ {0x30323449, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} }
};
}
+bool DirectShowMediaType::isPartiallySpecified() const
+{
+ return majortype == GUID_NULL || formattype == GUID_NULL;
+}
+
+bool DirectShowMediaType::isCompatibleWith(const DirectShowMediaType *type) const
+{
+ if (type->majortype != GUID_NULL && majortype != type->majortype)
+ return false;
+
+ if (type->subtype != GUID_NULL && subtype != type->subtype)
+ return false;
+
+ if (type->formattype != GUID_NULL) {
+ if (formattype != type->formattype)
+ return false;
+ if (cbFormat != type->cbFormat)
+ return false;
+ if (cbFormat != 0 && memcmp(pbFormat, type->pbFormat, cbFormat) != 0)
+ return false;
+ }
+
+ return true;
+}
+
+void DirectShowMediaType::init(AM_MEDIA_TYPE *type)
+{
+ ZeroMemory((PVOID)type, sizeof(*type));
+ type->lSampleSize = 1;
+ type->bFixedSizeSamples = TRUE;
+}
+
void DirectShowMediaType::copy(AM_MEDIA_TYPE *target, const AM_MEDIA_TYPE &source)
{
+ if (!target)
+ return;
+
*target = source;
if (source.cbFormat > 0) {
@@ -97,16 +133,13 @@ void DirectShowMediaType::freeData(AM_MEDIA_TYPE *type)
GUID DirectShowMediaType::convertPixelFormat(QVideoFrame::PixelFormat format)
{
- // MEDIASUBTYPE_None;
- static const GUID none = {
- 0xe436eb8e, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70} };
-
const int count = sizeof(qt_typeLookup) / sizeof(TypeLookup);
for (int i = 0; i < count; ++i)
if (qt_typeLookup[i].pixelFormat == format)
return qt_typeLookup[i].mediaType;
- return none;
+
+ return MEDIASUBTYPE_None;
}
QVideoSurfaceFormat DirectShowMediaType::formatFromType(const AM_MEDIA_TYPE &type)
@@ -147,6 +180,19 @@ QVideoSurfaceFormat DirectShowMediaType::formatFromType(const AM_MEDIA_TYPE &typ
return QVideoSurfaceFormat();
}
+QVideoFrame::PixelFormat DirectShowMediaType::pixelFormatFromType(const AM_MEDIA_TYPE &type)
+{
+ const int count = sizeof(qt_typeLookup) / sizeof(TypeLookup);
+
+ for (int i = 0; i < count; ++i) {
+ if (IsEqualGUID(qt_typeLookup[i].mediaType, type.subtype)) {
+ return qt_typeLookup[i].pixelFormat;
+ }
+ }
+
+ return QVideoFrame::Format_Invalid;
+}
+
#define PAD_TO_DWORD(x) (((x) + 3) & ~3)
int DirectShowMediaType::bytesPerLine(const QVideoSurfaceFormat &format)
{
@@ -165,14 +211,14 @@ int DirectShowMediaType::bytesPerLine(const QVideoSurfaceFormat &format)
case QVideoFrame::Format_UYVY:
return PAD_TO_DWORD(format.frameWidth() * 2);
// Planar formats.
+ case QVideoFrame::Format_YV12:
+ case QVideoFrame::Format_YUV420P:
case QVideoFrame::Format_IMC1:
case QVideoFrame::Format_IMC2:
case QVideoFrame::Format_IMC3:
case QVideoFrame::Format_IMC4:
- case QVideoFrame::Format_YV12:
case QVideoFrame::Format_NV12:
- case QVideoFrame::Format_YUV420P:
- return PAD_TO_DWORD(format.frameWidth());
+ return format.frameWidth();
default:
return 0;
}
diff --git a/src/plugins/directshow/player/directshowmediatype.h b/src/plugins/directshow/helpers/directshowmediatype.h
index cf5ac73aa..b2b074ccc 100644
--- a/src/plugins/directshow/player/directshowmediatype.h
+++ b/src/plugins/directshow/helpers/directshowmediatype.h
@@ -46,10 +46,12 @@
#include <dvdmedia.h>
+QT_USE_NAMESPACE
+
class DirectShowMediaType : public AM_MEDIA_TYPE
{
public:
- DirectShowMediaType() { memset(this, 0, sizeof(DirectShowMediaType)); }
+ DirectShowMediaType() { init(this); }
DirectShowMediaType(const AM_MEDIA_TYPE &type) { copy(this, type); }
DirectShowMediaType(const DirectShowMediaType &other) { copy(this, other); }
DirectShowMediaType &operator =(const AM_MEDIA_TYPE &type) {
@@ -58,14 +60,19 @@ public:
freeData(this); copy(this, other); return *this; }
~DirectShowMediaType() { freeData(this); }
- void clear() { freeData(this); memset(this, 0, sizeof(DirectShowMediaType)); }
+ void clear() { freeData(this); init(this); }
+
+ bool isPartiallySpecified() const;
+ bool isCompatibleWith(const DirectShowMediaType *type) const;
+ static void init(AM_MEDIA_TYPE *type);
static void copy(AM_MEDIA_TYPE *target, const AM_MEDIA_TYPE &source);
static void freeData(AM_MEDIA_TYPE *type);
static void deleteType(AM_MEDIA_TYPE *type);
static GUID convertPixelFormat(QVideoFrame::PixelFormat format);
static QVideoSurfaceFormat formatFromType(const AM_MEDIA_TYPE &type);
+ static QVideoFrame::PixelFormat pixelFormatFromType(const AM_MEDIA_TYPE &type);
static int bytesPerLine(const QVideoSurfaceFormat &format);
@@ -73,4 +80,6 @@ private:
static QVideoSurfaceFormat::Direction scanLineDirection(QVideoFrame::PixelFormat pixelFormat, const BITMAPINFOHEADER &bmiHeader);
};
+Q_DECLARE_TYPEINFO(DirectShowMediaType, Q_MOVABLE_TYPE);
+
#endif
diff --git a/src/plugins/directshow/helpers/directshowmediatypeenum.cpp b/src/plugins/directshow/helpers/directshowmediatypeenum.cpp
new file mode 100644
index 000000000..a1c8b2306
--- /dev/null
+++ b/src/plugins/directshow/helpers/directshowmediatypeenum.cpp
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "directshowmediatypeenum.h"
+
+#include "directshowpin.h"
+
+DirectShowMediaTypeEnum::DirectShowMediaTypeEnum(DirectShowPin *pin)
+ : m_pin(pin)
+ , m_mediaTypes(pin->supportedMediaTypes())
+ , m_index(0)
+{
+ m_pin->AddRef();
+}
+
+DirectShowMediaTypeEnum::DirectShowMediaTypeEnum(const QList<DirectShowMediaType> &types)
+ : m_pin(NULL)
+ , m_mediaTypes(types)
+ , m_index(0)
+{
+}
+
+DirectShowMediaTypeEnum::~DirectShowMediaTypeEnum()
+{
+ if (m_pin)
+ m_pin->Release();
+}
+
+HRESULT DirectShowMediaTypeEnum::getInterface(REFIID riid, void **ppvObject)
+{
+ if (riid == IID_IEnumMediaTypes) {
+ return GetInterface(static_cast<IEnumMediaTypes *>(this), ppvObject);
+ } else {
+ return DirectShowObject::getInterface(riid, ppvObject);
+ }
+}
+
+HRESULT DirectShowMediaTypeEnum::Next(ULONG cMediaTypes, AM_MEDIA_TYPE **ppMediaTypes, ULONG *pcFetched)
+{
+ if (ppMediaTypes && (pcFetched || cMediaTypes == 1)) {
+ ULONG count = qBound<ULONG>(0, cMediaTypes, m_mediaTypes.count() - m_index);
+
+ for (ULONG i = 0; i < count; ++i, ++m_index) {
+ ppMediaTypes[i] = reinterpret_cast<AM_MEDIA_TYPE *>(CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE)));
+ DirectShowMediaType::copy(ppMediaTypes[i], m_mediaTypes.at(m_index));
+ }
+
+ if (pcFetched)
+ *pcFetched = count;
+
+ return count == cMediaTypes ? S_OK : S_FALSE;
+ } else {
+ return E_POINTER;
+ }
+}
+
+HRESULT DirectShowMediaTypeEnum::Skip(ULONG cMediaTypes)
+{
+ m_index = qMin(int(m_index + cMediaTypes), m_mediaTypes.count());
+ return m_index < m_mediaTypes.count() ? S_OK : S_FALSE;
+}
+
+HRESULT DirectShowMediaTypeEnum::Reset()
+{
+ m_index = 0;
+ return S_OK;
+}
+
+HRESULT DirectShowMediaTypeEnum::Clone(IEnumMediaTypes **ppEnum)
+{
+ if (ppEnum) {
+ if (m_pin)
+ *ppEnum = new DirectShowMediaTypeEnum(m_pin);
+ else
+ *ppEnum = new DirectShowMediaTypeEnum(m_mediaTypes);
+ return S_OK;
+ } else {
+ return E_POINTER;
+ }
+}
+
diff --git a/src/plugins/directshow/helpers/directshowmediatypeenum.h b/src/plugins/directshow/helpers/directshowmediatypeenum.h
new file mode 100644
index 000000000..050df0881
--- /dev/null
+++ b/src/plugins/directshow/helpers/directshowmediatypeenum.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef DIRECTSHOWMEDIATYPEENUM_H
+#define DIRECTSHOWMEDIATYPEENUM_H
+
+#include "directshowobject.h"
+#include <qlist.h>
+
+QT_USE_NAMESPACE
+
+class DirectShowPin;
+class DirectShowMediaType;
+
+class DirectShowMediaTypeEnum : public DirectShowObject
+ , public IEnumMediaTypes
+{
+ DIRECTSHOW_OBJECT
+
+public:
+ DirectShowMediaTypeEnum(DirectShowPin *pin);
+ DirectShowMediaTypeEnum(const QList<DirectShowMediaType> &types);
+ ~DirectShowMediaTypeEnum();
+
+ // DirectShowObject
+ HRESULT getInterface(REFIID riid, void **ppvObject);
+
+ // IEnumMediaTypes
+ STDMETHODIMP Next(ULONG cMediaTypes, AM_MEDIA_TYPE **ppMediaTypes, ULONG *pcFetched);
+ STDMETHODIMP Skip(ULONG cMediaTypes);
+ STDMETHODIMP Reset();
+ STDMETHODIMP Clone(IEnumMediaTypes **ppEnum);
+
+private:
+ Q_DISABLE_COPY(DirectShowMediaTypeEnum)
+
+ DirectShowPin *m_pin;
+ QList<DirectShowMediaType> m_mediaTypes;
+ int m_index;
+};
+
+#endif // DIRECTSHOWMEDIATYPEENUM_H
diff --git a/src/plugins/directshow/player/directshowmediatypelist.h b/src/plugins/directshow/helpers/directshowobject.cpp
index 2bd8dca59..b9d989f6e 100644
--- a/src/plugins/directshow/player/directshowmediatypelist.h
+++ b/src/plugins/directshow/helpers/directshowobject.cpp
@@ -37,34 +37,47 @@
**
****************************************************************************/
-#ifndef DIRECTSHOWMEDIATYPELIST_H
-#define DIRECTSHOWMEDIATYPELIST_H
+#include "directshowobject.h"
-#include <dshow.h>
+DirectShowObject::DirectShowObject()
+ : m_ref(1)
+{
+}
+
+DirectShowObject::~DirectShowObject()
+{
+ Q_ASSERT(m_ref == 0);
+}
-#include <QtCore/qvector.h>
+HRESULT DirectShowObject::getInterface(const IID &riid, void **ppvObject)
+{
+ Q_UNUSED(riid)
+ *ppvObject = NULL;
+ return E_NOINTERFACE;
+}
-class DirectShowMediaTypeList : public IUnknown
+ULONG DirectShowObject::ref()
{
-public:
- DirectShowMediaTypeList();
- virtual ~DirectShowMediaTypeList();
+ return InterlockedIncrement(&m_ref);
+}
- IEnumMediaTypes *createMediaTypeEnum();
+ULONG DirectShowObject::unref()
+{
+ ULONG ref = InterlockedDecrement(&m_ref);
+ if (ref == 0)
+ delete this;
- void setMediaTypes(const QVector<AM_MEDIA_TYPE> &types);
+ return ref;
+}
- virtual int currentMediaTypeToken();
- virtual HRESULT nextMediaType(
- int token, int *index, ULONG count, AM_MEDIA_TYPE **types, ULONG *fetchedCount);
- virtual HRESULT skipMediaType(int token, int *index, ULONG count);
- virtual HRESULT cloneMediaType(int token, int index, IEnumMediaTypes **enumeration);
+HRESULT GetInterface(IUnknown *pUnk, void **ppv)
+{
+ if (!ppv)
+ return E_POINTER;
-protected:
- QVector<AM_MEDIA_TYPE> m_mediaTypes;
+ *ppv = pUnk;
+ pUnk->AddRef();
-private:
- int m_mediaTypeToken;
-};
+ return S_OK;
+}
-#endif
diff --git a/src/plugins/directshow/helpers/directshowobject.h b/src/plugins/directshow/helpers/directshowobject.h
new file mode 100644
index 000000000..3aba06f46
--- /dev/null
+++ b/src/plugins/directshow/helpers/directshowobject.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef DIRECTSHOWOBJECT_H
+#define DIRECTSHOWOBJECT_H
+
+#include "directshowglobal.h"
+
+QT_USE_NAMESPACE
+
+class DirectShowObject
+{
+public:
+ DirectShowObject();
+ virtual ~DirectShowObject();
+
+ virtual HRESULT getInterface(REFIID riid, void **ppvObject);
+ ULONG ref();
+ ULONG unref();
+
+private:
+ Q_DISABLE_COPY(DirectShowObject)
+
+ volatile LONG m_ref;
+};
+
+HRESULT GetInterface(IUnknown *pUnk, void **ppv);
+
+#define DIRECTSHOW_OBJECT \
+public: \
+ STDMETHODIMP QueryInterface(REFIID riid, void **ppv) { \
+ if (riid == IID_IUnknown) \
+ return GetInterface(reinterpret_cast<IUnknown*>(this), ppv); \
+ else \
+ return getInterface(riid, ppv); \
+ }; \
+ STDMETHODIMP_(ULONG) AddRef() { \
+ return ref(); \
+ }; \
+ STDMETHODIMP_(ULONG) Release() { \
+ return unref(); \
+ };
+
+#endif // DIRECTSHOWOBJECT_H
diff --git a/src/plugins/directshow/helpers/directshowpin.cpp b/src/plugins/directshow/helpers/directshowpin.cpp
new file mode 100644
index 000000000..6cf4da321
--- /dev/null
+++ b/src/plugins/directshow/helpers/directshowpin.cpp
@@ -0,0 +1,733 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "directshowpin.h"
+
+#include "directshowmediatype.h"
+#include "directshowbasefilter.h"
+#include "directshowmediatypeenum.h"
+
+#include <qdebug.h>
+
+DirectShowPin::DirectShowPin(DirectShowBaseFilter *filter, const QString &name, PIN_DIRECTION direction)
+ : m_mutex(QMutex::Recursive)
+ , m_filter(filter)
+ , m_name(name)
+ , m_direction(direction)
+ , m_peerPin(NULL)
+{
+}
+
+DirectShowPin::~DirectShowPin()
+{
+
+}
+
+HRESULT DirectShowPin::getInterface(const IID &riid, void **ppvObject)
+{
+ if (riid == IID_IPin)
+ return GetInterface(static_cast<IPin*>(this), ppvObject);
+ else
+ return DirectShowObject::getInterface(riid, ppvObject);
+}
+
+
+
+HRESULT DirectShowPin::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt)
+{
+ if (!pReceivePin)
+ return E_POINTER;
+
+ HRESULT hr = E_FAIL;
+ QMutexLocker locker(&m_mutex);
+
+ if (m_peerPin)
+ return VFW_E_ALREADY_CONNECTED;
+ if (m_filter->state() != State_Stopped)
+ return VFW_E_NOT_STOPPED;
+
+ PIN_DIRECTION pd;
+ pReceivePin->QueryDirection(&pd);
+ if (pd == m_direction)
+ return VFW_E_INVALID_DIRECTION;
+
+ const DirectShowMediaType *type = reinterpret_cast<const DirectShowMediaType*>(pmt);
+
+ if (type != NULL && !type->isPartiallySpecified()) {
+ // If the type is fully specified, use it
+ hr = tryConnect(pReceivePin, type);
+ } else {
+ IEnumMediaTypes *enumMediaTypes = NULL;
+
+ // First, try the receiving pin's preferred types
+ if (SUCCEEDED(pReceivePin->EnumMediaTypes(&enumMediaTypes))) {
+ hr = tryMediaTypes(pReceivePin, type, enumMediaTypes);
+ enumMediaTypes->Release();
+ }
+ // Then, try this pin's preferred types
+ if (FAILED(hr) && SUCCEEDED(EnumMediaTypes(&enumMediaTypes))) {
+ hr = tryMediaTypes(pReceivePin, type, enumMediaTypes);
+ enumMediaTypes->Release();
+ }
+ }
+
+ if (FAILED(hr)) {
+ return ((hr != E_FAIL) && (hr != E_INVALIDARG) && (hr != VFW_E_TYPE_NOT_ACCEPTED))
+ ? hr : VFW_E_NO_ACCEPTABLE_TYPES;
+ }
+
+ return S_OK;
+}
+
+HRESULT DirectShowPin::tryMediaTypes(IPin *pin, const DirectShowMediaType *partialType, IEnumMediaTypes *enumMediaTypes)
+{
+ HRESULT hr = enumMediaTypes->Reset();
+ if (FAILED(hr))
+ return hr;
+
+ DirectShowMediaType *mediaType = NULL;
+ ULONG mediaCount = 0;
+ HRESULT hrFailure = VFW_E_NO_ACCEPTABLE_TYPES;
+
+ for (; enumMediaTypes->Next(1, reinterpret_cast<AM_MEDIA_TYPE**>(&mediaType), &mediaCount) == S_OK;) {
+
+ if (mediaType && (partialType == NULL || mediaType->isCompatibleWith(partialType))) {
+ hr = tryConnect(pin, mediaType);
+
+ if (FAILED(hr) && (hr != E_FAIL)
+ && (hr != E_INVALIDARG)
+ && (hr != VFW_E_TYPE_NOT_ACCEPTED)) {
+ hrFailure = hr;
+ }
+ }
+
+ if (mediaType)
+ DirectShowMediaType::deleteType(mediaType);
+
+ if (SUCCEEDED(hr))
+ return S_OK;
+ }
+
+ return hrFailure;
+}
+
+HRESULT DirectShowPin::tryConnect(IPin *pin, const DirectShowMediaType *type)
+{
+ if (!isMediaTypeSupported(type))
+ return VFW_E_TYPE_NOT_ACCEPTED;
+
+ m_peerPin = pin;
+ m_peerPin->AddRef();
+
+ HRESULT hr;
+ if (!setMediaType(type)) {
+ hr = VFW_E_TYPE_NOT_ACCEPTED;
+ } else {
+ hr = pin->ReceiveConnection(this, type);
+ if (SUCCEEDED(hr)) {
+ hr = completeConnection(pin);
+ if (FAILED(hr))
+ pin->Disconnect();
+ }
+ }
+
+ if (FAILED(hr)) {
+ connectionEnded();
+ m_peerPin->Release();
+ m_peerPin = NULL;
+ setMediaType(NULL);
+ return hr;
+ }
+
+ return S_OK;
+}
+
+HRESULT DirectShowPin::ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt)
+{
+ if (!pConnector || !pmt)
+ return E_POINTER;
+
+ QMutexLocker locker(&m_mutex);
+
+ if (m_peerPin)
+ return VFW_E_ALREADY_CONNECTED;
+ if (m_filter->state() != State_Stopped)
+ return VFW_E_NOT_STOPPED;
+
+ PIN_DIRECTION pd;
+ pConnector->QueryDirection(&pd);
+ if (pd == m_direction)
+ return VFW_E_INVALID_DIRECTION;
+
+ const DirectShowMediaType *type = reinterpret_cast<const DirectShowMediaType*>(pmt);
+ if (!isMediaTypeSupported(type))
+ return VFW_E_TYPE_NOT_ACCEPTED;
+
+ m_peerPin = pConnector;
+ m_peerPin->AddRef();
+
+ HRESULT hr;
+ if (!setMediaType(type))
+ hr = VFW_E_TYPE_NOT_ACCEPTED;
+ else
+ hr = completeConnection(pConnector);
+
+ if (FAILED(hr)) {
+ connectionEnded();
+ m_peerPin->Release();
+ m_peerPin = NULL;
+ setMediaType(NULL);
+ return hr;
+ }
+
+ return S_OK;
+}
+
+HRESULT DirectShowPin::Disconnect()
+{
+ QMutexLocker locker(&m_mutex);
+
+ if (m_filter->state() != State_Stopped)
+ return VFW_E_NOT_STOPPED;
+
+ if (m_peerPin) {
+ HRESULT hr = connectionEnded();
+ if (FAILED(hr))
+ return hr;
+
+ m_peerPin->Release();
+ m_peerPin = NULL;
+
+ setMediaType(NULL);
+
+ return S_OK;
+ }
+
+ return S_FALSE;
+}
+
+HRESULT DirectShowPin::ConnectedTo(IPin **ppPin)
+{
+ if (!ppPin) {
+ return E_POINTER;
+ } else {
+ QMutexLocker locker(&m_mutex);
+
+ if (!m_peerPin) {
+ *ppPin = 0;
+ return VFW_E_NOT_CONNECTED;
+ } else {
+ m_peerPin->AddRef();
+ *ppPin = m_peerPin;
+ return S_OK;
+ }
+ }
+}
+
+HRESULT DirectShowPin::ConnectionMediaType(AM_MEDIA_TYPE *pmt)
+{
+ if (!pmt) {
+ return E_POINTER;
+ } else {
+ QMutexLocker locker(&m_mutex);
+
+ if (!m_peerPin) {
+ DirectShowMediaType::init(pmt);
+ return VFW_E_NOT_CONNECTED;
+ } else {
+ DirectShowMediaType::copy(pmt, m_mediaType);
+ return S_OK;
+ }
+ }
+}
+
+HRESULT DirectShowPin::QueryPinInfo(PIN_INFO *pInfo)
+{
+ if (!pInfo) {
+ return E_POINTER;
+ } else {
+ pInfo->pFilter = m_filter;
+ if (m_filter) {
+ m_filter->AddRef();
+ }
+ pInfo->dir = m_direction;
+
+ QString name = m_name;
+ if (name.length() >= MAX_PIN_NAME)
+ name.truncate(MAX_PIN_NAME - 1);
+ int length = name.toWCharArray(pInfo->achName);
+ pInfo->achName[length] = '\0';
+
+ return S_OK;
+ }
+}
+
+HRESULT DirectShowPin::QueryId(LPWSTR *Id)
+{
+ if (!Id) {
+ return E_POINTER;
+ } else {
+ const int bytes = (m_name.length() + 1) * 2;
+ *Id = static_cast<LPWSTR>(::CoTaskMemAlloc(bytes));
+ ::memcpy(*Id, m_name.utf16(), bytes);
+ return S_OK;
+ }
+}
+
+HRESULT DirectShowPin::QueryAccept(const AM_MEDIA_TYPE *pmt)
+{
+ if (!pmt)
+ return E_POINTER;
+
+ if (!isMediaTypeSupported(reinterpret_cast<const DirectShowMediaType*>(pmt)))
+ return S_FALSE;
+
+ return S_OK;
+}
+
+HRESULT DirectShowPin::EnumMediaTypes(IEnumMediaTypes **ppEnum)
+{
+ if (!ppEnum) {
+ return E_POINTER;
+ } else {
+ *ppEnum = new DirectShowMediaTypeEnum(this);
+ return S_OK;
+ }
+}
+
+HRESULT DirectShowPin::QueryInternalConnections(IPin **apPin, ULONG *nPin)
+{
+ Q_UNUSED(apPin);
+ Q_UNUSED(nPin);
+ return E_NOTIMPL;
+}
+
+HRESULT DirectShowPin::EndOfStream()
+{
+ return S_OK;
+}
+
+HRESULT DirectShowPin::BeginFlush()
+{
+ return E_UNEXPECTED;
+}
+
+HRESULT DirectShowPin::EndFlush()
+{
+ return E_UNEXPECTED;
+}
+
+HRESULT DirectShowPin::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
+{
+ Q_UNUSED(tStart);
+ Q_UNUSED(tStop);
+ Q_UNUSED(dRate);
+ return S_OK;
+}
+
+HRESULT DirectShowPin::QueryDirection(PIN_DIRECTION *pPinDir)
+{
+ if (!pPinDir) {
+ return E_POINTER;
+ } else {
+ *pPinDir = m_direction;
+ return S_OK;
+ }
+}
+
+QList<DirectShowMediaType> DirectShowPin::supportedMediaTypes()
+{
+ return QList<DirectShowMediaType>();
+}
+
+bool DirectShowPin::setMediaType(const DirectShowMediaType *type)
+{
+ if (!type)
+ m_mediaType.clear();
+ else
+ m_mediaType = *type;
+
+ return true;
+}
+
+HRESULT DirectShowPin::completeConnection(IPin *pin)
+{
+ Q_UNUSED(pin)
+ return S_OK;
+}
+
+HRESULT DirectShowPin::connectionEnded()
+{
+ return S_OK;
+}
+
+HRESULT DirectShowPin::setActive(bool active)
+{
+ Q_UNUSED(active)
+ return S_OK;
+}
+
+
+/* DirectShowOutputPin */
+
+DirectShowOutputPin::DirectShowOutputPin(DirectShowBaseFilter *filter, const QString &name)
+ : DirectShowPin(filter, name, PINDIR_OUTPUT)
+ , m_allocator(NULL)
+ , m_inputPin(NULL)
+{
+
+}
+
+DirectShowOutputPin::~DirectShowOutputPin()
+{
+}
+
+HRESULT DirectShowOutputPin::completeConnection(IPin *pin)
+{
+ if (!pin)
+ return E_POINTER;
+
+ Q_ASSERT(m_inputPin == NULL);
+ Q_ASSERT(m_allocator == NULL);
+
+ HRESULT hr = pin->QueryInterface(IID_PPV_ARGS(&m_inputPin));
+ if (FAILED(hr))
+ return hr;
+
+ ALLOCATOR_PROPERTIES prop;
+ ZeroMemory(&prop, sizeof(prop));
+ m_inputPin->GetAllocatorRequirements(&prop);
+ if (prop.cBuffers <= 0)
+ prop.cBuffers = 1;
+ if (prop.cbBuffer <= 0)
+ prop.cbBuffer = 1;
+ if (prop.cbAlign <= 0)
+ prop.cbAlign = 1;
+
+ // Use the connected input pin's allocator if it has one
+ hr = m_inputPin->GetAllocator(&m_allocator);
+ if (SUCCEEDED(hr)) {
+ ALLOCATOR_PROPERTIES actualProperties;
+ hr = m_allocator->SetProperties(&prop, &actualProperties);
+
+ if (SUCCEEDED(hr)) {
+ hr = m_inputPin->NotifyAllocator(m_allocator, FALSE);
+ if (SUCCEEDED(hr))
+ return S_OK;
+ }
+
+ m_allocator->Release();
+ m_allocator = NULL;
+ }
+
+ // Otherwise, allocate its own allocator
+ m_allocator = com_new<IMemAllocator>(CLSID_MemoryAllocator);
+ if (!m_allocator) {
+ hr = E_OUTOFMEMORY;
+ } else {
+ ALLOCATOR_PROPERTIES actualProperties;
+ hr = m_allocator->SetProperties(&prop, &actualProperties);
+
+ if (SUCCEEDED(hr)) {
+ hr = m_inputPin->NotifyAllocator(m_allocator, FALSE);
+ if (SUCCEEDED(hr))
+ return S_OK;
+ }
+
+ m_allocator->Release();
+ m_allocator = NULL;
+ }
+
+ return hr;
+}
+
+HRESULT DirectShowOutputPin::connectionEnded()
+{
+ if (m_allocator) {
+ HRESULT hr = m_allocator->Decommit();
+ if (FAILED(hr))
+ return hr;
+
+ m_allocator->Release();
+ m_allocator = NULL;
+ }
+
+ if (m_inputPin) {
+ m_inputPin->Release();
+ m_inputPin = NULL;
+ }
+
+ return S_OK;
+}
+
+HRESULT DirectShowOutputPin::setActive(bool active)
+{
+ if (!m_allocator)
+ return VFW_E_NO_ALLOCATOR;
+
+ return active ? m_allocator->Commit()
+ : m_allocator->Decommit();
+}
+
+HRESULT DirectShowOutputPin::EndOfStream()
+{
+ return E_UNEXPECTED;
+}
+
+
+/* DirectShowInputPin */
+
+DirectShowInputPin::DirectShowInputPin(DirectShowBaseFilter *filter, const QString &name)
+ : DirectShowPin(filter, name, PINDIR_INPUT)
+ , m_allocator(NULL)
+ , m_flushing(false)
+ , m_inErrorState(false)
+{
+ ZeroMemory(&m_sampleProperties, sizeof(m_sampleProperties));
+}
+
+DirectShowInputPin::~DirectShowInputPin()
+{
+
+}
+
+HRESULT DirectShowInputPin::getInterface(const IID &riid, void **ppvObject)
+{
+ if (riid == IID_IMemInputPin)
+ return GetInterface(static_cast<IMemInputPin*>(this), ppvObject);
+ else
+ return DirectShowPin::getInterface(riid, ppvObject);
+}
+
+HRESULT DirectShowInputPin::connectionEnded()
+{
+ if (m_allocator) {
+ HRESULT hr = m_allocator->Decommit();
+ if (FAILED(hr))
+ return hr;
+
+ m_allocator->Release();
+ m_allocator = NULL;
+ }
+
+ return S_OK;
+}
+
+HRESULT DirectShowInputPin::setActive(bool active)
+{
+ if (!active) {
+ m_inErrorState = false;
+
+ if (!m_allocator)
+ return VFW_E_NO_ALLOCATOR;
+
+ m_flushing = false;
+ return m_allocator->Decommit();
+ }
+
+ return S_OK;
+}
+
+HRESULT DirectShowInputPin::EndOfStream()
+{
+ if (m_filter->state() == State_Stopped)
+ return VFW_E_WRONG_STATE;
+ if (m_flushing)
+ return S_FALSE;
+ if (m_inErrorState)
+ return VFW_E_RUNTIME_ERROR;
+
+ return S_OK;
+}
+
+HRESULT DirectShowInputPin::BeginFlush()
+{
+ QMutexLocker locker(&m_mutex);
+ m_flushing = true;
+ return S_OK;
+}
+
+HRESULT DirectShowInputPin::EndFlush()
+{
+ QMutexLocker locker(&m_mutex);
+ m_flushing = false;
+ m_inErrorState = false;
+ return S_OK;
+}
+
+HRESULT DirectShowInputPin::GetAllocator(IMemAllocator **ppAllocator)
+{
+ if (!ppAllocator)
+ return E_POINTER;
+
+ QMutexLocker locker(&m_mutex);
+
+ if (!m_allocator) {
+ m_allocator = com_new<IMemAllocator>(CLSID_MemoryAllocator);;
+ if (!m_allocator)
+ return E_OUTOFMEMORY;
+ }
+
+ *ppAllocator = m_allocator;
+ m_allocator->AddRef();
+
+ return S_OK;
+}
+
+HRESULT DirectShowInputPin::NotifyAllocator(IMemAllocator *pAllocator, BOOL bReadOnly)
+{
+ Q_UNUSED(bReadOnly)
+
+ if (!pAllocator)
+ return E_POINTER;
+
+ QMutexLocker locker(&m_mutex);
+
+ if (m_allocator)
+ m_allocator->Release();
+
+ m_allocator = pAllocator;
+ m_allocator->AddRef();
+
+ return S_OK;
+}
+
+HRESULT DirectShowInputPin::GetAllocatorRequirements(ALLOCATOR_PROPERTIES *pProps)
+{
+ Q_UNUSED(pProps)
+ return E_NOTIMPL;
+}
+
+HRESULT DirectShowInputPin::Receive(IMediaSample *pSample)
+{
+ if (!pSample)
+ return E_POINTER;
+ if (m_filter->state() == State_Stopped)
+ return VFW_E_WRONG_STATE;
+ if (m_flushing)
+ return S_FALSE;
+ if (m_inErrorState)
+ return VFW_E_RUNTIME_ERROR;
+
+ HRESULT hr = S_OK;
+
+ IMediaSample2 *sample2;
+ if (SUCCEEDED(pSample->QueryInterface(IID_PPV_ARGS(&sample2)))) {
+ hr = sample2->GetProperties(sizeof(m_sampleProperties), (PBYTE)&m_sampleProperties);
+ sample2->Release();
+ if (FAILED(hr))
+ return hr;
+ } else {
+ m_sampleProperties.cbData = sizeof(m_sampleProperties);
+ m_sampleProperties.dwTypeSpecificFlags = 0;
+ m_sampleProperties.dwStreamId = AM_STREAM_MEDIA;
+ m_sampleProperties.dwSampleFlags = 0;
+ if (pSample->IsDiscontinuity() == S_OK)
+ m_sampleProperties.dwSampleFlags |= AM_SAMPLE_DATADISCONTINUITY;
+ if (pSample->IsPreroll() == S_OK)
+ m_sampleProperties.dwSampleFlags |= AM_SAMPLE_PREROLL;
+ if (pSample->IsSyncPoint() == S_OK)
+ m_sampleProperties.dwSampleFlags |= AM_SAMPLE_SPLICEPOINT;
+ if (SUCCEEDED(pSample->GetTime(&m_sampleProperties.tStart,
+ &m_sampleProperties.tStop))) {
+ m_sampleProperties.dwSampleFlags |= AM_SAMPLE_TIMEVALID | AM_SAMPLE_STOPVALID;
+ }
+ if (pSample->GetMediaType(&m_sampleProperties.pMediaType) == S_OK)
+ m_sampleProperties.dwSampleFlags |= AM_SAMPLE_TYPECHANGED;
+ pSample->GetPointer(&m_sampleProperties.pbBuffer);
+ m_sampleProperties.lActual = pSample->GetActualDataLength();
+ m_sampleProperties.cbBuffer = pSample->GetSize();
+ }
+
+
+ if (!(m_sampleProperties.dwSampleFlags & AM_SAMPLE_TYPECHANGED))
+ return S_OK;
+
+ if (isMediaTypeSupported(reinterpret_cast<DirectShowMediaType*>(m_sampleProperties.pMediaType)))
+ return S_OK;
+
+ m_inErrorState = true;
+ EndOfStream();
+ m_filter->NotifyEvent(EC_ERRORABORT, VFW_E_TYPE_NOT_ACCEPTED, 0);
+ return VFW_E_INVALIDMEDIATYPE;
+}
+
+HRESULT DirectShowInputPin::ReceiveMultiple(IMediaSample **pSamples, long nSamples, long *nSamplesProcessed)
+{
+ if (!pSamples || !nSamplesProcessed)
+ return E_POINTER;
+
+ HRESULT hr = S_OK;
+ *nSamplesProcessed = 0;
+ while (nSamples-- > 0) {
+ hr = Receive(pSamples[*nSamplesProcessed]);
+ if (hr != S_OK)
+ break;
+ (*nSamplesProcessed)++;
+ }
+ return hr;
+}
+
+HRESULT DirectShowInputPin::ReceiveCanBlock()
+{
+ int outputPins = 0;
+
+ const QList<DirectShowPin *> pinList = m_filter->pins();
+ for (DirectShowPin *pin : pinList) {
+ PIN_DIRECTION pd;
+ HRESULT hr = pin->QueryDirection(&pd);
+ if (FAILED(hr))
+ return hr;
+
+ if (pd == PINDIR_OUTPUT) {
+ IPin *connected;
+ hr = pin->ConnectedTo(&connected);
+ if (SUCCEEDED(hr)) {
+ ++outputPins;
+ IMemInputPin *inputPin;
+ hr = connected->QueryInterface(IID_PPV_ARGS(&inputPin));
+ connected->Release();
+ if (SUCCEEDED(hr)) {
+ hr = inputPin->ReceiveCanBlock();
+ inputPin->Release();
+ if (hr != S_FALSE)
+ return S_OK;
+ } else {
+ return S_OK;
+ }
+ }
+ }
+ }
+
+ return outputPins == 0 ? S_OK : S_FALSE;
+}
diff --git a/src/plugins/directshow/helpers/directshowpin.h b/src/plugins/directshow/helpers/directshowpin.h
new file mode 100644
index 000000000..823223956
--- /dev/null
+++ b/src/plugins/directshow/helpers/directshowpin.h
@@ -0,0 +1,184 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef DIRECTSHOWPIN_H
+#define DIRECTSHOWPIN_H
+
+#include "directshowobject.h"
+
+#include "directshowmediatype.h"
+#include <qstring.h>
+#include <qmutex.h>
+
+QT_USE_NAMESPACE
+
+class DirectShowBaseFilter;
+
+class DirectShowPin : public DirectShowObject
+ , public IPin
+{
+ DIRECTSHOW_OBJECT
+
+public:
+ virtual ~DirectShowPin();
+
+ QString name() const { return m_name; }
+ bool isConnected() const { return m_peerPin != NULL; }
+
+ virtual bool isMediaTypeSupported(const DirectShowMediaType *type) = 0;
+ virtual QList<DirectShowMediaType> supportedMediaTypes();
+ virtual bool setMediaType(const DirectShowMediaType *type);
+
+ virtual HRESULT completeConnection(IPin *pin);
+ virtual HRESULT connectionEnded();
+
+ virtual HRESULT setActive(bool active);
+
+ // DirectShowObject
+ HRESULT getInterface(REFIID riid, void **ppvObject);
+
+ // IPin
+ STDMETHODIMP Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt);
+ STDMETHODIMP ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt);
+ STDMETHODIMP Disconnect();
+ STDMETHODIMP ConnectedTo(IPin **ppPin);
+
+ STDMETHODIMP ConnectionMediaType(AM_MEDIA_TYPE *pmt);
+
+ STDMETHODIMP QueryPinInfo(PIN_INFO *pInfo);
+ STDMETHODIMP QueryId(LPWSTR *Id);
+
+ STDMETHODIMP QueryAccept(const AM_MEDIA_TYPE *pmt);
+
+ STDMETHODIMP EnumMediaTypes(IEnumMediaTypes **ppEnum);
+
+ STDMETHODIMP QueryInternalConnections(IPin **apPin, ULONG *nPin);
+
+ STDMETHODIMP EndOfStream();
+
+ STDMETHODIMP BeginFlush();
+ STDMETHODIMP EndFlush();
+
+ STDMETHODIMP NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate);
+
+ STDMETHODIMP QueryDirection(PIN_DIRECTION *pPinDir);
+
+protected:
+ DirectShowPin(DirectShowBaseFilter *filter, const QString &name, PIN_DIRECTION direction);
+
+ QMutex m_mutex;
+
+ DirectShowBaseFilter *m_filter;
+ QString m_name;
+ PIN_DIRECTION m_direction;
+
+ IPin *m_peerPin;
+ DirectShowMediaType m_mediaType;
+
+private:
+ Q_DISABLE_COPY(DirectShowPin)
+ HRESULT tryMediaTypes(IPin *pin, const DirectShowMediaType *type, IEnumMediaTypes *enumMediaTypes);
+ HRESULT tryConnect(IPin *pin, const DirectShowMediaType *type);
+};
+
+
+class DirectShowOutputPin : public DirectShowPin
+{
+ DIRECTSHOW_OBJECT
+
+public:
+ virtual ~DirectShowOutputPin();
+
+ // DirectShowPin
+ virtual HRESULT completeConnection(IPin *pin);
+ virtual HRESULT connectionEnded();
+ virtual HRESULT setActive(bool active);
+
+ // IPin
+ STDMETHODIMP EndOfStream();
+
+protected:
+ DirectShowOutputPin(DirectShowBaseFilter *filter, const QString &name);
+
+ IMemAllocator *m_allocator;
+ IMemInputPin *m_inputPin;
+
+private:
+ Q_DISABLE_COPY(DirectShowOutputPin)
+};
+
+
+class DirectShowInputPin : public DirectShowPin
+ , public IMemInputPin
+{
+ DIRECTSHOW_OBJECT
+
+public:
+ virtual ~DirectShowInputPin();
+
+ const AM_SAMPLE2_PROPERTIES *currentSampleProperties() const { return &m_sampleProperties; }
+
+ // DirectShowObject
+ HRESULT getInterface(REFIID riid, void **ppvObject);
+
+ // DirectShowPin
+ HRESULT connectionEnded();
+ HRESULT setActive(bool active);
+
+ // IPin
+ STDMETHODIMP EndOfStream();
+ STDMETHODIMP BeginFlush();
+ STDMETHODIMP EndFlush();
+
+ // IMemInputPin
+ STDMETHODIMP GetAllocator(IMemAllocator **ppAllocator);
+ STDMETHODIMP NotifyAllocator(IMemAllocator *pAllocator, BOOL bReadOnly);
+ STDMETHODIMP GetAllocatorRequirements(ALLOCATOR_PROPERTIES *pProps);
+
+ STDMETHODIMP Receive(IMediaSample *pSample);
+ STDMETHODIMP ReceiveMultiple(IMediaSample **pSamples, long nSamples, long *nSamplesProcessed);
+ STDMETHODIMP ReceiveCanBlock();
+
+protected:
+ DirectShowInputPin(DirectShowBaseFilter *filter, const QString &name);
+
+ IMemAllocator *m_allocator;
+ bool m_flushing;
+ bool m_inErrorState;
+ AM_SAMPLE2_PROPERTIES m_sampleProperties;
+
+private:
+ Q_DISABLE_COPY(DirectShowInputPin)
+};
+
+#endif // DIRECTSHOWPIN_H
diff --git a/src/plugins/directshow/player/directshowpinenum.cpp b/src/plugins/directshow/helpers/directshowpinenum.cpp
index 7ef986a26..61aca8b9c 100644
--- a/src/plugins/directshow/player/directshowpinenum.cpp
+++ b/src/plugins/directshow/helpers/directshowpinenum.cpp
@@ -38,10 +38,22 @@
****************************************************************************/
#include "directshowpinenum.h"
+#include "directshowbasefilter.h"
+DirectShowPinEnum::DirectShowPinEnum(DirectShowBaseFilter *filter)
+ : m_filter(filter)
+ , m_index(0)
+{
+ m_filter->AddRef();
+ const QList<DirectShowPin *> pinList = filter->pins();
+ for (DirectShowPin *pin : pinList) {
+ pin->AddRef();
+ m_pins.append(pin);
+ }
+}
DirectShowPinEnum::DirectShowPinEnum(const QList<IPin *> &pins)
- : m_ref(1)
+ : m_filter(NULL)
, m_pins(pins)
, m_index(0)
{
@@ -53,40 +65,19 @@ DirectShowPinEnum::~DirectShowPinEnum()
{
for (IPin *pin : qAsConst(m_pins))
pin->Release();
+ if (m_filter)
+ m_filter->Release();
}
-HRESULT DirectShowPinEnum::QueryInterface(REFIID riid, void **ppvObject)
+HRESULT DirectShowPinEnum::getInterface(REFIID riid, void **ppvObject)
{
- if (riid == IID_IUnknown
- || riid == IID_IEnumPins) {
- AddRef();
-
- *ppvObject = static_cast<IEnumPins *>(this);
-
- return S_OK;
+ if (riid == IID_IEnumPins) {
+ return GetInterface(static_cast<IEnumPins *>(this), ppvObject);
} else {
- *ppvObject = 0;
-
- return E_NOINTERFACE;
+ return DirectShowObject::getInterface(riid, ppvObject);
}
}
-ULONG DirectShowPinEnum::AddRef()
-{
- return InterlockedIncrement(&m_ref);
-}
-
-ULONG DirectShowPinEnum::Release()
-{
- ULONG ref = InterlockedDecrement(&m_ref);
-
- if (ref == 0) {
- delete this;
- }
-
- return ref;
-}
-
HRESULT DirectShowPinEnum::Next(ULONG cPins, IPin **ppPins, ULONG *pcFetched)
{
if (ppPins && (pcFetched || cPins == 1)) {
@@ -123,7 +114,10 @@ HRESULT DirectShowPinEnum::Reset()
HRESULT DirectShowPinEnum::Clone(IEnumPins **ppEnum)
{
if (ppEnum) {
- *ppEnum = new DirectShowPinEnum(m_pins);
+ if (m_filter)
+ *ppEnum = new DirectShowPinEnum(m_filter);
+ else
+ *ppEnum = new DirectShowPinEnum(m_pins);
return S_OK;
} else {
diff --git a/src/plugins/directshow/player/directshowpinenum.h b/src/plugins/directshow/helpers/directshowpinenum.h
index 8859f49a5..84c2a7579 100644
--- a/src/plugins/directshow/player/directshowpinenum.h
+++ b/src/plugins/directshow/helpers/directshowpinenum.h
@@ -43,27 +43,35 @@
#include <dshow.h>
#include <QtCore/qlist.h>
+#include "directshowpin.h"
+QT_USE_NAMESPACE
-class DirectShowPinEnum : public IEnumPins
+class DirectShowBaseFilter;
+
+class DirectShowPinEnum : public DirectShowObject
+ , public IEnumPins
{
+ DIRECTSHOW_OBJECT
+
public:
+ DirectShowPinEnum(DirectShowBaseFilter *filter);
DirectShowPinEnum(const QList<IPin *> &pins);
- virtual ~DirectShowPinEnum();
+ ~DirectShowPinEnum();
- // IUnknown
- HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);
- ULONG STDMETHODCALLTYPE AddRef();
- ULONG STDMETHODCALLTYPE Release();
+ // DirectShowObject
+ HRESULT getInterface(REFIID riid, void **ppvObject);
// IEnumPins
- HRESULT STDMETHODCALLTYPE Next(ULONG cPins, IPin **ppPins, ULONG *pcFetched);
- HRESULT STDMETHODCALLTYPE Skip(ULONG cPins);
- HRESULT STDMETHODCALLTYPE Reset();
- HRESULT STDMETHODCALLTYPE Clone(IEnumPins **ppEnum);
+ STDMETHODIMP Next(ULONG cPins, IPin **ppPins, ULONG *pcFetched);
+ STDMETHODIMP Skip(ULONG cPins);
+ STDMETHODIMP Reset();
+ STDMETHODIMP Clone(IEnumPins **ppEnum);
private:
- LONG m_ref;
+ Q_DISABLE_COPY(DirectShowPinEnum)
+
+ DirectShowBaseFilter *m_filter;
QList<IPin *> m_pins;
int m_index;
};
diff --git a/src/plugins/directshow/player/mediasamplevideobuffer.cpp b/src/plugins/directshow/helpers/directshowvideobuffer.cpp
index 58b146a89..3204e9f7e 100644
--- a/src/plugins/directshow/player/mediasamplevideobuffer.cpp
+++ b/src/plugins/directshow/helpers/directshowvideobuffer.cpp
@@ -37,9 +37,9 @@
**
****************************************************************************/
-#include "mediasamplevideobuffer.h"
+#include "directshowvideobuffer.h"
-MediaSampleVideoBuffer::MediaSampleVideoBuffer(IMediaSample *sample, int bytesPerLine)
+DirectShowVideoBuffer::DirectShowVideoBuffer(IMediaSample *sample, int bytesPerLine)
: QAbstractVideoBuffer(NoHandle)
, m_sample(sample)
, m_bytesPerLine(bytesPerLine)
@@ -48,12 +48,12 @@ MediaSampleVideoBuffer::MediaSampleVideoBuffer(IMediaSample *sample, int bytesPe
m_sample->AddRef();
}
-MediaSampleVideoBuffer::~MediaSampleVideoBuffer()
+DirectShowVideoBuffer::~DirectShowVideoBuffer()
{
m_sample->Release();
}
-uchar *MediaSampleVideoBuffer::map(MapMode mode, int *numBytes, int *bytesPerLine)
+uchar *DirectShowVideoBuffer::map(MapMode mode, int *numBytes, int *bytesPerLine)
{
if (m_mapMode == NotMapped && mode != NotMapped) {
if (numBytes)
@@ -73,12 +73,12 @@ uchar *MediaSampleVideoBuffer::map(MapMode mode, int *numBytes, int *bytesPerLin
return 0;
}
-void MediaSampleVideoBuffer::unmap()
+void DirectShowVideoBuffer::unmap()
{
m_mapMode = NotMapped;
}
-QAbstractVideoBuffer::MapMode MediaSampleVideoBuffer::mapMode() const
+QAbstractVideoBuffer::MapMode DirectShowVideoBuffer::mapMode() const
{
return m_mapMode;
}
diff --git a/src/plugins/directshow/player/mediasamplevideobuffer.h b/src/plugins/directshow/helpers/directshowvideobuffer.h
index 6ec1470c5..10089c75a 100644
--- a/src/plugins/directshow/player/mediasamplevideobuffer.h
+++ b/src/plugins/directshow/helpers/directshowvideobuffer.h
@@ -37,18 +37,18 @@
**
****************************************************************************/
-#ifndef MEDIASAMPLEVIDEOBUFFER_H
-#define MEDIASAMPLEVIDEOBUFFER_H
+#ifndef DIRECTSHOWVIDEOBUFFER_H
+#define DIRECTSHOWVIDEOBUFFER_H
#include <dshow.h>
#include <qabstractvideobuffer.h>
-class MediaSampleVideoBuffer : public QAbstractVideoBuffer
+class DirectShowVideoBuffer : public QAbstractVideoBuffer
{
public:
- MediaSampleVideoBuffer(IMediaSample *sample, int bytesPerLine);
- ~MediaSampleVideoBuffer();
+ DirectShowVideoBuffer(IMediaSample *sample, int bytesPerLine);
+ ~DirectShowVideoBuffer();
IMediaSample *sample() { return m_sample; }
diff --git a/src/plugins/directshow/helpers/helpers.pri b/src/plugins/directshow/helpers/helpers.pri
new file mode 100644
index 000000000..b3743a680
--- /dev/null
+++ b/src/plugins/directshow/helpers/helpers.pri
@@ -0,0 +1,22 @@
+INCLUDEPATH += $$PWD
+
+HEADERS += \
+ $$PWD/directshowbasefilter.h \
+ $$PWD/directshoweventloop.h \
+ $$PWD/directshowglobal.h \
+ $$PWD/directshowmediatype.h \
+ $$PWD/directshowmediatypeenum.h \
+ $$PWD/directshowobject.h \
+ $$PWD/directshowpin.h \
+ $$PWD/directshowpinenum.h \
+ $$PWD/directshowvideobuffer.h
+
+SOURCES += \
+ $$PWD/directshowbasefilter.cpp \
+ $$PWD/directshoweventloop.cpp \
+ $$PWD/directshowmediatype.cpp \
+ $$PWD/directshowmediatypeenum.cpp \
+ $$PWD/directshowobject.cpp \
+ $$PWD/directshowpin.cpp \
+ $$PWD/directshowpinenum.cpp \
+ $$PWD/directshowvideobuffer.cpp
diff --git a/src/plugins/directshow/player/directshowiosource.cpp b/src/plugins/directshow/player/directshowiosource.cpp
index fa17e51af..3c44dd1ed 100644
--- a/src/plugins/directshow/player/directshowiosource.cpp
+++ b/src/plugins/directshow/player/directshowiosource.cpp
@@ -41,6 +41,7 @@
#include "directshowglobal.h"
#include "directshowmediatype.h"
+#include "directshowmediatypeenum.h"
#include "directshowpinenum.h"
#include <QtCore/qcoreapplication.h>
@@ -81,7 +82,6 @@ DirectShowIOSource::DirectShowIOSource(DirectShowEventLoop *loop)
// The filter works in pull mode, the downstream filter is responsible for requesting
// samples from this one.
//
- QVector<AM_MEDIA_TYPE> mediaTypes;
AM_MEDIA_TYPE type =
{
MEDIATYPE_Stream, // majortype
@@ -99,10 +99,8 @@ DirectShowIOSource::DirectShowIOSource(DirectShowEventLoop *loop)
for (int i = 0; i < count; ++i) {
type.subtype = directshow_subtypes[i];
- mediaTypes.append(type);
+ m_supportedMediaTypes.append(type);
}
-
- setMediaTypes(mediaTypes);
}
DirectShowIOSource::~DirectShowIOSource()
@@ -377,24 +375,20 @@ HRESULT DirectShowIOSource::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt)
} else if (pmt && pmt->subtype == MEDIATYPE_NULL) { // - Partial type (Stream, but no subtype specified).
m_connectionMediaType = *pmt;
// Check if the receiving pin accepts any of the streaming subtypes.
- QVector<AM_MEDIA_TYPE>::const_iterator cit = m_mediaTypes.constBegin();
- while (cit != m_mediaTypes.constEnd()) {
- m_connectionMediaType.subtype = cit->subtype;
+ for (const DirectShowMediaType &t : qAsConst(m_supportedMediaTypes)) {
+ m_connectionMediaType.subtype = t.subtype;
hr = pReceivePin->ReceiveConnection(this, &m_connectionMediaType);
if (SUCCEEDED(hr))
break;
- ++cit;
}
} else { // - No media type specified.
// Check if the receiving pin accepts any of the streaming types.
- QVector<AM_MEDIA_TYPE>::const_iterator cit = m_mediaTypes.constBegin();
- while (cit != m_mediaTypes.constEnd()) {
- hr = pReceivePin->ReceiveConnection(this, cit);
+ for (const DirectShowMediaType &t : qAsConst(m_supportedMediaTypes)) {
+ hr = pReceivePin->ReceiveConnection(this, &t);
if (SUCCEEDED(hr)) {
- m_connectionMediaType = *cit;
+ m_connectionMediaType = t;
break;
}
- ++cit;
}
}
@@ -539,7 +533,7 @@ HRESULT DirectShowIOSource::EnumMediaTypes(IEnumMediaTypes **ppEnum)
if (!ppEnum) {
return E_POINTER;
} else {
- *ppEnum = createMediaTypeEnum();
+ *ppEnum = new DirectShowMediaTypeEnum(m_supportedMediaTypes);
return S_OK;
}
diff --git a/src/plugins/directshow/player/directshowiosource.h b/src/plugins/directshow/player/directshowiosource.h
index 3d5cd4dd7..702bfed61 100644
--- a/src/plugins/directshow/player/directshowiosource.h
+++ b/src/plugins/directshow/player/directshowiosource.h
@@ -43,13 +43,11 @@
#include "directshowglobal.h"
#include "directshowioreader.h"
#include "directshowmediatype.h"
-#include "directshowmediatypelist.h"
#include <QtCore/qfile.h>
class DirectShowIOSource
- : public DirectShowMediaTypeList
- , public IBaseFilter
+ : public IBaseFilter
, public IAMFilterMiscFlags
, public IPin
{
@@ -126,6 +124,7 @@ private:
IMemAllocator *m_allocator;
IPin *m_peerPin;
DirectShowMediaType m_connectionMediaType;
+ QList<DirectShowMediaType> m_supportedMediaTypes;
QString m_filterName;
const QString m_pinId;
bool m_queriedForAsyncReader;
diff --git a/src/plugins/directshow/player/directshowmediatypelist.cpp b/src/plugins/directshow/player/directshowmediatypelist.cpp
deleted file mode 100644
index 8d5e572ca..000000000
--- a/src/plugins/directshow/player/directshowmediatypelist.cpp
+++ /dev/null
@@ -1,228 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** 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 The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "directshowmediatypelist.h"
-
-#include "directshowmediatype.h"
-#include "videosurfacefilter.h"
-
-
-class DirectShowMediaTypeEnum : public IEnumMediaTypes
-{
-public:
- DirectShowMediaTypeEnum(DirectShowMediaTypeList *list, int token, int index = 0);
- virtual ~DirectShowMediaTypeEnum();
-
- // IUnknown
- HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);
- ULONG STDMETHODCALLTYPE AddRef();
- ULONG STDMETHODCALLTYPE Release();
-
- // IEnumMediaTypes
- HRESULT STDMETHODCALLTYPE Next(
- ULONG cMediaTypes, AM_MEDIA_TYPE **ppMediaTypes, ULONG *pcFetched);
- HRESULT STDMETHODCALLTYPE Skip(ULONG cMediaTypes);
- HRESULT STDMETHODCALLTYPE Reset();
-
- HRESULT STDMETHODCALLTYPE Clone(IEnumMediaTypes **ppEnum);
-
-private:
- LONG m_ref;
- DirectShowMediaTypeList *m_list;
- int m_mediaTypeToken;
- int m_index;
-};
-
-
-DirectShowMediaTypeEnum::DirectShowMediaTypeEnum(
- DirectShowMediaTypeList *list, int token, int index)
- : m_ref(1)
- , m_list(list)
- , m_mediaTypeToken(token)
- , m_index(index)
-{
- m_list->AddRef();
-}
-
-DirectShowMediaTypeEnum::~DirectShowMediaTypeEnum()
-{
- m_list->Release();
-}
-
-HRESULT DirectShowMediaTypeEnum::QueryInterface(REFIID riid, void **ppvObject)
-{
- if (!ppvObject) {
- return E_POINTER;
- } else if (riid == IID_IUnknown
- || riid == IID_IEnumMediaTypes) {
- *ppvObject = static_cast<IEnumMediaTypes *>(this);
- } else {
- *ppvObject = 0;
-
- return E_NOINTERFACE;
- }
-
- AddRef();
-
- return S_OK;
-}
-
-ULONG DirectShowMediaTypeEnum::AddRef()
-{
- return InterlockedIncrement(&m_ref);
-}
-
-ULONG DirectShowMediaTypeEnum::Release()
-{
- ULONG ref = InterlockedDecrement(&m_ref);
-
- if (ref == 0) {
- delete this;
- }
-
- return ref;
-}
-
-HRESULT DirectShowMediaTypeEnum::Next(
- ULONG cMediaTypes, AM_MEDIA_TYPE **ppMediaTypes, ULONG *pcFetched)
-{
- return m_list->nextMediaType(m_mediaTypeToken, &m_index, cMediaTypes, ppMediaTypes, pcFetched);
-}
-
-HRESULT DirectShowMediaTypeEnum::Skip(ULONG cMediaTypes)
-{
- return m_list->skipMediaType(m_mediaTypeToken, &m_index, cMediaTypes);
-}
-
-HRESULT DirectShowMediaTypeEnum::Reset()
-{
- m_mediaTypeToken = m_list->currentMediaTypeToken();
- m_index = 0;
-
- return S_OK;
-}
-
-HRESULT DirectShowMediaTypeEnum::Clone(IEnumMediaTypes **ppEnum)
-{
- return m_list->cloneMediaType(m_mediaTypeToken, m_index, ppEnum);
-}
-
-
-DirectShowMediaTypeList::DirectShowMediaTypeList()
- : m_mediaTypeToken(0)
-{
-}
-
-DirectShowMediaTypeList::~DirectShowMediaTypeList()
-{
-}
-
-IEnumMediaTypes *DirectShowMediaTypeList::createMediaTypeEnum()
-{
- return new DirectShowMediaTypeEnum(this, m_mediaTypeToken, 0);
-}
-
-
-void DirectShowMediaTypeList::setMediaTypes(const QVector<AM_MEDIA_TYPE> &types)
-{
- ++m_mediaTypeToken;
-
- m_mediaTypes = types;
-}
-
-
-int DirectShowMediaTypeList::currentMediaTypeToken()
-{
- return m_mediaTypeToken;
-}
-
-HRESULT DirectShowMediaTypeList::nextMediaType(
- int token, int *index, ULONG count, AM_MEDIA_TYPE **types, ULONG *fetchedCount)
-{
- if (!types || (count != 1 && !fetchedCount)) {
- return E_POINTER;
- } else if (m_mediaTypeToken != token) {
- return VFW_E_ENUM_OUT_OF_SYNC;
- } else {
- int boundedCount = qBound<int>(0, count, m_mediaTypes.count() - *index);
-
- for (int i = 0; i < boundedCount; ++i, ++(*index)) {
- types[i] = reinterpret_cast<AM_MEDIA_TYPE *>(CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE)));
-
- if (types[i]) {
- DirectShowMediaType::copy(types[i], m_mediaTypes.at(*index));
- } else {
- for (--i; i >= 0; --i)
- CoTaskMemFree(types[i]);
-
- if (fetchedCount)
- *fetchedCount = 0;
-
- return E_OUTOFMEMORY;
- }
- }
- if (fetchedCount)
- *fetchedCount = boundedCount;
-
- return boundedCount == int(count) ? S_OK : S_FALSE;
- }
-}
-
-HRESULT DirectShowMediaTypeList::skipMediaType(int token, int *index, ULONG count)
-{
- if (m_mediaTypeToken != token) {
- return VFW_E_ENUM_OUT_OF_SYNC;
- } else {
- *index = qMin<int>(*index + count, m_mediaTypes.size());
-
- return *index < m_mediaTypes.size() ? S_OK : S_FALSE;
- }
-}
-
-HRESULT DirectShowMediaTypeList::cloneMediaType(int token, int index, IEnumMediaTypes **enumeration)
-{
- if (m_mediaTypeToken != token) {
- return VFW_E_ENUM_OUT_OF_SYNC;
- } else {
- *enumeration = new DirectShowMediaTypeEnum(this, token, index);
-
- return S_OK;
- }
-}
-
diff --git a/src/plugins/directshow/player/directshowplayercontrol.cpp b/src/plugins/directshow/player/directshowplayercontrol.cpp
index d4fd0c8be..fce488af2 100644
--- a/src/plugins/directshow/player/directshowplayercontrol.cpp
+++ b/src/plugins/directshow/player/directshowplayercontrol.cpp
@@ -45,21 +45,7 @@
#include <QtCore/qcoreapplication.h>
#include <QtCore/qmath.h>
-
-static int volumeToDecibels(int volume)
-{
- if (volume == 0) {
- return -10000;
- } else if (volume == 100) {
- return 0;
-#ifdef QT_USE_MATH_H_FLOATS
- } else if (sizeof(qreal) == sizeof(float)) {
- return qRound(::log10f(float(volume) / 100) * 5000);
-#endif
- } else {
- return qRound(::log10(qreal(volume) / 100) * 5000);
- }
-}
+#include <qaudio.h>
DirectShowPlayerControl::DirectShowPlayerControl(DirectShowPlayerService *service, QObject *parent)
: QMediaPlayerControl(parent)
@@ -168,7 +154,18 @@ void DirectShowPlayerControl::setVolumeHelper(int volume)
if (!m_audio)
return;
- m_audio->put_Volume(volumeToDecibels(volume));
+ long adjustedVolume;
+ if (volume == 0) {
+ adjustedVolume = -10000; // -100 dB (lower limit for put_Volume())
+ } else if (volume == 100) {
+ adjustedVolume = 0;
+ } else {
+ adjustedVolume = QAudio::convertVolume(volume / qreal(100),
+ QAudio::LinearVolumeScale,
+ QAudio::DecibelVolumeScale) * 100;
+ }
+
+ m_audio->put_Volume(adjustedVolume);
}
int DirectShowPlayerControl::bufferStatus() const
diff --git a/src/plugins/directshow/player/directshowplayerservice.cpp b/src/plugins/directshow/player/directshowplayerservice.cpp
index ccc25d30b..1502c6df3 100644
--- a/src/plugins/directshow/player/directshowplayerservice.cpp
+++ b/src/plugins/directshow/player/directshowplayerservice.cpp
@@ -47,11 +47,9 @@
#include "directshowplayerservice.h"
-#ifndef Q_OS_WINCE
#include "directshowaudioendpointcontrol.h"
#include "directshowmetadatacontrol.h"
#include "vmr9videowindowcontrol.h"
-#endif
#include "directshowiosource.h"
#include "directshowplayercontrol.h"
#include "directshowvideorenderercontrol.h"
@@ -111,14 +109,10 @@ private:
DirectShowPlayerService::DirectShowPlayerService(QObject *parent)
: QMediaService(parent)
, m_playerControl(0)
-#ifndef Q_OS_WINCE
, m_metaDataControl(0)
-#endif
, m_videoRendererControl(0)
-#ifndef Q_OS_WINCE
, m_videoWindowControl(0)
, m_audioEndpointControl(0)
-#endif
, m_taskThread(0)
, m_loop(qt_directShowEventLoop())
, m_pendingTasks(0)
@@ -142,10 +136,8 @@ DirectShowPlayerService::DirectShowPlayerService(QObject *parent)
, m_dontCacheNextSeekResult(false)
{
m_playerControl = new DirectShowPlayerControl(this);
-#ifndef Q_OS_WINCE
m_metaDataControl = new DirectShowMetaDataControl(this);
m_audioEndpointControl = new DirectShowAudioEndpointControl(this);
-#endif
m_taskThread = new DirectShowPlayerServiceThread(this);
m_taskThread->start();
@@ -176,14 +168,10 @@ DirectShowPlayerService::~DirectShowPlayerService()
}
delete m_playerControl;
-#ifndef Q_OS_WINCE
delete m_audioEndpointControl;
delete m_metaDataControl;
-#endif
delete m_videoRendererControl;
-#ifndef Q_OS_WINCE
delete m_videoWindowControl;
-#endif
::CloseHandle(m_taskHandle);
}
@@ -192,18 +180,12 @@ QMediaControl *DirectShowPlayerService::requestControl(const char *name)
{
if (qstrcmp(name, QMediaPlayerControl_iid) == 0) {
return m_playerControl;
-#ifndef Q_OS_WINCE
} else if (qstrcmp(name, QAudioOutputSelectorControl_iid) == 0) {
return m_audioEndpointControl;
} else if (qstrcmp(name, QMetaDataReaderControl_iid) == 0) {
return m_metaDataControl;
-#endif
} else if (qstrcmp(name, QVideoRendererControl_iid) == 0) {
- if (!m_videoRendererControl
-#ifndef Q_OS_WINCE
- && !m_videoWindowControl
-#endif
- ){
+ if (!m_videoRendererControl && !m_videoWindowControl) {
m_videoRendererControl = new DirectShowVideoRendererControl(m_loop);
connect(m_videoRendererControl, SIGNAL(filterChanged()),
@@ -211,7 +193,6 @@ QMediaControl *DirectShowPlayerService::requestControl(const char *name)
return m_videoRendererControl;
}
-#ifndef Q_OS_WINCE
} else if (qstrcmp(name, QVideoWindowControl_iid) == 0) {
if (!m_videoRendererControl && !m_videoWindowControl) {
IBaseFilter *filter;
@@ -234,7 +215,6 @@ QMediaControl *DirectShowPlayerService::requestControl(const char *name)
return m_videoWindowControl;
}
-#endif
}
return 0;
}
@@ -250,14 +230,12 @@ void DirectShowPlayerService::releaseControl(QMediaControl *control)
delete m_videoRendererControl;
m_videoRendererControl = 0;
-#ifndef Q_OS_WINCE
} else if (control == m_videoWindowControl) {
setVideoOutput(0);
delete m_videoWindowControl;
m_videoWindowControl = 0;
-#endif
}
}
@@ -283,9 +261,7 @@ void DirectShowPlayerService::load(const QMediaContent &media, QIODevice *stream
m_seekable = false;
m_atEnd = false;
m_dontCacheNextSeekResult = false;
-#ifndef Q_OS_WINCE
m_metaDataControl->reset();
-#endif
if (m_resources.isEmpty() && !stream) {
m_pendingTasks = 0;
@@ -1188,9 +1164,7 @@ void DirectShowPlayerService::customEvent(QEvent *event)
QMutexLocker locker(&m_mutex);
m_playerControl->updateMediaInfo(m_duration, m_streamTypes, m_seekable);
-#ifndef Q_OS_WINCE
m_metaDataControl->updateMetadata(m_graph, m_source, m_url.toString());
-#endif
updateStatus();
} else if (event->type() == QEvent::Type(Error)) {
diff --git a/src/plugins/directshow/player/directshowplayerservice.h b/src/plugins/directshow/player/directshowplayerservice.h
index 9419a8a99..b8d30e79a 100644
--- a/src/plugins/directshow/player/directshowplayerservice.h
+++ b/src/plugins/directshow/player/directshowplayerservice.h
@@ -176,14 +176,10 @@ private:
};
DirectShowPlayerControl *m_playerControl;
-#ifndef Q_OS_WINCE
DirectShowMetaDataControl *m_metaDataControl;
-#endif
DirectShowVideoRendererControl *m_videoRendererControl;
-#ifndef Q_OS_WINCE
QVideoWindowControl *m_videoWindowControl;
DirectShowAudioEndpointControl *m_audioEndpointControl;
-#endif
QThread *m_taskThread;
DirectShowEventLoop *m_loop;
diff --git a/src/plugins/directshow/player/directshowsamplescheduler.cpp b/src/plugins/directshow/player/directshowsamplescheduler.cpp
deleted file mode 100644
index 0aa257f7f..000000000
--- a/src/plugins/directshow/player/directshowsamplescheduler.cpp
+++ /dev/null
@@ -1,435 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** 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 The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "directshowsamplescheduler.h"
-
-#include <QtCore/qcoreapplication.h>
-#include <QtCore/qcoreevent.h>
-
-class DirectShowTimedSample
-{
-public:
- DirectShowTimedSample(IMediaSample *sample)
- : m_next(0)
- , m_sample(sample)
- , m_cookie(0)
- , m_lastSample(false)
- {
- m_sample->AddRef();
- }
-
- ~DirectShowTimedSample()
- {
- m_sample->Release();
- }
-
- IMediaSample *sample() const { return m_sample; }
-
- DirectShowTimedSample *nextSample() const { return m_next; }
- void setNextSample(DirectShowTimedSample *sample) { Q_ASSERT(!m_next); m_next = sample; }
-
- DirectShowTimedSample *remove() {
- DirectShowTimedSample *next = m_next; delete this; return next; }
-
- bool schedule(IReferenceClock *clock, REFERENCE_TIME startTime, HANDLE handle);
- void unschedule(IReferenceClock *clock);
-
- bool isReady(IReferenceClock *clock) const;
-
- bool isLast() const { return m_lastSample; }
- void setLast() { m_lastSample = true; }
-
-private:
- DirectShowTimedSample *m_next;
- IMediaSample *m_sample;
- DWORD_PTR m_cookie;
- bool m_lastSample;
-};
-
-bool DirectShowTimedSample::schedule(
- IReferenceClock *clock, REFERENCE_TIME startTime, HANDLE handle)
-{
- REFERENCE_TIME sampleStartTime;
- REFERENCE_TIME sampleEndTime;
- if (m_sample->GetTime(&sampleStartTime, &sampleEndTime) == S_OK) {
- if (clock->AdviseTime(
- startTime, sampleStartTime, reinterpret_cast<HEVENT>(handle), &m_cookie) == S_OK) {
- return true;
- }
- }
- return false;
-}
-
-void DirectShowTimedSample::unschedule(IReferenceClock *clock)
-{
- clock->Unadvise(m_cookie);
-}
-
-bool DirectShowTimedSample::isReady(IReferenceClock *clock) const
-{
- REFERENCE_TIME sampleStartTime;
- REFERENCE_TIME sampleEndTime;
- REFERENCE_TIME currentTime;
- if (m_sample->GetTime(&sampleStartTime, &sampleEndTime) == S_OK) {
- if (clock->GetTime(&currentTime) == S_OK)
- return currentTime >= sampleStartTime;
- }
- return true;
-}
-
-DirectShowSampleScheduler::DirectShowSampleScheduler(IUnknown *pin, QObject *parent)
- : QObject(parent)
- , m_pin(pin)
- , m_clock(0)
- , m_allocator(0)
- , m_head(0)
- , m_tail(0)
- , m_maximumSamples(1)
- , m_state(Stopped)
- , m_startTime(0)
- , m_timeoutEvent(::CreateEvent(0, 0, 0, 0))
- , m_flushEvent(::CreateEvent(0, 0, 0, 0))
-{
- m_semaphore.release(m_maximumSamples);
-}
-
-DirectShowSampleScheduler::~DirectShowSampleScheduler()
-{
- ::CloseHandle(m_timeoutEvent);
- ::CloseHandle(m_flushEvent);
-
- Q_ASSERT(!m_clock);
- Q_ASSERT(!m_allocator);
-}
-
-HRESULT DirectShowSampleScheduler::QueryInterface(REFIID riid, void **ppvObject)
-{
- return m_pin->QueryInterface(riid, ppvObject);
-}
-
-ULONG DirectShowSampleScheduler::AddRef()
-{
- return m_pin->AddRef();
-}
-
-ULONG DirectShowSampleScheduler::Release()
-{
- return m_pin->Release();
-}
-
-// IMemInputPin
-HRESULT DirectShowSampleScheduler::GetAllocator(IMemAllocator **ppAllocator)
-{
- if (!ppAllocator) {
- return E_POINTER;
- } else {
- QMutexLocker locker(&m_mutex);
-
- if (!m_allocator) {
- return VFW_E_NO_ALLOCATOR;
- } else {
- *ppAllocator = m_allocator;
-
- return S_OK;
- }
- }
-}
-
-HRESULT DirectShowSampleScheduler::NotifyAllocator(IMemAllocator *pAllocator, BOOL bReadOnly)
-{
- Q_UNUSED(bReadOnly);
-
- HRESULT hr;
- ALLOCATOR_PROPERTIES properties;
-
- if (!pAllocator) {
- if (m_allocator)
- m_allocator->Release();
-
- m_allocator = 0;
-
- return S_OK;
- } else if ((hr = pAllocator->GetProperties(&properties)) != S_OK) {
- return hr;
- } else {
- if (properties.cBuffers == 1) {
- ALLOCATOR_PROPERTIES actual;
-
- properties.cBuffers = 2;
- if ((hr = pAllocator->SetProperties(&properties, &actual)) != S_OK)
- return hr;
- }
-
- QMutexLocker locker(&m_mutex);
-
- if (m_allocator)
- m_allocator->Release();
-
- m_allocator = pAllocator;
- m_allocator->AddRef();
-
- return S_OK;
- }
-}
-
-HRESULT DirectShowSampleScheduler::GetAllocatorRequirements(ALLOCATOR_PROPERTIES *pProps)
-{
- if (!pProps)
- return E_POINTER;
-
- pProps->cBuffers = 2;
-
- return S_OK;
-}
-
-HRESULT DirectShowSampleScheduler::Receive(IMediaSample *pSample)
-{
- if (!pSample)
- return E_POINTER;
-
- m_semaphore.acquire(1);
-
- QMutexLocker locker(&m_mutex);
-
- if (m_state & Flushing) {
- m_semaphore.release(1);
-
- return S_FALSE;
- } else if (m_state == Stopped) {
- m_semaphore.release();
-
- return VFW_E_WRONG_STATE;
- } else {
- DirectShowTimedSample *timedSample = new DirectShowTimedSample(pSample);
-
- if (m_tail)
- m_tail->setNextSample(timedSample);
- else
- m_head = timedSample;
-
- m_tail = timedSample;
-
- if (m_state == Running) {
- if (!timedSample->schedule(m_clock, m_startTime, m_timeoutEvent)) {
- // Timing information is unavailable, so schedule frames immediately.
- QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
- } else {
- locker.unlock();
- HANDLE handles[] = { m_flushEvent, m_timeoutEvent };
- DWORD result = ::WaitForMultipleObjects(2, handles, FALSE, INFINITE);
- locker.relock();
-
- if (result == WAIT_OBJECT_0 + 1)
- QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
- }
- } else if (m_tail == m_head) {
- // If this is the first frame make it available.
- QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
-
- if (m_state == Paused) {
- ::ResetEvent(m_timeoutEvent);
-
- locker.unlock();
- HANDLE handles[] = { m_flushEvent, m_timeoutEvent };
- ::WaitForMultipleObjects(2, handles, FALSE, INFINITE);
- locker.relock();
- }
- }
-
- return S_OK;
- }
-}
-
-HRESULT DirectShowSampleScheduler::ReceiveMultiple(
- IMediaSample **pSamples, long nSamples, long *nSamplesProcessed)
-{
- if (!pSamples || !nSamplesProcessed)
- return E_POINTER;
-
- for (*nSamplesProcessed = 0; *nSamplesProcessed < nSamples; ++(*nSamplesProcessed)) {
- HRESULT hr = Receive(pSamples[*nSamplesProcessed]);
-
- if (hr != S_OK)
- return hr;
- }
- return S_OK;
-}
-
-HRESULT DirectShowSampleScheduler::ReceiveCanBlock()
-{
- return S_OK;
-}
-
-void DirectShowSampleScheduler::run(REFERENCE_TIME startTime)
-{
- QMutexLocker locker(&m_mutex);
-
- m_state = (m_state & Flushing) | Running;
- m_startTime = startTime;
-
- for (DirectShowTimedSample *sample = m_head; sample; sample = sample->nextSample()) {
- sample->schedule(m_clock, m_startTime, m_timeoutEvent);
- }
-
- if (!(m_state & Flushing))
- ::ResetEvent(m_flushEvent);
-
- if (!m_head)
- ::SetEvent(m_timeoutEvent);
-
-}
-
-void DirectShowSampleScheduler::pause()
-{
- QMutexLocker locker(&m_mutex);
-
- m_state = (m_state & Flushing) | Paused;
-
- for (DirectShowTimedSample *sample = m_head; sample; sample = sample->nextSample())
- sample->unschedule(m_clock);
-
- if (!(m_state & Flushing))
- ::ResetEvent(m_flushEvent);
-}
-
-void DirectShowSampleScheduler::stop()
-{
- QMutexLocker locker(&m_mutex);
-
- m_state = m_state & Flushing;
-
- for (DirectShowTimedSample *sample = m_head; sample; sample = sample->remove()) {
- sample->unschedule(m_clock);
-
- m_semaphore.release(1);
- }
-
- m_head = 0;
- m_tail = 0;
-
- ::SetEvent(m_flushEvent);
-}
-
-void DirectShowSampleScheduler::setFlushing(bool flushing)
-{
- QMutexLocker locker(&m_mutex);
-
- const bool isFlushing = m_state & Flushing;
-
- if (isFlushing != flushing) {
- if (flushing) {
- m_state |= Flushing;
-
- for (DirectShowTimedSample *sample = m_head; sample; sample = sample->remove()) {
- sample->unschedule(m_clock);
-
- m_semaphore.release(1);
- }
- m_head = 0;
- m_tail = 0;
-
- ::SetEvent(m_flushEvent);
- } else {
- m_state &= ~Flushing;
-
- if (m_state != Stopped)
- ::ResetEvent(m_flushEvent);
- }
- }
-}
-
-void DirectShowSampleScheduler::setClock(IReferenceClock *clock)
-{
- QMutexLocker locker(&m_mutex);
-
- if (m_clock)
- m_clock->Release();
-
- m_clock = clock;
-
- if (m_clock)
- m_clock->AddRef();
-}
-
-IMediaSample *DirectShowSampleScheduler::takeSample(bool *eos)
-{
- QMutexLocker locker(&m_mutex);
-
- if (m_head && m_head->isReady(m_clock)) {
- IMediaSample *sample = m_head->sample();
- sample->AddRef();
-
- *eos = m_head->isLast();
-
- m_head = m_head->remove();
-
- if (!m_head)
- m_tail = 0;
-
- m_semaphore.release(1);
-
- return sample;
- } else {
- return 0;
- }
-}
-
-bool DirectShowSampleScheduler::scheduleEndOfStream()
-{
- QMutexLocker locker(&m_mutex);
-
- if (m_tail) {
- m_tail->setLast();
-
- return true;
- } else {
- return false;
- }
-}
-
-bool DirectShowSampleScheduler::event(QEvent *event)
-{
- if (event->type() == QEvent::UpdateRequest) {
- emit sampleReady();
-
- return true;
- } else {
- return QObject::event(event);
- }
-}
diff --git a/src/plugins/directshow/player/directshowsamplescheduler.h b/src/plugins/directshow/player/directshowsamplescheduler.h
deleted file mode 100644
index 1670d23ed..000000000
--- a/src/plugins/directshow/player/directshowsamplescheduler.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** 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 The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef DIRECTSHOWSAMPLESCHEDULER_H
-#define DIRECTSHOWSAMPLESCHEDULER_H
-
-#include <dshow.h>
-
-#include <QtCore/qmutex.h>
-#include <QtCore/qobject.h>
-#include <QtCore/qsemaphore.h>
-
-class DirectShowTimedSample;
-
-class DirectShowSampleScheduler : public QObject, public IMemInputPin
-{
- Q_OBJECT
-public:
-
- enum State
- {
- Stopped = 0x00,
- Running = 0x01,
- Paused = 0x02,
- RunMask = 0x03,
- Flushing = 0x04
- };
-
- DirectShowSampleScheduler(IUnknown *pin, QObject *parent = 0);
- ~DirectShowSampleScheduler();
-
- // IUnknown
- HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);
- ULONG STDMETHODCALLTYPE AddRef();
- ULONG STDMETHODCALLTYPE Release();
-
- // IMemInputPin
- HRESULT STDMETHODCALLTYPE GetAllocator(IMemAllocator **ppAllocator);
- HRESULT STDMETHODCALLTYPE NotifyAllocator(IMemAllocator *pAllocator, BOOL bReadOnly);
- HRESULT STDMETHODCALLTYPE GetAllocatorRequirements(ALLOCATOR_PROPERTIES *pProps);
-
- HRESULT STDMETHODCALLTYPE Receive(IMediaSample *pSample);
- HRESULT STDMETHODCALLTYPE ReceiveMultiple(IMediaSample **pSamples, long nSamples, long *nSamplesProcessed);
- HRESULT STDMETHODCALLTYPE ReceiveCanBlock();
-
- void run(REFERENCE_TIME startTime);
- void pause();
- void stop();
- void setFlushing(bool flushing);
-
- IReferenceClock *clock() const { return m_clock; }
- void setClock(IReferenceClock *clock);
-
- bool schedule(IMediaSample *sample);
- bool scheduleEndOfStream();
-
- IMediaSample *takeSample(bool *eos);
-
- bool event(QEvent *event);
-
-Q_SIGNALS:
- void sampleReady();
-
-private:
- IUnknown *m_pin;
- IReferenceClock *m_clock;
- IMemAllocator *m_allocator;
- DirectShowTimedSample *m_head;
- DirectShowTimedSample *m_tail;
- int m_maximumSamples;
- int m_state;
- REFERENCE_TIME m_startTime;
- HANDLE m_timeoutEvent;
- HANDLE m_flushEvent;
- QSemaphore m_semaphore;
- QMutex m_mutex;
-};
-
-#endif
diff --git a/src/plugins/directshow/player/player.pri b/src/plugins/directshow/player/player.pri
index c5fb8442a..8b4bb70b7 100644
--- a/src/plugins/directshow/player/player.pri
+++ b/src/plugins/directshow/player/player.pri
@@ -1,7 +1,6 @@
INCLUDEPATH += $$PWD
-LIBS += -lstrmiids -ldmoguids -luuid -lole32 -loleaut32
-!wince: LIBS += -lmsdmo -lgdi32
+LIBS += -lstrmiids -ldmoguids -luuid -lole32 -loleaut32 -lmsdmo -lgdi32
qtHaveModule(widgets): QT += widgets
@@ -9,45 +8,26 @@ qtHaveModule(widgets): QT += widgets
DEFINES += QMEDIA_DIRECTSHOW_PLAYER
HEADERS += \
- $$PWD/directshoweventloop.h \
- $$PWD/directshowglobal.h \
$$PWD/directshowioreader.h \
$$PWD/directshowiosource.h \
- $$PWD/directshowmediatype.h \
- $$PWD/directshowmediatypelist.h \
- $$PWD/directshowpinenum.h \
$$PWD/directshowplayercontrol.h \
$$PWD/directshowplayerservice.h \
- $$PWD/directshowsamplescheduler.h \
$$PWD/directshowvideorenderercontrol.h \
- $$PWD/mediasamplevideobuffer.h \
- $$PWD/videosurfacefilter.h
+ $$PWD/videosurfacefilter.h \
+ $$PWD/directshowaudioendpointcontrol.h \
+ $$PWD/directshowmetadatacontrol.h \
+ $$PWD/vmr9videowindowcontrol.h
SOURCES += \
- $$PWD/directshoweventloop.cpp \
$$PWD/directshowioreader.cpp \
$$PWD/directshowiosource.cpp \
- $$PWD/directshowmediatype.cpp \
- $$PWD/directshowmediatypelist.cpp \
- $$PWD/directshowpinenum.cpp \
$$PWD/directshowplayercontrol.cpp \
$$PWD/directshowplayerservice.cpp \
- $$PWD/directshowsamplescheduler.cpp \
$$PWD/directshowvideorenderercontrol.cpp \
- $$PWD/mediasamplevideobuffer.cpp \
- $$PWD/videosurfacefilter.cpp
-
-!wince {
-HEADERS += \
- $$PWD/directshowaudioendpointcontrol.h \
- $$PWD/directshowmetadatacontrol.h \
- $$PWD/vmr9videowindowcontrol.h
-
-SOURCES += \
+ $$PWD/videosurfacefilter.cpp \
$$PWD/directshowaudioendpointcontrol.cpp \
$$PWD/directshowmetadatacontrol.cpp \
$$PWD/vmr9videowindowcontrol.cpp
-}
config_evr {
DEFINES += HAVE_EVR
diff --git a/src/plugins/directshow/player/videosurfacefilter.cpp b/src/plugins/directshow/player/videosurfacefilter.cpp
index b7b0d3aa8..4cb97be39 100644
--- a/src/plugins/directshow/player/videosurfacefilter.cpp
+++ b/src/plugins/directshow/player/videosurfacefilter.cpp
@@ -41,226 +41,220 @@
#include "directshoweventloop.h"
#include "directshowglobal.h"
-#include "directshowpinenum.h"
-#include "mediasamplevideobuffer.h"
+#include "directshowvideobuffer.h"
-#include <QtCore/qcoreapplication.h>
-#include <QtCore/qcoreevent.h>
#include <QtCore/qthread.h>
+#include <QtCore/qloggingcategory.h>
#include <qabstractvideosurface.h>
#include <initguid.h>
+Q_LOGGING_CATEGORY(qLcRenderFilter, "qt.multimedia.plugins.directshow.renderfilter")
+
// { e23cad72-153d-406c-bf3f-4c4b523d96f2 }
DEFINE_GUID(CLSID_VideoSurfaceFilter,
0xe23cad72, 0x153d, 0x406c, 0xbf, 0x3f, 0x4c, 0x4b, 0x52, 0x3d, 0x96, 0xf2);
-VideoSurfaceFilter::VideoSurfaceFilter(
- QAbstractVideoSurface *surface, DirectShowEventLoop *loop, QObject *parent)
- : QObject(parent)
- , m_ref(1)
- , m_state(State_Stopped)
- , m_surface(surface)
- , m_loop(loop)
- , m_graph(0)
- , m_peerPin(0)
- , m_bytesPerLine(0)
- , m_startResult(S_OK)
- , m_pinId(QString::fromLatin1("reference"))
- , m_sampleScheduler(static_cast<IPin *>(this))
+class VideoSurfaceInputPin : public DirectShowInputPin
{
- connect(surface, SIGNAL(supportedFormatsChanged()), this, SLOT(supportedFormatsChanged()));
- connect(&m_sampleScheduler, SIGNAL(sampleReady()), this, SLOT(sampleReady()));
-}
+ DIRECTSHOW_OBJECT
-VideoSurfaceFilter::~VideoSurfaceFilter()
-{
- Q_ASSERT(m_ref == 0);
-}
+public:
+ VideoSurfaceInputPin(VideoSurfaceFilter *filter);
-HRESULT VideoSurfaceFilter::QueryInterface(REFIID riid, void **ppvObject)
-{
- // 2dd74950-a890-11d1-abe8-00a0c905f375
- static const GUID iid_IAmFilterMiscFlags = {
- 0x2dd74950, 0xa890, 0x11d1, {0xab, 0xe8, 0x00, 0xa0, 0xc9, 0x05, 0xf3, 0x75} };
+ // DirectShowPin
+ bool isMediaTypeSupported(const DirectShowMediaType *type);
+ bool setMediaType(const DirectShowMediaType *type);
- if (!ppvObject) {
- return E_POINTER;
- } else if (riid == IID_IUnknown
- || riid == IID_IPersist
- || riid == IID_IMediaFilter
- || riid == IID_IBaseFilter) {
- *ppvObject = static_cast<IBaseFilter *>(this);
- } else if (riid == iid_IAmFilterMiscFlags) {
- *ppvObject = static_cast<IAMFilterMiscFlags *>(this);
- } else if (riid == IID_IPin) {
- *ppvObject = static_cast<IPin *>(this);
- } else if (riid == IID_IMemInputPin) {
- *ppvObject = static_cast<IMemInputPin *>(&m_sampleScheduler);
- } else {
- *ppvObject = 0;
+ HRESULT completeConnection(IPin *pin);
+ HRESULT connectionEnded();
- return E_NOINTERFACE;
- }
+ // IPin
+ STDMETHODIMP ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt);
+ STDMETHODIMP Disconnect();
+ STDMETHODIMP EndOfStream();
+ STDMETHODIMP BeginFlush();
+ STDMETHODIMP EndFlush();
- AddRef();
+ // IMemInputPin
+ STDMETHODIMP GetAllocatorRequirements(ALLOCATOR_PROPERTIES *pProps);
+ STDMETHODIMP Receive(IMediaSample *pMediaSample);
- return S_OK;
+private:
+ VideoSurfaceFilter *m_videoSurfaceFilter;
+};
+
+VideoSurfaceInputPin::VideoSurfaceInputPin(VideoSurfaceFilter *filter)
+ : DirectShowInputPin(filter, QStringLiteral("Input"))
+ , m_videoSurfaceFilter(filter)
+{
}
-ULONG VideoSurfaceFilter::AddRef()
+bool VideoSurfaceInputPin::isMediaTypeSupported(const DirectShowMediaType *type)
{
- return InterlockedIncrement(&m_ref);
+ return m_videoSurfaceFilter->isMediaTypeSupported(type);
}
-ULONG VideoSurfaceFilter::Release()
+bool VideoSurfaceInputPin::setMediaType(const DirectShowMediaType *type)
{
- ULONG ref = InterlockedDecrement(&m_ref);
- if (ref == 0)
- delete this;
+ if (!DirectShowInputPin::setMediaType(type))
+ return false;
- return ref;
+ return m_videoSurfaceFilter->setMediaType(type);
}
-HRESULT VideoSurfaceFilter::GetClassID(CLSID *pClassID)
+HRESULT VideoSurfaceInputPin::completeConnection(IPin *pin)
{
- *pClassID = CLSID_VideoSurfaceFilter;
+ HRESULT hr = DirectShowInputPin::completeConnection(pin);
+ if (FAILED(hr))
+ return hr;
- return S_OK;
+ return m_videoSurfaceFilter->completeConnection(pin);
}
-HRESULT VideoSurfaceFilter::Run(REFERENCE_TIME tStart)
+HRESULT VideoSurfaceInputPin::connectionEnded()
{
- m_state = State_Running;
-
- m_sampleScheduler.run(tStart);
+ HRESULT hr = DirectShowInputPin::connectionEnded();
+ if (FAILED(hr))
+ return hr;
- return S_OK;
+ return m_videoSurfaceFilter->connectionEnded();
}
-HRESULT VideoSurfaceFilter::Pause()
+HRESULT VideoSurfaceInputPin::ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt)
{
- m_state = State_Paused;
-
- m_sampleScheduler.pause();
+ QMutexLocker lock(&m_videoSurfaceFilter->m_mutex);
+ return DirectShowInputPin::ReceiveConnection(pConnector, pmt);
+}
- return S_OK;
+HRESULT VideoSurfaceInputPin::Disconnect()
+{
+ QMutexLocker lock(&m_videoSurfaceFilter->m_mutex);
+ return DirectShowInputPin::Disconnect();
}
-HRESULT VideoSurfaceFilter::Stop()
+HRESULT VideoSurfaceInputPin::EndOfStream()
{
- m_state = State_Stopped;
+ QMutexLocker lock(&m_videoSurfaceFilter->m_mutex);
+ QMutexLocker renderLock(&m_videoSurfaceFilter->m_renderMutex);
- m_sampleScheduler.stop();
+ HRESULT hr = DirectShowInputPin::EndOfStream();
+ if (hr != S_OK)
+ return hr;
- if (thread() == QThread::currentThread()) {
- flush();
- } else {
- QMutexLocker locker(&m_mutex);
- m_loop->postEvent(this, new QEvent(QEvent::Type(FlushSurface)));
- m_wait.wait(&m_mutex);
+ return m_videoSurfaceFilter->EndOfStream();
+}
+
+HRESULT VideoSurfaceInputPin::BeginFlush()
+{
+ QMutexLocker lock(&m_videoSurfaceFilter->m_mutex);
+ {
+ QMutexLocker renderLock(&m_videoSurfaceFilter->m_renderMutex);
+ DirectShowInputPin::BeginFlush();
+ m_videoSurfaceFilter->BeginFlush();
}
+ m_videoSurfaceFilter->resetEOS();
return S_OK;
}
-HRESULT VideoSurfaceFilter::GetState(DWORD dwMilliSecsTimeout, FILTER_STATE *pState)
+HRESULT VideoSurfaceInputPin::EndFlush()
{
- Q_UNUSED(dwMilliSecsTimeout)
- if (!pState)
- return E_POINTER;
-
- *pState = m_state;
+ QMutexLocker lock(&m_videoSurfaceFilter->m_mutex);
+ QMutexLocker renderLock(&m_videoSurfaceFilter->m_renderMutex);
- return S_OK;
+ HRESULT hr = m_videoSurfaceFilter->EndFlush();
+ if (SUCCEEDED(hr))
+ hr = DirectShowInputPin::EndFlush();
+ return hr;
}
-HRESULT VideoSurfaceFilter::SetSyncSource(IReferenceClock *pClock)
+HRESULT VideoSurfaceInputPin::GetAllocatorRequirements(ALLOCATOR_PROPERTIES *pProps)
{
+ if (!pProps)
+ return E_POINTER;
- m_sampleScheduler.setClock(pClock);
+ // We need at least two allocated buffers, one for holding the frame currently being
+ // rendered and another one to decode the following frame at the same time.
+ pProps->cBuffers = 2;
return S_OK;
}
-HRESULT VideoSurfaceFilter::GetSyncSource(IReferenceClock **ppClock)
+HRESULT VideoSurfaceInputPin::Receive(IMediaSample *pMediaSample)
{
- if (!ppClock) {
- return E_POINTER;
- } else {
- *ppClock = m_sampleScheduler.clock();
-
- if (*ppClock) {
- (*ppClock)->AddRef();
-
- return S_OK;
- } else {
- return S_FALSE;
+ HRESULT hr = m_videoSurfaceFilter->Receive(pMediaSample);
+ if (FAILED(hr)) {
+ QMutexLocker locker(&m_videoSurfaceFilter->m_mutex);
+ if (m_videoSurfaceFilter->state() != State_Stopped && !m_flushing && !m_inErrorState) {
+ m_videoSurfaceFilter->NotifyEvent(EC_ERRORABORT, hr, 0);
+ {
+ QMutexLocker renderLocker(&m_videoSurfaceFilter->m_renderMutex);
+ if (m_videoSurfaceFilter->m_running && !m_videoSurfaceFilter->m_EOSDelivered)
+ m_videoSurfaceFilter->notifyEOS();
+ }
+ m_inErrorState = true;
}
}
+
+ return hr;
}
-HRESULT VideoSurfaceFilter::EnumPins(IEnumPins **ppEnum)
-{
- if (ppEnum) {
- *ppEnum = new DirectShowPinEnum(QList<IPin *>() << this);
- return S_OK;
- } else {
- return E_POINTER;
- }
+VideoSurfaceFilter::VideoSurfaceFilter(QAbstractVideoSurface *surface, DirectShowEventLoop *loop, QObject *parent)
+ : QObject(parent)
+ , m_loop(loop)
+ , m_pin(NULL)
+ , m_surface(surface)
+ , m_bytesPerLine(0)
+ , m_surfaceStarted(false)
+ , m_renderMutex(QMutex::Recursive)
+ , m_running(false)
+ , m_pendingSample(NULL)
+ , m_pendingSampleEndTime(0)
+ , m_renderEvent(CreateEvent(NULL, FALSE, FALSE, NULL))
+ , m_flushEvent(CreateEvent(NULL, TRUE, FALSE, NULL))
+ , m_adviseCookie(0)
+ , m_EOS(false)
+ , m_EOSDelivered(false)
+ , m_EOSTimer(0)
+{
+ supportedFormatsChanged();
+ connect(surface, &QAbstractVideoSurface::supportedFormatsChanged,
+ this, &VideoSurfaceFilter::supportedFormatsChanged);
}
-HRESULT VideoSurfaceFilter::FindPin(LPCWSTR pId, IPin **ppPin)
+VideoSurfaceFilter::~VideoSurfaceFilter()
{
- if (!ppPin || !pId) {
- return E_POINTER;
- } else if (QString::fromWCharArray(pId) == m_pinId) {
- AddRef();
+ clearPendingSample();
- *ppPin = this;
+ if (m_pin)
+ m_pin->Release();
- return S_OK;
- } else {
- return VFW_E_NOT_FOUND;
- }
+ CloseHandle(m_flushEvent);
+ CloseHandle(m_renderEvent);
}
-HRESULT VideoSurfaceFilter::JoinFilterGraph(IFilterGraph *pGraph, LPCWSTR pName)
+HRESULT VideoSurfaceFilter::getInterface(const IID &riid, void **ppvObject)
{
- m_graph = pGraph;
- m_name = QString::fromWCharArray(pName);
-
- return S_OK;
+ if (riid == IID_IAMFilterMiscFlags)
+ return GetInterface(static_cast<IAMFilterMiscFlags*>(this), ppvObject);
+ else
+ return DirectShowBaseFilter::getInterface(riid, ppvObject);
}
-HRESULT VideoSurfaceFilter::QueryFilterInfo(FILTER_INFO *pInfo)
+QList<DirectShowPin *> VideoSurfaceFilter::pins()
{
- if (pInfo) {
- QString name = m_name;
-
- if (name.length() >= MAX_FILTER_NAME)
- name.truncate(MAX_FILTER_NAME - 1);
-
- int length = name.toWCharArray(pInfo->achName);
- pInfo->achName[length] = '\0';
-
- if (m_graph)
- m_graph->AddRef();
-
- pInfo->pGraph = m_graph;
+ if (!m_pin)
+ m_pin = new VideoSurfaceInputPin(this);
- return S_OK;
- } else {
- return E_POINTER;
- }
+ return QList<DirectShowPin *>() << m_pin;
}
-HRESULT VideoSurfaceFilter::QueryVendorInfo(LPWSTR *pVendorInfo)
+HRESULT VideoSurfaceFilter::GetClassID(CLSID *pClassID)
{
- Q_UNUSED(pVendorInfo);
-
- return E_NOTIMPL;
+ *pClassID = CLSID_VideoSurfaceFilter;
+ return S_OK;
}
ULONG VideoSurfaceFilter::GetMiscFlags()
@@ -268,388 +262,527 @@ ULONG VideoSurfaceFilter::GetMiscFlags()
return AM_FILTER_MISC_FLAGS_IS_RENDERER;
}
-
-HRESULT VideoSurfaceFilter::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt)
-{
- Q_UNUSED(pReceivePin)
- Q_UNUSED(pmt)
- // This is an input pin, you shouldn't be calling Connect on it.
- return E_POINTER;
-}
-
-HRESULT VideoSurfaceFilter::ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt)
+void VideoSurfaceFilter::supportedFormatsChanged()
{
- if (!pConnector) {
- return E_POINTER;
- } else if (!pmt) {
- return E_POINTER;
- } else {
- HRESULT hr;
- QMutexLocker locker(&m_mutex);
+ QWriteLocker writeLocker(&m_typesLock);
- if (m_peerPin) {
- hr = VFW_E_ALREADY_CONNECTED;
- } else if (pmt->majortype != MEDIATYPE_Video) {
- hr = VFW_E_TYPE_NOT_ACCEPTED;
- } else {
- m_surfaceFormat = DirectShowMediaType::formatFromType(*pmt);
- m_bytesPerLine = DirectShowMediaType::bytesPerLine(m_surfaceFormat);
+ qCDebug(qLcRenderFilter, "supportedFormatChanged");
- if (thread() == QThread::currentThread()) {
- hr = start();
- } else {
- m_loop->postEvent(this, new QEvent(QEvent::Type(StartSurface)));
+ m_supportedTypes.clear();
- m_wait.wait(&m_mutex);
+ const QList<QVideoFrame::PixelFormat> formats = m_surface->supportedPixelFormats();
+ m_supportedTypes.reserve(formats.count());
- hr = m_startResult;
- }
+ for (QVideoFrame::PixelFormat format : formats) {
+ GUID subtype = DirectShowMediaType::convertPixelFormat(format);
+ if (!IsEqualGUID(subtype, MEDIASUBTYPE_None)) {
+ qCDebug(qLcRenderFilter) << " " << format;
+ m_supportedTypes.append(subtype);
}
- if (hr == S_OK) {
- m_peerPin = pConnector;
- m_peerPin->AddRef();
+ }
+}
- DirectShowMediaType::copy(&m_mediaType, *pmt);
- }
- return hr;
+bool VideoSurfaceFilter::isMediaTypeSupported(const DirectShowMediaType *type)
+{
+ if (type->majortype != MEDIATYPE_Video || type->bFixedSizeSamples == FALSE)
+ return false;
+
+ QReadLocker readLocker(&m_typesLock);
+
+ for (const GUID &supportedType : m_supportedTypes) {
+ if (IsEqualGUID(supportedType, type->subtype))
+ return true;
}
+
+ return false;
}
-HRESULT VideoSurfaceFilter::start()
+bool VideoSurfaceFilter::setMediaType(const DirectShowMediaType *type)
{
- if (!m_surface->isFormatSupported(m_surfaceFormat)) {
- return VFW_E_TYPE_NOT_ACCEPTED;
+ if (!type) {
+ qCDebug(qLcRenderFilter, "clear media type");
+ m_surfaceFormat = QVideoSurfaceFormat();
+ m_bytesPerLine = 0;
+ return true;
+ } else {
+ m_surfaceFormat = DirectShowMediaType::formatFromType(*type);
+ m_bytesPerLine = DirectShowMediaType::bytesPerLine(m_surfaceFormat);
+ qCDebug(qLcRenderFilter) << "setMediaType -->" << m_surfaceFormat;
+ return m_surfaceFormat.isValid();
}
- if (!m_surface->start(m_surfaceFormat)) {
+}
+
+HRESULT VideoSurfaceFilter::completeConnection(IPin *pin)
+{
+ Q_UNUSED(pin);
+
+ qCDebug(qLcRenderFilter, "completeConnection");
+
+ if (!startSurface())
return VFW_E_TYPE_NOT_ACCEPTED;
- } else {
+ else
return S_OK;
- }
}
-HRESULT VideoSurfaceFilter::Disconnect()
+HRESULT VideoSurfaceFilter::connectionEnded()
+{
+ qCDebug(qLcRenderFilter, "connectionEnded");
+
+ stopSurface();
+
+ return S_OK;
+}
+
+HRESULT VideoSurfaceFilter::Run(REFERENCE_TIME tStart)
{
QMutexLocker locker(&m_mutex);
- if (!m_peerPin)
- return S_FALSE;
+ if (m_state == State_Running)
+ return S_OK;
- if (thread() == QThread::currentThread()) {
- stop();
- } else {
- m_loop->postEvent(this, new QEvent(QEvent::Type(StopSurface)));
+ qCDebug(qLcRenderFilter, "Run (start=%lli)", tStart);
+
+ HRESULT hr = DirectShowBaseFilter::Run(tStart);
+ if (FAILED(hr))
+ return hr;
+
+ ResetEvent(m_flushEvent);
- m_wait.wait(&m_mutex);
+ IMemAllocator *allocator;
+ if (SUCCEEDED(m_pin->GetAllocator(&allocator))) {
+ allocator->Commit();
+ allocator->Release();
}
- m_mediaType.clear();
+ QMutexLocker renderLocker(&m_renderMutex);
- m_sampleScheduler.NotifyAllocator(0, FALSE);
+ m_running = true;
- m_peerPin->Release();
- m_peerPin = 0;
+ if (!m_pendingSample)
+ checkEOS();
+ else if (!scheduleSample(m_pendingSample))
+ SetEvent(m_renderEvent); // render immediately
return S_OK;
}
-void VideoSurfaceFilter::stop()
+HRESULT VideoSurfaceFilter::Pause()
{
- m_surface->stop();
-}
+ QMutexLocker locker(&m_mutex);
-HRESULT VideoSurfaceFilter::ConnectedTo(IPin **ppPin)
-{
- if (!ppPin) {
- return E_POINTER;
- } else {
- QMutexLocker locker(&m_mutex);
+ if (m_state == State_Paused)
+ return S_OK;
- if (!m_peerPin) {
- return VFW_E_NOT_CONNECTED;
- } else {
- m_peerPin->AddRef();
+ qCDebug(qLcRenderFilter, "Pause");
- *ppPin = m_peerPin;
+ HRESULT hr = DirectShowBaseFilter::Pause();
+ if (FAILED(hr))
+ return hr;
- return S_OK;
- }
+ m_renderMutex.lock();
+ m_EOSDelivered = false;
+ m_running = false;
+ m_renderMutex.unlock();
+
+ resetEOSTimer();
+ ResetEvent(m_flushEvent);
+ unscheduleSample();
+
+ IMemAllocator *allocator;
+ if (SUCCEEDED(m_pin->GetAllocator(&allocator))) {
+ allocator->Commit();
+ allocator->Release();
}
+
+ return S_OK;
}
-HRESULT VideoSurfaceFilter::ConnectionMediaType(AM_MEDIA_TYPE *pmt)
+HRESULT VideoSurfaceFilter::Stop()
{
- if (!pmt) {
- return E_POINTER;
- } else {
- QMutexLocker locker(&m_mutex);
+ QMutexLocker locker(&m_mutex);
- if (!m_peerPin) {
- return VFW_E_NOT_CONNECTED;
- } else {
- DirectShowMediaType::copy(pmt, m_mediaType);
+ if (m_state == State_Stopped)
+ return S_OK;
- return S_OK;
- }
- }
-}
+ qCDebug(qLcRenderFilter, "Stop");
-HRESULT VideoSurfaceFilter::QueryPinInfo(PIN_INFO *pInfo)
-{
- if (!pInfo) {
- return E_POINTER;
- } else {
- AddRef();
+ DirectShowBaseFilter::Stop();
- pInfo->pFilter = this;
- pInfo->dir = PINDIR_INPUT;
+ clearPendingSample();
- const int bytes = qMin(MAX_FILTER_NAME, (m_pinId.length() + 1) * 2);
+ m_renderMutex.lock();
+ m_EOSDelivered = false;
+ m_running = false;
+ m_renderMutex.unlock();
- ::memcpy(pInfo->achName, m_pinId.utf16(), bytes);
+ SetEvent(m_flushEvent);
+ resetEOS();
+ unscheduleSample();
+ flushSurface();
- return S_OK;
+ IMemAllocator *allocator;
+ if (SUCCEEDED(m_pin->GetAllocator(&allocator))) {
+ allocator->Decommit();
+ allocator->Release();
}
+
+ return S_OK;
}
-HRESULT VideoSurfaceFilter::QueryId(LPWSTR *Id)
+HRESULT VideoSurfaceFilter::EndOfStream()
{
- if (!Id) {
- return E_POINTER;
- } else {
- const int bytes = (m_pinId.length() + 1) * 2;
+ QMutexLocker renderLocker(&m_renderMutex);
- *Id = static_cast<LPWSTR>(::CoTaskMemAlloc(bytes));
+ qCDebug(qLcRenderFilter, "EndOfStream");
- ::memcpy(*Id, m_pinId.utf16(), bytes);
+ m_EOS = true;
- return S_OK;
- }
-}
+ if (!m_pendingSample && m_running)
+ checkEOS();
-HRESULT VideoSurfaceFilter::QueryAccept(const AM_MEDIA_TYPE *pmt)
-{
- return !m_surface->isFormatSupported(DirectShowMediaType::formatFromType(*pmt))
- ? S_OK
- : S_FALSE;
+ return S_OK;
}
-HRESULT VideoSurfaceFilter::EnumMediaTypes(IEnumMediaTypes **ppEnum)
+HRESULT VideoSurfaceFilter::BeginFlush()
{
- if (!ppEnum) {
- return E_POINTER;
- } else {
- QMutexLocker locker(&m_mutex);
+ qCDebug(qLcRenderFilter, "BeginFlush");
- *ppEnum = createMediaTypeEnum();
+ SetEvent(m_flushEvent);
+ unscheduleSample();
+ clearPendingSample();
- return S_OK;
- }
+ return S_OK;
}
-HRESULT VideoSurfaceFilter::QueryInternalConnections(IPin **apPin, ULONG *nPin)
+HRESULT VideoSurfaceFilter::EndFlush()
{
- Q_UNUSED(apPin);
- Q_UNUSED(nPin);
+ qCDebug(qLcRenderFilter, "EndFlush");
- return E_NOTIMPL;
+ ResetEvent(m_flushEvent);
+ return S_OK;
}
-HRESULT VideoSurfaceFilter::EndOfStream()
+HRESULT VideoSurfaceFilter::Receive(IMediaSample *pMediaSample)
{
- QMutexLocker locker(&m_mutex);
+ {
+ QMutexLocker locker(&m_mutex);
- if (!m_sampleScheduler.scheduleEndOfStream()) {
- if (IMediaEventSink *sink = com_cast<IMediaEventSink>(m_graph, IID_IMediaEventSink)) {
- sink->Notify(
- EC_COMPLETE,
- S_OK,
- reinterpret_cast<LONG_PTR>(static_cast<IBaseFilter *>(this)));
- sink->Release();
+ qCDebug(qLcRenderFilter, "Receive (sample=%p)", pMediaSample);
+
+ HRESULT hr = m_pin->DirectShowInputPin::Receive(pMediaSample);
+ if (hr != S_OK) {
+ qCDebug(qLcRenderFilter, " can't receive sample (error %X)", uint(hr));
+ return E_FAIL;
}
- }
- return S_OK;
-}
+ // If the format dynamically changed, the sample contains information about the new format.
+ // We need to reset the format and restart the QAbstractVideoSurface.
+ if (m_pin->currentSampleProperties()->pMediaType
+ && (!m_pin->setMediaType(reinterpret_cast<const DirectShowMediaType *>(m_pin->currentSampleProperties()->pMediaType))
+ || !restartSurface())) {
+ qCWarning(qLcRenderFilter, " dynamic format change failed, aborting rendering");
+ NotifyEvent(EC_ERRORABORT, VFW_E_TYPE_NOT_ACCEPTED, 0);
+ return VFW_E_INVALIDMEDIATYPE;
+ }
-HRESULT VideoSurfaceFilter::BeginFlush()
-{
- QMutexLocker locker(&m_mutex);
+ {
+ QMutexLocker locker(&m_renderMutex);
- m_sampleScheduler.setFlushing(true);
+ if (m_pendingSample || m_EOS)
+ return E_UNEXPECTED;
- if (thread() == QThread::currentThread()) {
- flush();
- } else {
- m_loop->postEvent(this, new QEvent(QEvent::Type(FlushSurface)));
+ if (m_running && !scheduleSample(pMediaSample)) {
+ qCWarning(qLcRenderFilter, " sample can't be scheduled, discarding it");
+ return S_OK;
+ }
+
+ m_pendingSample = pMediaSample;
+ m_pendingSample->AddRef();
+ m_pendingSampleEndTime = m_pin->currentSampleProperties()->tStop;
+ }
- m_wait.wait(&m_mutex);
+ if (m_state == State_Paused) // Render immediately
+ renderPendingSample();
}
- return S_OK;
-}
+ qCDebug(qLcRenderFilter, " waiting for render time");
-HRESULT VideoSurfaceFilter::EndFlush()
-{
- QMutexLocker locker(&m_mutex);
+ // Wait for render time. The clock will wake us up whenever the time comes.
+ // It can also be interrupted by a flush, pause or stop.
+ HANDLE waitObjects[] = { m_flushEvent, m_renderEvent };
+ DWORD result = WAIT_TIMEOUT;
+ while (result == WAIT_TIMEOUT)
+ result = WaitForMultipleObjects(2, waitObjects, FALSE, INFINITE);
- m_sampleScheduler.setFlushing(false);
+ if (result == WAIT_OBJECT_0) {
+ // render interrupted (flush, pause, stop)
+ qCDebug(qLcRenderFilter, " rendering of sample %p interrupted", pMediaSample);
+ return S_OK;
+ }
- return S_OK;
-}
+ m_adviseCookie = 0;
-void VideoSurfaceFilter::flush()
-{
- m_surface->present(QVideoFrame());
+ QMutexLocker locker(&m_mutex);
- m_wait.wakeAll();
-}
+ // State might have changed just before the lock
+ if (m_state == State_Stopped) {
+ qCDebug(qLcRenderFilter, " state changed to Stopped, discarding sample (%p)", pMediaSample);
+ return S_OK;
+ }
-HRESULT VideoSurfaceFilter::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
-{
- Q_UNUSED(tStart);
- Q_UNUSED(tStop);
- Q_UNUSED(dRate);
+ QMutexLocker renderLock(&m_renderMutex);
+
+ // Flush or pause might have happened just before the lock
+ if (m_pendingSample && m_running) {
+ renderLock.unlock();
+ renderPendingSample();
+ renderLock.relock();
+ } else {
+ qCDebug(qLcRenderFilter, " discarding sample (%p)", pMediaSample);
+ }
+
+ clearPendingSample();
+ checkEOS();
+ ResetEvent(m_renderEvent);
return S_OK;
}
-HRESULT VideoSurfaceFilter::QueryDirection(PIN_DIRECTION *pPinDir)
+bool VideoSurfaceFilter::scheduleSample(IMediaSample *sample)
{
- if (!pPinDir) {
- return E_POINTER;
- } else {
- *pPinDir = PINDIR_INPUT;
+ if (!sample)
+ return false;
- return S_OK;
+ qCDebug(qLcRenderFilter, "scheduleSample (sample=%p)", sample);
+
+ REFERENCE_TIME sampleStart, sampleEnd;
+ if (FAILED(sample->GetTime(&sampleStart, &sampleEnd)) || !m_clock) {
+ qCDebug(qLcRenderFilter, " render now");
+ SetEvent(m_renderEvent); // Render immediately
+ return true;
}
-}
-int VideoSurfaceFilter::currentMediaTypeToken()
-{
- QMutexLocker locker(&m_mutex);
+ if (sampleEnd < sampleStart) { // incorrect times
+ qCWarning(qLcRenderFilter, " invalid sample times (start=%lli, end=%lli)", sampleStart, sampleEnd);
+ return false;
+ }
+
+ HRESULT hr = m_clock->AdviseTime(m_startTime, sampleStart, (HEVENT)m_renderEvent, &m_adviseCookie);
+ if (FAILED(hr)) {
+ qCWarning(qLcRenderFilter, " clock failed to advise time (error=%X)", uint(hr));
+ return false;
+ }
- return DirectShowMediaTypeList::currentMediaTypeToken();
+ return true;
}
-HRESULT VideoSurfaceFilter::nextMediaType(
- int token, int *index, ULONG count, AM_MEDIA_TYPE **types, ULONG *fetchedCount)
+void VideoSurfaceFilter::unscheduleSample()
{
- QMutexLocker locker(&m_mutex);
-
- return DirectShowMediaTypeList::nextMediaType(token, index, count, types, fetchedCount);
+ if (m_adviseCookie) {
+ qCDebug(qLcRenderFilter, "unscheduleSample");
+ m_clock->Unadvise(m_adviseCookie);
+ m_adviseCookie = 0;
+ }
+ ResetEvent(m_renderEvent);
}
-HRESULT VideoSurfaceFilter::skipMediaType(int token, int *index, ULONG count)
+void VideoSurfaceFilter::clearPendingSample()
{
- QMutexLocker locker(&m_mutex);
+ QMutexLocker locker(&m_renderMutex);
+ if (m_pendingSample) {
+ qCDebug(qLcRenderFilter, "clearPendingSample");
+ m_pendingSample->Release();
+ m_pendingSample = NULL;
+ }
+}
- return DirectShowMediaTypeList::skipMediaType(token, index, count);
+void QT_WIN_CALLBACK EOSTimerCallback(UINT, UINT, DWORD_PTR dwUser, DWORD_PTR, DWORD_PTR)
+{
+ VideoSurfaceFilter *that = reinterpret_cast<VideoSurfaceFilter *>(dwUser);
+ that->onEOSTimerTimeout();
}
-HRESULT VideoSurfaceFilter::cloneMediaType(int token, int index, IEnumMediaTypes **enumeration)
+void VideoSurfaceFilter::onEOSTimerTimeout()
{
- QMutexLocker locker(&m_mutex);
+ QMutexLocker locker(&m_renderMutex);
- return DirectShowMediaTypeList::cloneMediaType(token, index, enumeration);
+ if (m_EOSTimer) {
+ m_EOSTimer = 0;
+ checkEOS();
+ }
}
-void VideoSurfaceFilter::customEvent(QEvent *event)
+void VideoSurfaceFilter::checkEOS()
{
- const int type = event->type();
- if (type == StartSurface) {
- QMutexLocker locker(&m_mutex);
+ QMutexLocker locker(&m_renderMutex);
- m_startResult = start();
+ if (!m_EOS || m_EOSDelivered || m_EOSTimer)
+ return;
- m_wait.wakeAll();
- } else if (type == StopSurface) {
- QMutexLocker locker(&m_mutex);
+ if (!m_clock) {
+ notifyEOS();
+ return;
+ }
- stop();
+ REFERENCE_TIME eosTime = m_startTime + m_pendingSampleEndTime;
+ REFERENCE_TIME currentTime;
+ m_clock->GetTime(&currentTime);
+ LONG delay = LONG((eosTime - currentTime) / 10000);
- m_wait.wakeAll();
- } else if (type == FlushSurface) {
- QMutexLocker locker(&m_mutex);
+ if (delay < 1) {
+ notifyEOS();
+ } else {
+ qCDebug(qLcRenderFilter, "will trigger EOS in %li", delay);
- flush();
+ m_EOSTimer = timeSetEvent(delay,
+ 1,
+ EOSTimerCallback,
+ reinterpret_cast<DWORD_PTR>(this),
+ TIME_ONESHOT | TIME_CALLBACK_FUNCTION | TIME_KILL_SYNCHRONOUS);
- m_wait.wakeAll();
- } else {
- QObject::customEvent(event);
+ if (!m_EOSTimer) {
+ qDebug("Error with timer");
+ notifyEOS();
+ }
}
}
-void VideoSurfaceFilter::supportedFormatsChanged()
+void VideoSurfaceFilter::notifyEOS()
{
- QMutexLocker locker(&m_mutex);
+ QMutexLocker locker(&m_renderMutex);
- // MEDIASUBTYPE_None;
- static const GUID none = {
- 0xe436eb8e, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70} };
+ if (!m_running)
+ return;
- const QList<QVideoFrame::PixelFormat> formats = m_surface->supportedPixelFormats();
+ qCDebug(qLcRenderFilter, "notifyEOS, delivering EC_COMPLETE event");
- QVector<AM_MEDIA_TYPE> mediaTypes;
- mediaTypes.reserve(formats.count());
+ m_EOSTimer = 0;
+ m_EOSDelivered = true;
+ NotifyEvent(EC_COMPLETE, S_OK, (LONG_PTR)(IBaseFilter *)this);
+}
- AM_MEDIA_TYPE type;
- type.majortype = MEDIATYPE_Video;
- type.bFixedSizeSamples = TRUE;
- type.bTemporalCompression = FALSE;
- type.lSampleSize = 0;
- type.formattype = GUID_NULL;
- type.pUnk = 0;
- type.cbFormat = 0;
- type.pbFormat = 0;
+void VideoSurfaceFilter::resetEOS()
+{
+ resetEOSTimer();
- for (QVideoFrame::PixelFormat format : formats) {
- type.subtype = DirectShowMediaType::convertPixelFormat(format);
+ QMutexLocker locker(&m_renderMutex);
- if (type.subtype != none)
- mediaTypes.append(type);
- }
+ if (m_EOS)
+ qCDebug(qLcRenderFilter, "resetEOS (delivered=%s)", m_EOSDelivered ? "true" : "false");
- setMediaTypes(mediaTypes);
+ m_EOS = false;
+ m_EOSDelivered = false;
+ m_pendingSampleEndTime = 0;
}
-void VideoSurfaceFilter::sampleReady()
+void VideoSurfaceFilter::resetEOSTimer()
{
- bool eos = false;
+ if (m_EOSTimer) {
+ timeKillEvent(m_EOSTimer);
+ m_EOSTimer = 0;
+ }
+}
- IMediaSample *sample = m_sampleScheduler.takeSample(&eos);
+bool VideoSurfaceFilter::startSurface()
+{
+ if (QThread::currentThread() != thread()) {
+ m_loop->postEvent(this, new QEvent(QEvent::Type(StartSurface)));
+ m_waitSurface.wait(&m_mutex);
+ return m_surfaceStarted;
+ } else {
+ m_surfaceStarted = m_surface->start(m_surfaceFormat);
+ qCDebug(qLcRenderFilter, "startSurface %s", m_surfaceStarted ? "succeeded" : "failed");
+ return m_surfaceStarted;
+ }
+}
- if (sample) {
- QVideoFrame frame(new MediaSampleVideoBuffer(sample, m_bytesPerLine),
- m_surfaceFormat.frameSize(),
- m_surfaceFormat.pixelFormat());
+void VideoSurfaceFilter::stopSurface()
+{
+ if (!m_surfaceStarted)
+ return;
- if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph, IID_IMediaSeeking)) {
- LONGLONG position = 0;
- seeking->GetCurrentPosition(&position);
- seeking->Release();
+ if (QThread::currentThread() != thread()) {
+ m_loop->postEvent(this, new QEvent(QEvent::Type(StopSurface)));
+ m_waitSurface.wait(&m_mutex);
+ } else {
+ qCDebug(qLcRenderFilter, "stopSurface");
+ m_surface->stop();
+ m_surfaceStarted = false;
+ }
+}
- frame.setStartTime(position * 0.1);
+bool VideoSurfaceFilter::restartSurface()
+{
+ if (QThread::currentThread() != thread()) {
+ m_loop->postEvent(this, new QEvent(QEvent::Type(RestartSurface)));
+ m_waitSurface.wait(&m_mutex);
+ return m_surfaceStarted;
+ } else {
+ m_surface->stop();
+ m_surfaceStarted = m_surface->start(m_surfaceFormat);
+ qCDebug(qLcRenderFilter, "restartSurface %s", m_surfaceStarted ? "succeeded" : "failed");
+ return m_surfaceStarted;
+ }
+}
- REFERENCE_TIME startTime = -1;
- REFERENCE_TIME endTime = -1;
- if (sample->GetTime(&startTime, &endTime) == S_OK)
- frame.setEndTime(frame.startTime() + (endTime - startTime) * 0.1);
- }
+void VideoSurfaceFilter::flushSurface()
+{
+ if (QThread::currentThread() != thread()) {
+ m_loop->postEvent(this, new QEvent(QEvent::Type(FlushSurface)));
+ m_waitSurface.wait(&m_mutex);
+ } else {
+ qCDebug(qLcRenderFilter, "flushSurface");
+ m_surface->present(QVideoFrame());
+ }
+}
- m_surface->present(frame);
+void VideoSurfaceFilter::renderPendingSample()
+{
+ if (QThread::currentThread() != thread()) {
+ m_loop->postEvent(this, new QEvent(QEvent::Type(RenderSample)));
+ m_waitSurface.wait(&m_mutex);
+ } else {
+ QMutexLocker locker(&m_renderMutex);
+ if (!m_pendingSample)
+ return;
- sample->Release();
+ qCDebug(qLcRenderFilter, "presentSample (sample=%p)", m_pendingSample);
- if (eos) {
- if (IMediaEventSink *sink = com_cast<IMediaEventSink>(m_graph, IID_IMediaEventSink)) {
- sink->Notify(
- EC_COMPLETE,
- S_OK,
- reinterpret_cast<LONG_PTR>(static_cast<IBaseFilter *>(this)));
- sink->Release();
- }
- }
+ m_surface->present(QVideoFrame(new DirectShowVideoBuffer(m_pendingSample, m_bytesPerLine),
+ m_surfaceFormat.frameSize(),
+ m_surfaceFormat.pixelFormat()));
}
}
+bool VideoSurfaceFilter::event(QEvent *e)
+{
+ if (e->type() == QEvent::Type(StartSurface)) {
+ QMutexLocker locker(&m_mutex);
+ startSurface();
+ m_waitSurface.wakeAll();
+ return true;
+ } else if (e->type() == QEvent::Type(StopSurface)) {
+ QMutexLocker locker(&m_mutex);
+ stopSurface();
+ m_waitSurface.wakeAll();
+ return true;
+ } else if (e->type() == QEvent::Type(RestartSurface)) {
+ QMutexLocker locker(&m_mutex);
+ restartSurface();
+ m_waitSurface.wakeAll();
+ return true;
+ } else if (e->type() == QEvent::Type(FlushSurface)) {
+ QMutexLocker locker(&m_mutex);
+ flushSurface();
+ m_waitSurface.wakeAll();
+ return true;
+ } else if (e->type() == QEvent::Type(RenderSample)) {
+ QMutexLocker locker(&m_mutex);
+ renderPendingSample();
+ m_waitSurface.wakeAll();
+ return true;
+ }
+
+ return QObject::event(e);
+}
diff --git a/src/plugins/directshow/player/videosurfacefilter.h b/src/plugins/directshow/player/videosurfacefilter.h
index 001e2804b..581e33c70 100644
--- a/src/plugins/directshow/player/videosurfacefilter.h
+++ b/src/plugins/directshow/player/videosurfacefilter.h
@@ -40,135 +40,121 @@
#ifndef VIDEOSURFACEFILTER_H
#define VIDEOSURFACEFILTER_H
-#include "directshowglobal.h"
-#include "directshowmediatypelist.h"
-#include "directshowsamplescheduler.h"
-#include "directshowmediatype.h"
+#include "directshowbasefilter.h"
-#include <QtCore/qbasictimer.h>
#include <QtCore/qcoreevent.h>
#include <QtCore/qmutex.h>
-#include <QtCore/qsemaphore.h>
-#include <QtCore/qstring.h>
-#include <QtCore/qwaitcondition.h>
-
-#include <dshow.h>
+#include <qreadwritelock.h>
+#include <qsemaphore.h>
+#include <qwaitcondition.h>
QT_BEGIN_NAMESPACE
class QAbstractVideoSurface;
QT_END_NAMESPACE
class DirectShowEventLoop;
+class VideoSurfaceInputPin;
-class VideoSurfaceFilter
- : public QObject
- , public DirectShowMediaTypeList
- , public IBaseFilter
- , public IAMFilterMiscFlags
- , public IPin
+class VideoSurfaceFilter : public QObject
+ , public DirectShowBaseFilter
+ , public IAMFilterMiscFlags
{
Q_OBJECT
+ DIRECTSHOW_OBJECT
public:
- VideoSurfaceFilter(
- QAbstractVideoSurface *surface, DirectShowEventLoop *loop, QObject *parent = 0);
+ VideoSurfaceFilter(QAbstractVideoSurface *surface, DirectShowEventLoop *loop, QObject *parent = 0);
~VideoSurfaceFilter();
- // IUnknown
- HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);
- ULONG STDMETHODCALLTYPE AddRef();
- ULONG STDMETHODCALLTYPE Release();
+ // DirectShowObject
+ HRESULT getInterface(REFIID riid, void **ppvObject);
+
+ // DirectShowBaseFilter
+ QList<DirectShowPin *> pins();
// IPersist
- HRESULT STDMETHODCALLTYPE GetClassID(CLSID *pClassID);
+ STDMETHODIMP GetClassID(CLSID *pClassID);
// IMediaFilter
- HRESULT STDMETHODCALLTYPE Run(REFERENCE_TIME tStart);
- HRESULT STDMETHODCALLTYPE Pause();
- HRESULT STDMETHODCALLTYPE Stop();
-
- HRESULT STDMETHODCALLTYPE GetState(DWORD dwMilliSecsTimeout, FILTER_STATE *pState);
-
- HRESULT STDMETHODCALLTYPE SetSyncSource(IReferenceClock *pClock);
- HRESULT STDMETHODCALLTYPE GetSyncSource(IReferenceClock **ppClock);
-
- // IBaseFilter
- HRESULT STDMETHODCALLTYPE EnumPins(IEnumPins **ppEnum);
- HRESULT STDMETHODCALLTYPE FindPin(LPCWSTR Id, IPin **ppPin);
-
- HRESULT STDMETHODCALLTYPE JoinFilterGraph(IFilterGraph *pGraph, LPCWSTR pName);
-
- HRESULT STDMETHODCALLTYPE QueryFilterInfo(FILTER_INFO *pInfo);
- HRESULT STDMETHODCALLTYPE QueryVendorInfo(LPWSTR *pVendorInfo);
+ STDMETHODIMP Run(REFERENCE_TIME tStart);
+ STDMETHODIMP Pause();
+ STDMETHODIMP Stop();
// IAMFilterMiscFlags
- ULONG STDMETHODCALLTYPE GetMiscFlags();
+ STDMETHODIMP_(ULONG) GetMiscFlags();
- // IPin
- HRESULT STDMETHODCALLTYPE Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt);
- HRESULT STDMETHODCALLTYPE ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt);
- HRESULT STDMETHODCALLTYPE Disconnect();
- HRESULT STDMETHODCALLTYPE ConnectedTo(IPin **ppPin);
+ // DirectShowPin (delegate)
+ bool isMediaTypeSupported(const DirectShowMediaType *type);
+ bool setMediaType(const DirectShowMediaType *type);
+ HRESULT completeConnection(IPin *pin);
+ HRESULT connectionEnded();
- HRESULT STDMETHODCALLTYPE ConnectionMediaType(AM_MEDIA_TYPE *pmt);
+ // IPin (delegate)
+ HRESULT EndOfStream();
+ HRESULT BeginFlush();
+ HRESULT EndFlush();
- HRESULT STDMETHODCALLTYPE QueryPinInfo(PIN_INFO *pInfo);
- HRESULT STDMETHODCALLTYPE QueryId(LPWSTR *Id);
+ // IMemInputPin (delegate)
+ HRESULT Receive(IMediaSample *pMediaSample);
- HRESULT STDMETHODCALLTYPE QueryAccept(const AM_MEDIA_TYPE *pmt);
+private Q_SLOTS:
+ void supportedFormatsChanged();
+ void checkEOS();
- HRESULT STDMETHODCALLTYPE EnumMediaTypes(IEnumMediaTypes **ppEnum);
+private:
+ enum Events {
+ StartSurface = QEvent::User,
+ StopSurface = QEvent::User + 1,
+ RestartSurface = QEvent::User + 2,
+ FlushSurface = QEvent::User + 3,
+ RenderSample = QEvent::User + 4
+ };
+
+ bool event(QEvent *);
- HRESULT STDMETHODCALLTYPE QueryInternalConnections(IPin **apPin, ULONG *nPin);
+ bool startSurface();
+ void stopSurface();
+ bool restartSurface();
+ void flushSurface();
- HRESULT STDMETHODCALLTYPE EndOfStream();
+ bool scheduleSample(IMediaSample *sample);
+ void unscheduleSample();
+ void renderPendingSample();
+ void clearPendingSample();
- HRESULT STDMETHODCALLTYPE BeginFlush();
- HRESULT STDMETHODCALLTYPE EndFlush();
+ void notifyEOS();
+ void resetEOS();
+ void resetEOSTimer();
+ void onEOSTimerTimeout();
- HRESULT STDMETHODCALLTYPE NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate);
+ friend void QT_WIN_CALLBACK EOSTimerCallback(UINT, UINT, DWORD_PTR dwUser, DWORD_PTR, DWORD_PTR);
- HRESULT STDMETHODCALLTYPE QueryDirection(PIN_DIRECTION *pPinDir);
+ QMutex m_mutex;
- int currentMediaTypeToken();
- HRESULT nextMediaType(
- int token, int *index, ULONG count, AM_MEDIA_TYPE **types, ULONG *fetchedCount);
- HRESULT skipMediaType(int token, int *index, ULONG count);
- HRESULT cloneMediaType(int token, int index, IEnumMediaTypes **enumeration);
+ DirectShowEventLoop *m_loop;
+ VideoSurfaceInputPin *m_pin;
-protected:
- void customEvent(QEvent *event);
+ QWaitCondition m_waitSurface;
+ QAbstractVideoSurface *m_surface;
+ QVideoSurfaceFormat m_surfaceFormat;
+ int m_bytesPerLine;
+ bool m_surfaceStarted;
-private Q_SLOTS:
- void supportedFormatsChanged();
- void sampleReady();
+ QList<GUID> m_supportedTypes;
+ QReadWriteLock m_typesLock;
-private:
- HRESULT start();
- void stop();
- void flush();
+ QMutex m_renderMutex;
+ bool m_running;
+ IMediaSample *m_pendingSample;
+ REFERENCE_TIME m_pendingSampleEndTime;
+ HANDLE m_renderEvent;
+ HANDLE m_flushEvent;
+ DWORD_PTR m_adviseCookie;
- enum
- {
- StartSurface = QEvent::User,
- StopSurface,
- FlushSurface
- };
+ bool m_EOS;
+ bool m_EOSDelivered;
+ UINT m_EOSTimer;
- LONG m_ref;
- FILTER_STATE m_state;
- QAbstractVideoSurface *m_surface;
- DirectShowEventLoop *m_loop;
- IFilterGraph *m_graph;
- IPin *m_peerPin;
- int m_bytesPerLine;
- HRESULT m_startResult;
- QString m_name;
- QString m_pinId;
- DirectShowMediaType m_mediaType;
- QVideoSurfaceFormat m_surfaceFormat;
- QMutex m_mutex;
- QWaitCondition m_wait;
- DirectShowSampleScheduler m_sampleScheduler;
+ friend class VideoSurfaceInputPin;
};
#endif
diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp b/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp
index 074f8adfc..01103d659 100644
--- a/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp
+++ b/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp
@@ -93,6 +93,7 @@ static const QGstreamerMetaDataKeyLookup *qt_gstreamerMetaDataKeys()
//metadataKeys->insert(0, QMediaMetaData::CoverArtUrlSmall);
//metadataKeys->insert(0, QMediaMetaData::CoverArtUrlLarge);
+ metadataKeys->insert(GST_TAG_PREVIEW_IMAGE, QMediaMetaData::CoverArtImage);
// Image/Video
metadataKeys->insert("resolution", QMediaMetaData::Resolution);
diff --git a/src/plugins/opensles/qopenslesaudiooutput.cpp b/src/plugins/opensles/qopenslesaudiooutput.cpp
index 47006ed34..70d77a380 100644
--- a/src/plugins/opensles/qopenslesaudiooutput.cpp
+++ b/src/plugins/opensles/qopenslesaudiooutput.cpp
@@ -48,8 +48,6 @@
#endif // ANDROID
#define BUFFER_COUNT 2
-#define EBASE 2.302585093
-#define LOG10(x) qLn(x)/qreal(EBASE)
QT_BEGIN_NAMESPACE
@@ -723,7 +721,7 @@ inline SLmillibel QOpenSLESAudioOutput::adjustVolume(qreal vol)
if (qFuzzyCompare(vol, qreal(1.0)))
return 0;
- return 20 * LOG10(vol) * 100; // I.e., 20 * LOG10(SL_MILLIBEL_MAX * vol / SL_MILLIBEL_MAX)
+ return QAudio::convertVolume(vol, QAudio::LinearVolumeScale, QAudio::DecibelVolumeScale) * 100;
}
QT_END_NAMESPACE
diff --git a/src/plugins/opensles/qopenslesengine.cpp b/src/plugins/opensles/qopenslesengine.cpp
index 0cbd10887..1a16cc2a3 100644
--- a/src/plugins/opensles/qopenslesengine.cpp
+++ b/src/plugins/opensles/qopenslesengine.cpp
@@ -101,6 +101,12 @@ SLDataFormat_PCM QOpenSLESEngine::audioFormatToSLFormatPCM(const QAudioFormat &f
}
+QByteArray QOpenSLESEngine::defaultDevice(QAudio::Mode mode) const
+{
+ const auto &devices = availableDevices(mode);
+ return !devices.isEmpty() ? devices.first() : QByteArray();
+}
+
QList<QByteArray> QOpenSLESEngine::availableDevices(QAudio::Mode mode) const
{
QList<QByteArray> devices;
diff --git a/src/plugins/opensles/qopenslesengine.h b/src/plugins/opensles/qopenslesengine.h
index 364b3ef60..c36b21488 100644
--- a/src/plugins/opensles/qopenslesengine.h
+++ b/src/plugins/opensles/qopenslesengine.h
@@ -62,6 +62,7 @@ public:
static SLDataFormat_PCM audioFormatToSLFormatPCM(const QAudioFormat &format);
+ QByteArray defaultDevice(QAudio::Mode mode) const;
QList<QByteArray> availableDevices(QAudio::Mode mode) const;
QList<int> supportedChannelCounts(QAudio::Mode mode) const;
QList<int> supportedSampleRates(QAudio::Mode mode) const;
diff --git a/src/plugins/opensles/qopenslesplugin.cpp b/src/plugins/opensles/qopenslesplugin.cpp
index 8f89d044d..9a2fbbf79 100644
--- a/src/plugins/opensles/qopenslesplugin.cpp
+++ b/src/plugins/opensles/qopenslesplugin.cpp
@@ -52,6 +52,11 @@ QOpenSLESPlugin::QOpenSLESPlugin(QObject *parent)
{
}
+QByteArray QOpenSLESPlugin::defaultDevice(QAudio::Mode mode) const
+{
+ return m_engine->defaultDevice(mode);
+}
+
QList<QByteArray> QOpenSLESPlugin::availableDevices(QAudio::Mode mode) const
{
return m_engine->availableDevices(mode);
diff --git a/src/plugins/opensles/qopenslesplugin.h b/src/plugins/opensles/qopenslesplugin.h
index 2a967b27e..d45a47923 100644
--- a/src/plugins/opensles/qopenslesplugin.h
+++ b/src/plugins/opensles/qopenslesplugin.h
@@ -40,22 +40,25 @@
#ifndef QOPENSLESPLUGIN_H
#define QOPENSLESPLUGIN_H
-#include <qaudiosystemplugin.h>
+#include <QtMultimedia/qaudiosystemplugin.h>
+#include <QtMultimedia/private/qaudiosystempluginext_p.h>
QT_BEGIN_NAMESPACE
class QOpenSLESEngine;
-class QOpenSLESPlugin : public QAudioSystemPlugin
+class QOpenSLESPlugin : public QAudioSystemPlugin, public QAudioSystemPluginExtension
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.qt.audiosystemfactory/5.0" FILE "opensles.json")
+ Q_INTERFACES(QAudioSystemPluginExtension)
public:
QOpenSLESPlugin(QObject *parent = 0);
~QOpenSLESPlugin() {}
+ QByteArray defaultDevice(QAudio::Mode mode) const;
QList<QByteArray> availableDevices(QAudio::Mode mode) const;
QAbstractAudioInput *createInput(const QByteArray &device);
QAbstractAudioOutput *createOutput(const QByteArray &device);
diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro
index 67b06a61b..269437149 100644
--- a/src/plugins/plugins.pro
+++ b/src/plugins/plugins.pro
@@ -25,7 +25,11 @@ qnx:!blackberry {
SUBDIRS += qnx-audio
}
-win32:!winrt:!wince {
+win32 {
+ config_wasapi: SUBDIRS += wasapi
+}
+
+win32:!winrt {
SUBDIRS += audiocapture \
windowsaudio
@@ -34,8 +38,7 @@ win32:!winrt:!wince {
}
winrt {
- SUBDIRS += wasapi \
- winrt
+ SUBDIRS += winrt
}
unix:!mac:!android {
@@ -54,7 +57,7 @@ unix:!mac:!android {
# }
}
-mac:!simulator {
+darwin:!watchos:!simulator {
SUBDIRS += audiocapture coreaudio
config_avfoundation: SUBDIRS += avfoundation
diff --git a/src/plugins/pulseaudio/qpulseaudioengine.cpp b/src/plugins/pulseaudio/qpulseaudioengine.cpp
index 286f310bc..967a696b0 100644
--- a/src/plugins/pulseaudio/qpulseaudioengine.cpp
+++ b/src/plugins/pulseaudio/qpulseaudioengine.cpp
@@ -443,4 +443,9 @@ QList<QByteArray> QPulseAudioEngine::availableDevices(QAudio::Mode mode) const
return devices;
}
+QByteArray QPulseAudioEngine::defaultDevice(QAudio::Mode mode) const
+{
+ return (mode == QAudio::AudioOutput) ? m_defaultSink : m_defaultSource;
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/pulseaudio/qpulseaudioengine.h b/src/plugins/pulseaudio/qpulseaudioengine.h
index f03dbfd16..a19be1841 100644
--- a/src/plugins/pulseaudio/qpulseaudioengine.h
+++ b/src/plugins/pulseaudio/qpulseaudioengine.h
@@ -54,7 +54,7 @@
#include <QtCore/qmap.h>
#include <QtCore/qbytearray.h>
#include <QtCore/qreadwritelock.h>
-#include <qaudiosystemplugin.h>
+#include <QtMultimedia/qaudiosystemplugin.h>
#include <pulse/pulseaudio.h>
#include "qpulsehelpers.h"
#include <qaudioformat.h>
@@ -92,6 +92,7 @@ public:
}
QList<QByteArray> availableDevices(QAudio::Mode mode) const;
+ QByteArray defaultDevice(QAudio::Mode mode) const;
Q_SIGNALS:
void contextFailed();
diff --git a/src/plugins/pulseaudio/qpulseaudioplugin.cpp b/src/plugins/pulseaudio/qpulseaudioplugin.cpp
index 2b7b22089..6b3019279 100644
--- a/src/plugins/pulseaudio/qpulseaudioplugin.cpp
+++ b/src/plugins/pulseaudio/qpulseaudioplugin.cpp
@@ -53,6 +53,11 @@ QPulseAudioPlugin::QPulseAudioPlugin(QObject *parent)
{
}
+QByteArray QPulseAudioPlugin::defaultDevice(QAudio::Mode mode) const
+{
+ return m_pulseEngine->defaultDevice(mode);
+}
+
QList<QByteArray> QPulseAudioPlugin::availableDevices(QAudio::Mode mode) const
{
return m_pulseEngine->availableDevices(mode);
diff --git a/src/plugins/pulseaudio/qpulseaudioplugin.h b/src/plugins/pulseaudio/qpulseaudioplugin.h
index 4bad509e9..120d57df5 100644
--- a/src/plugins/pulseaudio/qpulseaudioplugin.h
+++ b/src/plugins/pulseaudio/qpulseaudioplugin.h
@@ -40,22 +40,25 @@
#ifndef QPULSEAUDIOPLUGIN_H
#define QPULSEAUDIOPLUGIN_H
-#include <qaudiosystemplugin.h>
+#include <QtMultimedia/qaudiosystemplugin.h>
+#include <QtMultimedia/private/qaudiosystempluginext_p.h>
QT_BEGIN_NAMESPACE
class QPulseAudioEngine;
-class QPulseAudioPlugin : public QAudioSystemPlugin
+class QPulseAudioPlugin : public QAudioSystemPlugin, public QAudioSystemPluginExtension
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.qt.audiosystemfactory/5.0" FILE "pulseaudio.json")
+ Q_INTERFACES(QAudioSystemPluginExtension)
public:
QPulseAudioPlugin(QObject *parent = 0);
~QPulseAudioPlugin() {}
+ QByteArray defaultDevice(QAudio::Mode mode) const;
QList<QByteArray> availableDevices(QAudio::Mode mode) const;
QAbstractAudioInput *createInput(const QByteArray &device);
QAbstractAudioOutput *createOutput(const QByteArray &device);
diff --git a/src/plugins/qnx-audio/audio/qnxaudioplugin.cpp b/src/plugins/qnx-audio/audio/qnxaudioplugin.cpp
index a3793fc3c..5d26c8954 100644
--- a/src/plugins/qnx-audio/audio/qnxaudioplugin.cpp
+++ b/src/plugins/qnx-audio/audio/qnxaudioplugin.cpp
@@ -55,6 +55,11 @@ QnxAudioPlugin::QnxAudioPlugin(QObject *parent)
{
}
+QByteArray QnxAudioPlugin::defaultDevice(QAudio::Mode mode) const
+{
+ return (mode == QAudio::AudioOutput) ? OUTPUT_ID : INPUT_ID;
+}
+
QList<QByteArray> QnxAudioPlugin::availableDevices(QAudio::Mode mode) const
{
if (mode == QAudio::AudioOutput)
diff --git a/src/plugins/qnx-audio/audio/qnxaudioplugin.h b/src/plugins/qnx-audio/audio/qnxaudioplugin.h
index 5e2410619..1d8b8a74b 100644
--- a/src/plugins/qnx-audio/audio/qnxaudioplugin.h
+++ b/src/plugins/qnx-audio/audio/qnxaudioplugin.h
@@ -40,19 +40,22 @@
#ifndef QNXAUDIOPLUGIN_H
#define QNXAUDIOPLUGIN_H
-#include <qaudiosystemplugin.h>
+#include <QtMultimedia/qaudiosystemplugin.h>
+#include <QtMultimedia/private/qaudiosystempluginext_p.h>
QT_BEGIN_NAMESPACE
-class QnxAudioPlugin : public QAudioSystemPlugin
+class QnxAudioPlugin : public QAudioSystemPlugin, public QAudioSystemPluginExtension
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.qt.audiosystemfactory/5.0" FILE "qnx_audio.json")
+ Q_INTERFACES(QAudioSystemPluginExtension)
public:
explicit QnxAudioPlugin(QObject *parent = 0);
~QnxAudioPlugin() {}
+ QByteArray defaultDevice(QAudio::Mode mode) const Q_DECL_OVERRIDE;
QList<QByteArray> availableDevices(QAudio::Mode mode) const Q_DECL_OVERRIDE;
QAbstractAudioInput *createInput(const QByteArray &device) Q_DECL_OVERRIDE;
QAbstractAudioOutput *createOutput(const QByteArray &device) Q_DECL_OVERRIDE;
diff --git a/src/plugins/videonode/videonode.pro b/src/plugins/videonode/videonode.pro
index e38b0a6a0..5fbcaecd4 100644
--- a/src/plugins/videonode/videonode.pro
+++ b/src/plugins/videonode/videonode.pro
@@ -1,7 +1,8 @@
TEMPLATE = subdirs
+QT_FOR_CONFIG += gui-private
config_gpu_vivante {
SUBDIRS += imx6
}
-contains(QT_CONFIG, egl):contains(QT_CONFIG, opengles2):!android: SUBDIRS += egl
+qtConfig(egl):qtConfig(opengles2):!android: SUBDIRS += egl
diff --git a/src/plugins/wasapi/qwasapiplugin.cpp b/src/plugins/wasapi/qwasapiplugin.cpp
index 1466347ba..9325dc400 100644
--- a/src/plugins/wasapi/qwasapiplugin.cpp
+++ b/src/plugins/wasapi/qwasapiplugin.cpp
@@ -53,6 +53,11 @@ QWasapiPlugin::QWasapiPlugin(QObject *parent)
qCDebug(lcMmPlugin) << __FUNCTION__;
}
+QByteArray QWasapiPlugin::defaultDevice(QAudio::Mode mode) const
+{
+ return QWasapiUtils::defaultDevice(mode);
+}
+
QList<QByteArray> QWasapiPlugin::availableDevices(QAudio::Mode mode) const
{
qCDebug(lcMmPlugin) << __FUNCTION__ << mode;
diff --git a/src/plugins/wasapi/qwasapiplugin.h b/src/plugins/wasapi/qwasapiplugin.h
index fb9b6fc31..e69e7895f 100644
--- a/src/plugins/wasapi/qwasapiplugin.h
+++ b/src/plugins/wasapi/qwasapiplugin.h
@@ -42,22 +42,25 @@
#include <QtCore/QLoggingCategory>
#include <QtCore/QList>
-#include <QtMultimedia/QAudioSystemPlugin>
+#include <QtMultimedia/qaudiosystemplugin.h>
+#include <QtMultimedia/private/qaudiosystempluginext_p.h>
QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(lcMmPlugin)
-class QWasapiPlugin : public QAudioSystemPlugin
+class QWasapiPlugin : public QAudioSystemPlugin, public QAudioSystemPluginExtension
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.qt.audiosystemfactory/5.0" FILE "wasapi.json")
+ Q_INTERFACES(QAudioSystemPluginExtension)
public:
explicit QWasapiPlugin(QObject *parent = 0);
~QWasapiPlugin() {}
+ QByteArray defaultDevice(QAudio::Mode mode) const Q_DECL_OVERRIDE;
QList<QByteArray> availableDevices(QAudio::Mode mode) const Q_DECL_OVERRIDE;
QAbstractAudioInput *createInput(const QByteArray &device) Q_DECL_OVERRIDE;
QAbstractAudioOutput *createOutput(const QByteArray &device) Q_DECL_OVERRIDE;
diff --git a/src/plugins/wasapi/qwasapiutils.cpp b/src/plugins/wasapi/qwasapiutils.cpp
index bd1795aee..727c94c23 100644
--- a/src/plugins/wasapi/qwasapiutils.cpp
+++ b/src/plugins/wasapi/qwasapiutils.cpp
@@ -178,6 +178,38 @@ bool QWasapiUtils::convertFromNativeFormat(const WAVEFORMATEX *native, QAudioFor
return true;
}
+QByteArray QWasapiUtils::defaultDevice(QAudio::Mode mode)
+{
+ qCDebug(lcMmUtils) << __FUNCTION__ << mode;
+
+ QList<QByteArray> &deviceNames = mode == QAudio::AudioInput ? gMapping->inputDeviceNames : gMapping->outputDeviceNames;
+ QList<QString> &deviceIds = mode == QAudio::AudioInput ? gMapping->inputDeviceIds : gMapping->outputDeviceIds;
+ if (deviceNames.isEmpty() || deviceIds.isEmpty()) // Initialize
+ availableDevices(mode);
+ if (deviceNames.isEmpty() || deviceIds.isEmpty()) // No audio devices at all
+ return QByteArray();
+
+ ComPtr<IMediaDeviceStatics> mediaDeviceStatics;
+ HRESULT hr;
+
+ hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Media_Devices_MediaDevice).Get(), &mediaDeviceStatics);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ HString defaultAudioDevice;
+ quint32 dADSize = 0;
+
+ if (mode == QAudio::AudioOutput)
+ hr = mediaDeviceStatics->GetDefaultAudioRenderId(AudioDeviceRole_Default, defaultAudioDevice.GetAddressOf());
+ else
+ hr = mediaDeviceStatics->GetDefaultAudioCaptureId(AudioDeviceRole_Default, defaultAudioDevice.GetAddressOf());
+
+ const wchar_t *dadWStr = defaultAudioDevice.GetRawBuffer(&dADSize);
+ const QString defaultAudioDeviceId = QString::fromWCharArray(dadWStr, dADSize);
+ Q_ASSERT(deviceIds.indexOf(defaultAudioDeviceId) != -1);
+
+ return deviceNames.at(deviceIds.indexOf(defaultAudioDeviceId));
+}
+
QList<QByteArray> QWasapiUtils::availableDevices(QAudio::Mode mode)
{
qCDebug(lcMmUtils) << __FUNCTION__ << mode;
@@ -189,16 +221,6 @@ QList<QByteArray> QWasapiUtils::availableDevices(QAudio::Mode mode)
&statics);
Q_ASSERT_SUCCEEDED(hr);
- ComPtr<IMediaDeviceStatics> mediaDeviceStatics;
- hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Media_Devices_MediaDevice).Get(), &mediaDeviceStatics);
- Q_ASSERT_SUCCEEDED(hr);
-
- HString defaultAudioRender;
- quint32 dARSize = 0;
- hr = mediaDeviceStatics->GetDefaultAudioRenderId(AudioDeviceRole_Default, defaultAudioRender.GetAddressOf());
- const wchar_t *darWStr = defaultAudioRender.GetRawBuffer(&dARSize);
- const QString defaultAudioDeviceId = QString::fromWCharArray(darWStr, dARSize);
-
DeviceClass dc = mode == QAudio::AudioInput ? DeviceClass_AudioCapture : DeviceClass_AudioRender;
QList<QByteArray> &deviceNames = mode == QAudio::AudioInput ? gMapping->inputDeviceNames : gMapping->outputDeviceNames;
@@ -248,18 +270,6 @@ QList<QByteArray> QWasapiUtils::availableDevices(QAudio::Mode mode)
const wchar_t *idWStr = hString.GetRawBuffer(&size);
const QString deviceId = QString::fromWCharArray(idWStr, size);
- boolean def;
- hr = item->get_IsDefault(&def);
- if (FAILED(hr)) {
- qErrnoWarning(hr, "Could not access audio device default.");
- continue;
- }
-
- // At least on desktop no device is marked as default
- // Hence use the default audio device string from above
- if (!def && !defaultAudioDeviceId.isEmpty())
- def = defaultAudioDeviceId == deviceId;
-
boolean enabled;
hr = item->get_IsEnabled(&enabled);
if (FAILED(hr)) {
@@ -268,14 +278,10 @@ QList<QByteArray> QWasapiUtils::availableDevices(QAudio::Mode mode)
}
qCDebug(lcMmUtils) << "Audio Device:" << deviceName << " ID:" << deviceId
- << " Enabled:" << enabled << " Default:" << def;
- if (def) {
- deviceNames.prepend(deviceName.toLocal8Bit());
- deviceIds.prepend(deviceId);
- } else {
- deviceNames.append(deviceName.toLocal8Bit());
- deviceIds.append(deviceId);
- }
+ << " Enabled:" << enabled;
+
+ deviceNames.append(deviceName.toLocal8Bit());
+ deviceIds.append(deviceId);
}
return deviceNames;
}
diff --git a/src/plugins/wasapi/qwasapiutils.h b/src/plugins/wasapi/qwasapiutils.h
index ff2d915b6..7cfdd3cda 100644
--- a/src/plugins/wasapi/qwasapiutils.h
+++ b/src/plugins/wasapi/qwasapiutils.h
@@ -137,6 +137,7 @@ namespace QWasapiUtils
bool convertToNativeFormat(const QAudioFormat &qt, WAVEFORMATEX *native);
bool convertFromNativeFormat(const WAVEFORMATEX *native, QAudioFormat *qt);
+ QByteArray defaultDevice(QAudio::Mode mode);
QList<QByteArray> availableDevices(QAudio::Mode mode);
Microsoft::WRL::ComPtr<AudioInterface> createOrGetInterface(const QByteArray &dev, QAudio::Mode mode);
}
diff --git a/src/plugins/windowsaudio/qwindowsaudiodeviceinfo.cpp b/src/plugins/windowsaudio/qwindowsaudiodeviceinfo.cpp
index 9aa4487ab..83e9ccfc8 100644
--- a/src/plugins/windowsaudio/qwindowsaudiodeviceinfo.cpp
+++ b/src/plugins/windowsaudio/qwindowsaudiodeviceinfo.cpp
@@ -400,7 +400,6 @@ QList<QByteArray> QWindowsAudioDeviceInfo::availableDevices(QAudio::Mode mode)
Q_UNUSED(mode)
QList<QByteArray> devices;
-#ifndef Q_OS_WINCE
//enumerate device fullnames through directshow api
CoInitialize(NULL);
ICreateDevEnum *pDevEnum = NULL;
@@ -454,55 +453,18 @@ QList<QByteArray> QWindowsAudioDeviceInfo::availableDevices(QAudio::Mode mode)
pDevEnum->Release();
}
CoUninitialize();
-#else // Q_OS_WINCE
- if (mode == QAudio::AudioOutput) {
- WAVEOUTCAPS woc;
- unsigned long iNumDevs,i;
- iNumDevs = waveOutGetNumDevs();
- for (i=0;i<iNumDevs;i++) {
- if (waveOutGetDevCaps(i, &woc, sizeof(WAVEOUTCAPS))
- == MMSYSERR_NOERROR) {
- QByteArray device;
- QDataStream ds(&device, QIODevice::WriteOnly);
- ds << quint32(i) << QString::fromWCharArray(woc.szPname);
- devices.append(device);
- }
- }
- } else {
- WAVEINCAPS woc;
- unsigned long iNumDevs,i;
- iNumDevs = waveInGetNumDevs();
- for (i=0;i<iNumDevs;i++) {
- if (waveInGetDevCaps(i, &woc, sizeof(WAVEINCAPS))
- == MMSYSERR_NOERROR) {
- QByteArray device;
- QDataStream ds(&device, QIODevice::WriteOnly);
- ds << quint32(i) << QString::fromWCharArray(woc.szPname);
- devices.append(device);
- }
- }
- }
-#endif // !Q_OS_WINCE
return devices;
}
-QByteArray QWindowsAudioDeviceInfo::defaultOutputDevice()
-{
- QByteArray defaultDevice;
- QDataStream ds(&defaultDevice, QIODevice::WriteOnly);
- ds << quint32(WAVE_MAPPER) // device ID for default device
- << QStringLiteral("Default Output Device");
-
- return defaultDevice;
-}
-
-QByteArray QWindowsAudioDeviceInfo::defaultInputDevice()
+QByteArray QWindowsAudioDeviceInfo::defaultDevice(QAudio::Mode mode)
{
+ const QString &name = (mode == QAudio::AudioOutput) ? QStringLiteral("Default Output Device")
+ : QStringLiteral("Default Input Device");
QByteArray defaultDevice;
QDataStream ds(&defaultDevice, QIODevice::WriteOnly);
ds << quint32(WAVE_MAPPER) // device ID for default device
- << QStringLiteral("Default Input Device");
+ << name;
return defaultDevice;
}
diff --git a/src/plugins/windowsaudio/qwindowsaudiodeviceinfo.h b/src/plugins/windowsaudio/qwindowsaudiodeviceinfo.h
index d4833d3fc..d84eb8acf 100644
--- a/src/plugins/windowsaudio/qwindowsaudiodeviceinfo.h
+++ b/src/plugins/windowsaudio/qwindowsaudiodeviceinfo.h
@@ -88,8 +88,7 @@ public:
QList<int> supportedSampleSizes();
QList<QAudioFormat::Endian> supportedByteOrders();
QList<QAudioFormat::SampleType> supportedSampleTypes();
- static QByteArray defaultInputDevice();
- static QByteArray defaultOutputDevice();
+ static QByteArray defaultDevice(QAudio::Mode mode);
static QList<QByteArray> availableDevices(QAudio::Mode);
private:
diff --git a/src/plugins/windowsaudio/qwindowsaudioplugin.cpp b/src/plugins/windowsaudio/qwindowsaudioplugin.cpp
index ba1dba4c2..8f532fa70 100644
--- a/src/plugins/windowsaudio/qwindowsaudioplugin.cpp
+++ b/src/plugins/windowsaudio/qwindowsaudioplugin.cpp
@@ -49,6 +49,11 @@ QWindowsAudioPlugin::QWindowsAudioPlugin(QObject *parent)
{
}
+QByteArray QWindowsAudioPlugin::defaultDevice(QAudio::Mode mode) const
+{
+ return QWindowsAudioDeviceInfo::defaultDevice(mode);
+}
+
QList<QByteArray> QWindowsAudioPlugin::availableDevices(QAudio::Mode mode) const
{
return QWindowsAudioDeviceInfo::availableDevices(mode);
diff --git a/src/plugins/windowsaudio/qwindowsaudioplugin.h b/src/plugins/windowsaudio/qwindowsaudioplugin.h
index fb4749e0d..7b500a39c 100644
--- a/src/plugins/windowsaudio/qwindowsaudioplugin.h
+++ b/src/plugins/windowsaudio/qwindowsaudioplugin.h
@@ -41,19 +41,22 @@
#define QWINDOWSAUDIOPLUGIN_H
#include <QtMultimedia/qaudiosystemplugin.h>
+#include <QtMultimedia/private/qaudiosystempluginext_p.h>
QT_BEGIN_NAMESPACE
-class QWindowsAudioPlugin : public QAudioSystemPlugin
+class QWindowsAudioPlugin : public QAudioSystemPlugin, public QAudioSystemPluginExtension
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.qt.audiosystemfactory/5.0" FILE "windowsaudio.json")
+ Q_INTERFACES(QAudioSystemPluginExtension)
public:
QWindowsAudioPlugin(QObject *parent = 0);
~QWindowsAudioPlugin() {}
+ QByteArray defaultDevice(QAudio::Mode mode) const Q_DECL_OVERRIDE;
QList<QByteArray> availableDevices(QAudio::Mode mode) const Q_DECL_OVERRIDE;
QAbstractAudioInput *createInput(const QByteArray &device) Q_DECL_OVERRIDE;
QAbstractAudioOutput *createOutput(const QByteArray &device) Q_DECL_OVERRIDE;
diff --git a/src/plugins/windowsaudio/windowsaudio.pro b/src/plugins/windowsaudio/windowsaudio.pro
index ce64847dc..6d5fe9495 100644
--- a/src/plugins/windowsaudio/windowsaudio.pro
+++ b/src/plugins/windowsaudio/windowsaudio.pro
@@ -1,8 +1,7 @@
TARGET = qtaudio_windows
QT += multimedia-private
-LIBS += -lstrmiids -lole32 -loleaut32
-!wince*:LIBS += -lwinmm
+LIBS += -lstrmiids -lole32 -loleaut32 -lwinmm
HEADERS += \
qwindowsaudioplugin.h \
diff --git a/src/plugins/winrt/qwinrtcameracontrol.cpp b/src/plugins/winrt/qwinrtcameracontrol.cpp
index c32a5f2e2..f81a2e94d 100644
--- a/src/plugins/winrt/qwinrtcameracontrol.cpp
+++ b/src/plugins/winrt/qwinrtcameracontrol.cpp
@@ -42,6 +42,7 @@
#include "qwinrtvideodeviceselectorcontrol.h"
#include "qwinrtcameraimagecapturecontrol.h"
#include "qwinrtimageencodercontrol.h"
+#include "qwinrtcameraflashcontrol.h"
#include "qwinrtcamerafocuscontrol.h"
#include "qwinrtcameralockscontrol.h"
@@ -554,6 +555,7 @@ public:
QPointer<QWinRTVideoDeviceSelectorControl> videoDeviceSelector;
QPointer<QWinRTCameraImageCaptureControl> imageCaptureControl;
QPointer<QWinRTImageEncoderControl> imageEncoderControl;
+ QPointer<QWinRTCameraFlashControl> cameraFlashControl;
QPointer<QWinRTCameraFocusControl> cameraFocusControl;
QPointer<QWinRTCameraLocksControl> cameraLocksControl;
QAtomicInt framesMapped;
@@ -578,6 +580,7 @@ QWinRTCameraControl::QWinRTCameraControl(QObject *parent)
d->videoDeviceSelector = new QWinRTVideoDeviceSelectorControl(this);
d->imageCaptureControl = new QWinRTCameraImageCaptureControl(this);
d->imageEncoderControl = new QWinRTImageEncoderControl(this);
+ d->cameraFlashControl = new QWinRTCameraFlashControl(this);
d->cameraFocusControl = new QWinRTCameraFocusControl(this);
d->cameraLocksControl = new QWinRTCameraLocksControl(this);
@@ -815,6 +818,12 @@ QImageEncoderControl *QWinRTCameraControl::imageEncoderControl() const
return d->imageEncoderControl;
}
+QCameraFlashControl *QWinRTCameraControl::cameraFlashControl() const
+{
+ Q_D(const QWinRTCameraControl);
+ return d->cameraFlashControl;
+}
+
QCameraFocusControl *QWinRTCameraControl::cameraFocusControl() const
{
Q_D(const QWinRTCameraControl);
@@ -940,6 +949,8 @@ HRESULT QWinRTCameraControl::initialize()
hr = advancedVideoDeviceController->get_FocusControl(&d->focusControl);
Q_ASSERT_SUCCEEDED(hr);
+ d->cameraFlashControl->initialize(advancedVideoDeviceController);
+
boolean isFocusSupported;
hr = d->focusControl->get_Supported(&isFocusSupported);
Q_ASSERT_SUCCEEDED(hr);
diff --git a/src/plugins/winrt/qwinrtcameracontrol.h b/src/plugins/winrt/qwinrtcameracontrol.h
index 85dd4d44b..f978a8b2c 100644
--- a/src/plugins/winrt/qwinrtcameracontrol.h
+++ b/src/plugins/winrt/qwinrtcameracontrol.h
@@ -69,6 +69,7 @@ class QVideoRendererControl;
class QVideoDeviceSelectorControl;
class QCameraImageCaptureControl;
class QImageEncoderControl;
+class QCameraFlashControl;
class QCameraFocusControl;
class QCameraLocksControl;
@@ -95,6 +96,7 @@ public:
QVideoDeviceSelectorControl *videoDeviceSelector() const;
QCameraImageCaptureControl *imageCaptureControl() const;
QImageEncoderControl *imageEncoderControl() const;
+ QCameraFlashControl *cameraFlashControl() const;
QCameraFocusControl *cameraFocusControl() const;
QCameraLocksControl *cameraLocksControl() const;
diff --git a/src/plugins/winrt/qwinrtcameraflashcontrol.cpp b/src/plugins/winrt/qwinrtcameraflashcontrol.cpp
new file mode 100644
index 000000000..1ea877672
--- /dev/null
+++ b/src/plugins/winrt/qwinrtcameraflashcontrol.cpp
@@ -0,0 +1,191 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd and/or its subsidiary(-ies).
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwinrtcameraflashcontrol.h"
+#include "qwinrtcameracontrol.h"
+#include <QtCore/QTimer>
+#include <QtCore/qfunctions_winrt.h>
+#include <QtCore/private/qeventdispatcher_winrt_p.h>
+
+#include <windows.media.devices.h>
+#include <wrl.h>
+#include <functional>
+
+using namespace Microsoft::WRL;
+using namespace ABI::Windows::Media::Devices;
+
+QT_BEGIN_NAMESPACE
+
+class QWinRTCameraFlashControlPrivate
+{
+public:
+ ComPtr<IFlashControl> flashControl;
+
+ QList<QCameraExposure::FlashModes> supportedModes;
+ QCameraExposure::FlashModes currentModes;
+ bool initialized;
+};
+
+QWinRTCameraFlashControl::QWinRTCameraFlashControl(QWinRTCameraControl *parent)
+ : QCameraFlashControl(parent), d_ptr(new QWinRTCameraFlashControlPrivate)
+{
+ qCDebug(lcMMCamera) << __FUNCTION__ << parent;
+ Q_D(QWinRTCameraFlashControl);
+
+ d->initialized = false;
+ d->currentModes = QCameraExposure::FlashOff;
+}
+
+void QWinRTCameraFlashControl::initialize(Microsoft::WRL::ComPtr<IAdvancedVideoCaptureDeviceController2> &controller)
+{
+ qCDebug(lcMMCamera) << __FUNCTION__;
+ Q_D(QWinRTCameraFlashControl);
+
+ d->initialized = false;
+
+ d->supportedModes.clear();
+ HRESULT hr;
+ hr = QEventDispatcherWinRT::runOnXamlThread([d, controller]() {
+ HRESULT hr;
+ hr = controller->get_FlashControl(&d->flashControl);
+ RETURN_HR_IF_FAILED("Could not access flash control.");
+
+ boolean oldAuto;
+ boolean oldEnabled;
+ // IFlashControl::get_Supported() is only valid for additional
+ // controls (RedEye, etc.) so we have to manually try to set
+ // and reset flash
+ if (SUCCEEDED(d->flashControl->get_Auto(&oldAuto))) {
+ hr = d->flashControl->put_Auto(!oldAuto);
+ if (SUCCEEDED(hr)) {
+ d->flashControl->put_Auto(oldAuto);
+ d->supportedModes.append(QCameraExposure::FlashAuto);
+ }
+ }
+
+ if (SUCCEEDED(d->flashControl->get_Enabled(&oldEnabled))) {
+ hr = d->flashControl->put_Enabled(!oldEnabled);
+ if (SUCCEEDED(hr)) {
+ d->flashControl->put_Enabled(oldEnabled);
+ d->supportedModes.append(QCameraExposure::FlashOff);
+ d->supportedModes.append(QCameraExposure::FlashOn);
+ }
+ }
+
+ boolean val;
+ hr = d->flashControl->get_Supported(&val);
+ if (SUCCEEDED(hr) && val) {
+ hr = d->flashControl->get_RedEyeReductionSupported(&val);
+ if (SUCCEEDED(hr) && val)
+ d->supportedModes.append(QCameraExposure::FlashRedEyeReduction);
+
+ // ### There is no Qt API to actually set the power values.
+ // However query if the camera could theoretically do it
+ hr = d->flashControl->get_PowerSupported(&val);
+ if (SUCCEEDED(hr) && val)
+ d->supportedModes.append(QCameraExposure::FlashManual);
+ }
+
+ return S_OK;
+ });
+ Q_ASSERT_SUCCEEDED(hr);
+ d->initialized = true;
+ setFlashMode(d->currentModes);
+}
+
+QCameraExposure::FlashModes QWinRTCameraFlashControl::flashMode() const
+{
+ Q_D(const QWinRTCameraFlashControl);
+ return d->currentModes;
+}
+
+void QWinRTCameraFlashControl::setFlashMode(QCameraExposure::FlashModes mode)
+{
+ qCDebug(lcMMCamera) << __FUNCTION__ << mode;
+ Q_D(QWinRTCameraFlashControl);
+
+ if (!d->initialized) {
+ d->currentModes = mode;
+ return;
+ }
+
+ if (!isFlashModeSupported(mode))
+ return;
+
+ QEventDispatcherWinRT::runOnXamlThread([d, mode]() {
+ HRESULT hr;
+ if (mode.testFlag(QCameraExposure::FlashAuto)) {
+ hr = d->flashControl->put_Enabled(true);
+ RETURN_OK_IF_FAILED("Could not set flash mode on.");
+ hr = d->flashControl->put_Auto(true);
+ RETURN_OK_IF_FAILED("Could not set flash mode auto.");
+ d->currentModes = QCameraExposure::FlashAuto;
+ } else if (mode.testFlag(QCameraExposure::FlashOn)) {
+ hr = d->flashControl->put_Enabled(true);
+ RETURN_OK_IF_FAILED("Could not set flash mode on.");
+ hr = d->flashControl->put_Auto(false);
+ RETURN_OK_IF_FAILED("Could not disable flash auto mode.");
+ d->currentModes = QCameraExposure::FlashOn;
+ } else if (mode.testFlag(QCameraExposure::FlashRedEyeReduction)) {
+ hr = d->flashControl->put_Enabled(true);
+ RETURN_OK_IF_FAILED("Could not set flash mode on.");
+ hr = d->flashControl->put_RedEyeReduction(true);
+ RETURN_OK_IF_FAILED("Could not set flash mode red eye reduction.");
+ d->currentModes = QCameraExposure::FlashRedEyeReduction;
+ } else {
+ hr = d->flashControl->put_Enabled(false);
+ RETURN_OK_IF_FAILED("Could not set flash mode off.");
+ d->currentModes = QCameraExposure::FlashOff;
+ }
+ return S_OK;
+ });
+}
+
+bool QWinRTCameraFlashControl::isFlashModeSupported(QCameraExposure::FlashModes mode) const
+{
+ Q_D(const QWinRTCameraFlashControl);
+ qCDebug(lcMMCamera) << __FUNCTION__ << mode;
+ return d->initialized ? d->supportedModes.contains(mode) : false;
+}
+
+bool QWinRTCameraFlashControl::isFlashReady() const
+{
+ qCDebug(lcMMCamera) << __FUNCTION__;
+ // No native API to query state
+ return true;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/winrt/qwinrtcameraflashcontrol.h b/src/plugins/winrt/qwinrtcameraflashcontrol.h
new file mode 100644
index 000000000..335329037
--- /dev/null
+++ b/src/plugins/winrt/qwinrtcameraflashcontrol.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd and/or its subsidiary(-ies).
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINRTCAMERAFLASHCONTROL_H
+#define QWINRTCAMERAFLASHCONTROL_H
+#include <qcameraflashcontrol.h>
+
+#include <wrl.h>
+
+namespace ABI {
+ namespace Windows {
+ namespace Media {
+ namespace Devices {
+ struct IAdvancedVideoCaptureDeviceController2;
+ }
+ }
+ }
+}
+
+QT_BEGIN_NAMESPACE
+
+class QWinRTCameraControl;
+class QWinRTCameraFlashControlPrivate;
+class QWinRTCameraFlashControl : public QCameraFlashControl
+{
+ Q_OBJECT
+public:
+ explicit QWinRTCameraFlashControl(QWinRTCameraControl *parent);
+
+ void initialize(Microsoft::WRL::ComPtr<ABI::Windows::Media::Devices::IAdvancedVideoCaptureDeviceController2> &controller);
+
+ QCameraExposure::FlashModes flashMode() const Q_DECL_OVERRIDE;
+ void setFlashMode(QCameraExposure::FlashModes mode) Q_DECL_OVERRIDE;
+ bool isFlashModeSupported(QCameraExposure::FlashModes mode) const Q_DECL_OVERRIDE;
+
+ bool isFlashReady() const Q_DECL_OVERRIDE;
+
+private:
+ QScopedPointer<QWinRTCameraFlashControlPrivate> d_ptr;
+ Q_DECLARE_PRIVATE(QWinRTCameraFlashControl)
+};
+
+#endif // QWINRTCAMERAFLASHCONTROL_H
diff --git a/src/plugins/winrt/qwinrtcamerafocuscontrol.cpp b/src/plugins/winrt/qwinrtcamerafocuscontrol.cpp
index ef637ac37..aeefc9241 100644
--- a/src/plugins/winrt/qwinrtcamerafocuscontrol.cpp
+++ b/src/plugins/winrt/qwinrtcamerafocuscontrol.cpp
@@ -79,7 +79,41 @@ QCameraFocus::FocusModes QWinRTCameraFocusControl::focusMode() const
void QWinRTCameraFocusControl::setFocusMode(QCameraFocus::FocusModes modes)
{
- QMetaObject::invokeMethod(this, "applyFocusMode", Qt::QueuedConnection, Q_ARG(QCameraFocus::FocusModes, modes));
+ Q_D(QWinRTCameraFocusControl);
+ if (d->focusModes == modes)
+ return;
+ QWinRTCameraControl *cameraControl = static_cast<QWinRTCameraControl *>(parent());
+ Q_ASSERT(cameraControl);
+ if (!modes) {
+ cameraControl->emitError(QCamera::InvalidRequestError, QStringLiteral("Can't set empty camera focus modes."));
+ return;
+ }
+ if (!d->focusModeInitialized) {
+ d->focusModes = modes;
+ emit focusModeChanged(modes);
+ return;
+ }
+ if (!isFocusModeSupported(modes)) {
+ cameraControl->emitError(QCamera::NotSupportedFeatureError, QStringLiteral("Unsupported camera focus modes."));
+ return;
+ }
+ if (modes.testFlag(QCameraFocus::ContinuousFocus)) {
+ if (QCameraFocus::FocusPointCustom == d->focusPointMode) {
+ cameraControl->emitError(QCamera::NotSupportedFeatureError,
+ QStringLiteral("Unsupported camera focus modes: ContinuousFocus with FocusPointCustom."));
+ return;
+ } else if (!d->imageCaptureIdle) {
+ cameraControl->emitError(QCamera::NotSupportedFeatureError,
+ QStringLiteral("Can't set ContinuousFocus camera focus mode while capturing image."));
+ return;
+ }
+ }
+ if (!cameraControl->setFocus(modes))
+ return;
+ if (modes.testFlag(QCameraFocus::ContinuousFocus) || d->focusModes.testFlag(QCameraFocus::ContinuousFocus))
+ cameraControl->focus();
+ d->focusModes = modes;
+ emit focusModeChanged(modes);
}
bool QWinRTCameraFocusControl::isFocusModeSupported(QCameraFocus::FocusModes modes) const
@@ -96,7 +130,32 @@ QCameraFocus::FocusPointMode QWinRTCameraFocusControl::focusPointMode() const
void QWinRTCameraFocusControl::setFocusPointMode(QCameraFocus::FocusPointMode mode)
{
- QMetaObject::invokeMethod(this, "applyFocusPointMode", Qt::QueuedConnection, Q_ARG(QCameraFocus::FocusPointMode, mode));
+ Q_D(QWinRTCameraFocusControl);
+ if (d->focusPointMode == mode)
+ return;
+
+ if (!d->focusModeInitialized) {
+ d->focusPointMode = mode;
+ emit focusPointModeChanged(mode);
+ return;
+ }
+ QWinRTCameraControl *cameraControl = static_cast<QWinRTCameraControl *>(parent());
+ Q_ASSERT(cameraControl);
+ if (!d->supportedFocusPointModes.contains(mode)) {
+ cameraControl->emitError(QCamera::NotSupportedFeatureError, QStringLiteral("Unsupported camera point focus mode."));
+ return;
+ }
+ if (QCameraFocus::FocusPointCenter == mode || QCameraFocus::FocusPointAuto == mode)
+ d->focusPoint = QPointF(0.5, 0.5);
+ // Don't apply focus point focus settings if camera is in continuous focus mode
+ if (!d->focusModes.testFlag(QCameraFocus::ContinuousFocus)) {
+ changeFocusCustomPoint(d->focusPoint);
+ } else if (QCameraFocus::FocusPointCustom == mode) {
+ cameraControl->emitError(QCamera::NotSupportedFeatureError, QStringLiteral("Unsupported camera focus modes: ContinuousFocus with FocusPointCustom."));
+ return;
+ }
+ d->focusPointMode = mode;
+ emit focusPointModeChanged(mode);
}
bool QWinRTCameraFocusControl::isFocusPointModeSupported(QCameraFocus::FocusPointMode mode) const
@@ -113,7 +172,20 @@ QPointF QWinRTCameraFocusControl::customFocusPoint() const
void QWinRTCameraFocusControl::setCustomFocusPoint(const QPointF &point)
{
- QMetaObject::invokeMethod(this, "applyFocusCustomPoint", Qt::QueuedConnection, Q_ARG(const QPointF, point));
+ Q_D(QWinRTCameraFocusControl);
+ if (d->focusPointMode != QCameraFocus::FocusPointCustom) {
+ QWinRTCameraControl *cameraControl = static_cast<QWinRTCameraControl *>(parent());
+ Q_ASSERT(cameraControl);
+ cameraControl->emitError(QCamera::InvalidRequestError, QStringLiteral("Custom focus point can be set only in FocusPointCustom focus mode."));
+ return;
+ }
+ if (d->focusPoint == point)
+ return;
+ if (changeFocusCustomPoint(point)) {
+ d->focusPoint = point;
+ emit customFocusPointChanged(point);
+ }
+
}
QCameraFocusZoneList QWinRTCameraFocusControl::focusZones() const
@@ -176,92 +248,6 @@ void QWinRTCameraFocusControl::imageCaptureQueueChanged(bool isEmpty)
d->imageCaptureIdle = isEmpty;
}
-void QWinRTCameraFocusControl::applyFocusCustomPoint(const QPointF &point)
-{
- Q_D(QWinRTCameraFocusControl);
- if (d->focusPointMode != QCameraFocus::FocusPointCustom) {
- QWinRTCameraControl *cameraControl = static_cast<QWinRTCameraControl *>(parent());
- Q_ASSERT(cameraControl);
- cameraControl->emitError(QCamera::InvalidRequestError, QStringLiteral("Custom focus point can be set only in FocusPointCustom focus mode."));
- return;
- }
- if (d->focusPoint == point)
- return;
- if (changeFocusCustomPoint(point)) {
- d->focusPoint = point;
- emit customFocusPointChanged(point);
- }
-}
-
-void QWinRTCameraFocusControl::applyFocusMode(QCameraFocus::FocusModes modes)
-{
- Q_D(QWinRTCameraFocusControl);
- if (d->focusModes == modes)
- return;
- QWinRTCameraControl *cameraControl = static_cast<QWinRTCameraControl *>(parent());
- Q_ASSERT(cameraControl);
- if (!modes) {
- cameraControl->emitError(QCamera::InvalidRequestError, QStringLiteral("Can't set empty camera focus modes."));
- return;
- }
- if (!d->focusModeInitialized) {
- d->focusModes = modes;
- emit focusModeChanged(modes);
- return;
- }
- if (!isFocusModeSupported(modes)) {
- cameraControl->emitError(QCamera::NotSupportedFeatureError, QStringLiteral("Unsupported camera focus modes."));
- return;
- }
- if (modes.testFlag(QCameraFocus::ContinuousFocus)) {
- if (QCameraFocus::FocusPointCustom == d->focusPointMode) {
- cameraControl->emitError(QCamera::NotSupportedFeatureError,
- QStringLiteral("Unsupported camera focus modes: ContinuousFocus with FocusPointCustom."));
- return;
- } else if (!d->imageCaptureIdle) {
- cameraControl->emitError(QCamera::NotSupportedFeatureError,
- QStringLiteral("Can't set ContinuousFocus camera focus mode while capturing image."));
- return;
- }
- }
- if (!cameraControl->setFocus(modes))
- return;
- if (modes.testFlag(QCameraFocus::ContinuousFocus) || d->focusModes.testFlag(QCameraFocus::ContinuousFocus))
- cameraControl->focus();
- d->focusModes = modes;
- emit focusModeChanged(modes);
-}
-
-void QWinRTCameraFocusControl::applyFocusPointMode(QCameraFocus::FocusPointMode mode)
-{
- Q_D(QWinRTCameraFocusControl);
- if (d->focusPointMode == mode)
- return;
-
- if (!d->focusModeInitialized) {
- d->focusPointMode = mode;
- emit focusPointModeChanged(mode);
- return;
- }
- QWinRTCameraControl *cameraControl = static_cast<QWinRTCameraControl *>(parent());
- Q_ASSERT(cameraControl);
- if (!d->supportedFocusPointModes.contains(mode)) {
- cameraControl->emitError(QCamera::NotSupportedFeatureError, QStringLiteral("Unsupported camera point focus mode."));
- return;
- }
- if (QCameraFocus::FocusPointCenter == mode || QCameraFocus::FocusPointAuto == mode)
- d->focusPoint = QPointF(0.5, 0.5);
- // Don't apply focus point focus settings if camera is in continuous focus mode
- if (!d->focusModes.testFlag(QCameraFocus::ContinuousFocus)) {
- changeFocusCustomPoint(d->focusPoint);
- } else if (QCameraFocus::FocusPointCustom == mode) {
- cameraControl->emitError(QCamera::NotSupportedFeatureError, QStringLiteral("Unsupported camera focus modes: ContinuousFocus with FocusPointCustom."));
- return;
- }
- d->focusPointMode = mode;
- emit focusPointModeChanged(mode);
-}
-
bool QWinRTCameraFocusControl::changeFocusCustomPoint(const QPointF &point)
{
Q_D(QWinRTCameraFocusControl);
diff --git a/src/plugins/winrt/qwinrtcamerafocuscontrol.h b/src/plugins/winrt/qwinrtcamerafocuscontrol.h
index 6ec2ea67a..0a8c0afcf 100644
--- a/src/plugins/winrt/qwinrtcamerafocuscontrol.h
+++ b/src/plugins/winrt/qwinrtcamerafocuscontrol.h
@@ -68,9 +68,6 @@ private slots:
void imageCaptureQueueChanged(bool isEmpty);
private:
- Q_INVOKABLE void applyFocusCustomPoint(const QPointF &point);
- Q_INVOKABLE void applyFocusMode(QCameraFocus::FocusModes modes);
- Q_INVOKABLE void applyFocusPointMode(QCameraFocus::FocusPointMode mode);
bool changeFocusCustomPoint(const QPointF &point);
QScopedPointer<QWinRTCameraFocusControlPrivate> d_ptr;
diff --git a/src/plugins/winrt/qwinrtcameraservice.cpp b/src/plugins/winrt/qwinrtcameraservice.cpp
index f76edae51..d0327a708 100644
--- a/src/plugins/winrt/qwinrtcameraservice.cpp
+++ b/src/plugins/winrt/qwinrtcameraservice.cpp
@@ -50,6 +50,7 @@
#include <QtMultimedia/QVideoRendererControl>
#include <QtMultimedia/QVideoDeviceSelectorControl>
#include <QtMultimedia/QImageEncoderControl>
+#include <QtMultimedia/QCameraFlashControl>
#include <QtMultimedia/QCameraFocusControl>
#include <QtMultimedia/QCameraLocksControl>
#include <QtMultimedia/QMediaVideoProbeControl>
@@ -98,6 +99,9 @@ QMediaControl *QWinRTCameraService::requestControl(const char *name)
if (qstrcmp(name, QImageEncoderControl_iid) == 0)
return d->cameraControl->imageEncoderControl();
+ if (qstrcmp(name, QCameraFlashControl_iid) == 0)
+ return d->cameraControl->cameraFlashControl();
+
if (qstrcmp(name, QCameraFocusControl_iid) == 0)
return d->cameraControl->cameraFocusControl();
diff --git a/src/plugins/winrt/qwinrtcameravideorenderercontrol.cpp b/src/plugins/winrt/qwinrtcameravideorenderercontrol.cpp
index 38273ba23..5f7810060 100644
--- a/src/plugins/winrt/qwinrtcameravideorenderercontrol.cpp
+++ b/src/plugins/winrt/qwinrtcameravideorenderercontrol.cpp
@@ -266,6 +266,9 @@ bool QWinRTCameraVideoRendererControlPrivate::getCameraSampleInfo(const ComPtr<I
case DXGI_FORMAT_NV12:
cameraSampleformat = QVideoFrame::Format_NV12;
break;
+ case DXGI_FORMAT_YUY2:
+ cameraSampleformat = QVideoFrame::Format_YUYV;
+ break;
default:
cameraSampleformat = QVideoFrame::Format_Invalid;
qErrnoWarning("Unsupported camera probe format.");
diff --git a/src/plugins/winrt/winrt.pro b/src/plugins/winrt/winrt.pro
index 87e44cce2..940064f46 100644
--- a/src/plugins/winrt/winrt.pro
+++ b/src/plugins/winrt/winrt.pro
@@ -6,6 +6,7 @@ LIBS += -lmfplat -lmfuuid -loleaut32 -ld3d11 -lruntimeobject
HEADERS += \
qwinrtabstractvideorenderercontrol.h \
qwinrtcameracontrol.h \
+ qwinrtcameraflashcontrol.h \
qwinrtcamerafocuscontrol.h \
qwinrtcameraimagecapturecontrol.h \
qwinrtcamerainfocontrol.h \
@@ -23,6 +24,7 @@ HEADERS += \
SOURCES += \
qwinrtabstractvideorenderercontrol.cpp \
qwinrtcameracontrol.cpp \
+ qwinrtcameraflashcontrol.cpp \
qwinrtcamerafocuscontrol.cpp \
qwinrtcameraimagecapturecontrol.cpp \
qwinrtcamerainfocontrol.cpp \
diff --git a/src/qtmultimediaquicktools/qsgvideonode_texture.cpp b/src/qtmultimediaquicktools/qsgvideonode_texture.cpp
index 599b70021..8080f3ec2 100644
--- a/src/qtmultimediaquicktools/qsgvideonode_texture.cpp
+++ b/src/qtmultimediaquicktools/qsgvideonode_texture.cpp
@@ -78,7 +78,7 @@ public:
QSGVideoMaterialShader_Texture()
: QSGMaterialShader()
{
- setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/qtmultimediaquicktools/shaders/rgbvideo.vert"));
+ setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/qtmultimediaquicktools/shaders/monoplanarvideo.vert"));
setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/qtmultimediaquicktools/shaders/rgbvideo.frag"));
}
diff --git a/src/qtmultimediaquicktools/qsgvideonode_yuv.cpp b/src/qtmultimediaquicktools/qsgvideonode_yuv.cpp
index 314a26264..68e6b456b 100644
--- a/src/qtmultimediaquicktools/qsgvideonode_yuv.cpp
+++ b/src/qtmultimediaquicktools/qsgvideonode_yuv.cpp
@@ -53,7 +53,8 @@ QList<QVideoFrame::PixelFormat> QSGVideoNodeFactory_YUV::supportedPixelFormats(
if (handleType == QAbstractVideoBuffer::NoHandle) {
formats << QVideoFrame::Format_YUV420P << QVideoFrame::Format_YV12
- << QVideoFrame::Format_NV12 << QVideoFrame::Format_NV21;
+ << QVideoFrame::Format_NV12 << QVideoFrame::Format_NV21
+ << QVideoFrame::Format_UYVY << QVideoFrame::Format_YUYV;
}
return formats;
@@ -109,6 +110,55 @@ protected:
int m_id_opacity;
};
+class QSGVideoMaterialShader_UYVY : public QSGMaterialShader
+{
+public:
+ QSGVideoMaterialShader_UYVY()
+ : QSGMaterialShader()
+ {
+ setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/qtmultimediaquicktools/shaders/monoplanarvideo.vert"));
+ setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/qtmultimediaquicktools/shaders/uyvyvideo.frag"));
+ }
+
+ void updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) Q_DECL_OVERRIDE;
+
+ char const *const *attributeNames() const Q_DECL_OVERRIDE {
+ static const char *names[] = {
+ "qt_VertexPosition",
+ "qt_VertexTexCoord",
+ 0
+ };
+ return names;
+ }
+
+protected:
+ void initialize() Q_DECL_OVERRIDE {
+ m_id_matrix = program()->uniformLocation("qt_Matrix");
+ m_id_yuvtexture = program()->uniformLocation("yuvTexture");
+ m_id_imageWidth = program()->uniformLocation("imageWidth");
+ m_id_colorMatrix = program()->uniformLocation("colorMatrix");
+ m_id_opacity = program()->uniformLocation("opacity");
+ QSGMaterialShader::initialize();
+ }
+
+ int m_id_matrix;
+ int m_id_yuvtexture;
+ int m_id_imageWidth;
+ int m_id_colorMatrix;
+ int m_id_opacity;
+};
+
+
+class QSGVideoMaterialShader_YUYV : public QSGVideoMaterialShader_UYVY
+{
+public:
+ QSGVideoMaterialShader_YUYV()
+ : QSGVideoMaterialShader_UYVY()
+ {
+ setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/qtmultimediaquicktools/shaders/yuyvvideo.frag"));
+ }
+};
+
class QSGVideoMaterialShader_YUV_BiPlanar_swizzle : public QSGVideoMaterialShader_YUV_BiPlanar
{
@@ -152,13 +202,17 @@ public:
~QSGVideoMaterial_YUV();
virtual QSGMaterialType *type() const {
- static QSGMaterialType biPlanarType, biPlanarSwizzleType, triPlanarType;
+ static QSGMaterialType biPlanarType, biPlanarSwizzleType, triPlanarType, uyvyType, yuyvType;
switch (m_format.pixelFormat()) {
case QVideoFrame::Format_NV12:
return &biPlanarType;
case QVideoFrame::Format_NV21:
return &biPlanarSwizzleType;
+ case QVideoFrame::Format_UYVY:
+ return &uyvyType;
+ case QVideoFrame::Format_YUYV:
+ return &yuyvType;
default: // Currently: YUV420P and YV12
return &triPlanarType;
}
@@ -170,6 +224,10 @@ public:
return new QSGVideoMaterialShader_YUV_BiPlanar;
case QVideoFrame::Format_NV21:
return new QSGVideoMaterialShader_YUV_BiPlanar_swizzle;
+ case QVideoFrame::Format_UYVY:
+ return new QSGVideoMaterialShader_UYVY;
+ case QVideoFrame::Format_YUYV:
+ return new QSGVideoMaterialShader_YUYV;
default: // Currently: YUV420P and YV12
return new QSGVideoMaterialShader_YUV_TriPlanar;
}
@@ -230,6 +288,8 @@ QSGVideoMaterial_YUV::QSGVideoMaterial_YUV(const QVideoSurfaceFormat &format) :
case QVideoFrame::Format_YV12:
m_planeCount = 3;
break;
+ case QVideoFrame::Format_UYVY:
+ case QVideoFrame::Format_YUYV:
default:
m_planeCount = 1;
break;
@@ -293,7 +353,15 @@ void QSGVideoMaterial_YUV::bind()
functions->glGetIntegerv(GL_UNPACK_ALIGNMENT, &previousAlignment);
functions->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- if (m_format.pixelFormat() == QVideoFrame::Format_NV12
+ if (m_format.pixelFormat() == QVideoFrame::Format_UYVY
+ || m_format.pixelFormat() == QVideoFrame::Format_YUYV) {
+ int fw = m_frame.width() / 2;
+ m_planeWidth[0] = fw;
+
+ functions->glActiveTexture(GL_TEXTURE0);
+ bindTexture(m_textureIds[0], fw, m_frame.height(), m_frame.bits(), GL_RGBA);
+
+ } else if (m_format.pixelFormat() == QVideoFrame::Format_NV12
|| m_format.pixelFormat() == QVideoFrame::Format_NV21) {
const int y = 0;
const int uv = 1;
@@ -338,7 +406,6 @@ void QSGVideoMaterial_YUV::bind()
void QSGVideoMaterial_YUV::bindTexture(int id, int w, int h, const uchar *bits, GLenum format)
{
QOpenGLFunctions *functions = QOpenGLContext::currentContext()->functions();
-
functions->glBindTexture(GL_TEXTURE_2D, id);
functions->glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, format, GL_UNSIGNED_BYTE, bits);
functions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@@ -399,4 +466,28 @@ void QSGVideoMaterialShader_YUV_TriPlanar::updateState(const RenderState &state,
program()->setUniformValue(m_id_plane3Width, mat->m_planeWidth[2]);
}
+void QSGVideoMaterialShader_UYVY::updateState(const RenderState &state,
+ QSGMaterial *newMaterial,
+ QSGMaterial *oldMaterial)
+{
+ Q_UNUSED(oldMaterial);
+
+ QSGVideoMaterial_YUV *mat = static_cast<QSGVideoMaterial_YUV *>(newMaterial);
+
+ program()->setUniformValue(m_id_yuvtexture, 0);
+
+ mat->bind();
+
+ program()->setUniformValue(m_id_colorMatrix, mat->m_colorMatrix);
+ program()->setUniformValue(m_id_imageWidth, mat->m_frame.width());
+
+ if (state.isOpacityDirty()) {
+ mat->m_opacity = state.opacity();
+ program()->setUniformValue(m_id_opacity, GLfloat(mat->m_opacity));
+ }
+
+ if (state.isMatrixDirty())
+ program()->setUniformValue(m_id_matrix, state.combinedMatrix());
+}
+
QT_END_NAMESPACE
diff --git a/src/qtmultimediaquicktools/qtmultimediaquicktools.pro b/src/qtmultimediaquicktools/qtmultimediaquicktools.pro
index e1425c3ec..e4e157a54 100644
--- a/src/qtmultimediaquicktools/qtmultimediaquicktools.pro
+++ b/src/qtmultimediaquicktools/qtmultimediaquicktools.pro
@@ -35,7 +35,7 @@ RESOURCES += \
qtmultimediaquicktools.qrc
OTHER_FILES += \
- shaders/rgbvideo.vert \
+ shaders/monoplanarvideo.vert \
shaders/rgbvideo_padded.vert \
shaders/rgbvideo.frag \
shaders/rgbvideo_swizzle.frag \
@@ -43,6 +43,8 @@ OTHER_FILES += \
shaders/biplanaryuvvideo.frag \
shaders/biplanaryuvvideo_swizzle.frag \
shaders/triplanaryuvvideo.vert \
- shaders/triplanaryuvvideo.frag
+ shaders/triplanaryuvvideo.frag \
+ shaders/uyvyvideo.frag \
+ shaders/yuyvvideo.frag
load(qt_module)
diff --git a/src/qtmultimediaquicktools/qtmultimediaquicktools.qrc b/src/qtmultimediaquicktools/qtmultimediaquicktools.qrc
index b0a7f0789..d5efb1f3e 100644
--- a/src/qtmultimediaquicktools/qtmultimediaquicktools.qrc
+++ b/src/qtmultimediaquicktools/qtmultimediaquicktools.qrc
@@ -1,6 +1,6 @@
<RCC>
<qresource prefix="/qtmultimediaquicktools">
- <file>shaders/rgbvideo.vert</file>
+ <file>shaders/monoplanarvideo.vert</file>
<file>shaders/rgbvideo.frag</file>
<file>shaders/rgbvideo_swizzle.frag</file>
<file>shaders/rgbvideo_padded.vert</file>
@@ -9,5 +9,7 @@
<file>shaders/biplanaryuvvideo_swizzle.frag</file>
<file>shaders/triplanaryuvvideo.frag</file>
<file>shaders/triplanaryuvvideo.vert</file>
+ <file>shaders/uyvyvideo.frag</file>
+ <file>shaders/yuyvvideo.frag</file>
</qresource>
</RCC>
diff --git a/src/qtmultimediaquicktools/shaders/rgbvideo.vert b/src/qtmultimediaquicktools/shaders/monoplanarvideo.vert
index 19915f2ff..19915f2ff 100644
--- a/src/qtmultimediaquicktools/shaders/rgbvideo.vert
+++ b/src/qtmultimediaquicktools/shaders/monoplanarvideo.vert
diff --git a/src/qtmultimediaquicktools/shaders/uyvyvideo.frag b/src/qtmultimediaquicktools/shaders/uyvyvideo.frag
new file mode 100644
index 000000000..905035703
--- /dev/null
+++ b/src/qtmultimediaquicktools/shaders/uyvyvideo.frag
@@ -0,0 +1,22 @@
+uniform sampler2D yuvTexture; // UYVY macropixel texture passed as RGBA format
+uniform mediump float imageWidth; // The UYVY texture appears to the shader with 1/2 the image width since we use the RGBA format to pass UYVY
+uniform mediump mat4 colorMatrix;
+uniform lowp float opacity;
+
+varying highp vec2 qt_TexCoord;
+
+void main()
+{
+ // For U0 Y0 V0 Y1 macropixel, lookup Y0 or Y1 based on whether
+ // the original texture x coord is even or odd.
+ mediump float Y;
+ if (fract(floor(qt_TexCoord.x * imageWidth + 0.5) / 2.0) > 0.0)
+ Y = texture2D(yuvTexture, qt_TexCoord).a; // odd so choose Y1
+ else
+ Y = texture2D(yuvTexture, qt_TexCoord).g; // even so choose Y0
+ mediump float Cb = texture2D(yuvTexture, qt_TexCoord).r;
+ mediump float Cr = texture2D(yuvTexture, qt_TexCoord).b;
+
+ mediump vec4 color = vec4(Y, Cb, Cr, 1.0);
+ gl_FragColor = colorMatrix * color * opacity;
+}
diff --git a/src/qtmultimediaquicktools/shaders/yuyvvideo.frag b/src/qtmultimediaquicktools/shaders/yuyvvideo.frag
new file mode 100644
index 000000000..72732cd66
--- /dev/null
+++ b/src/qtmultimediaquicktools/shaders/yuyvvideo.frag
@@ -0,0 +1,22 @@
+uniform sampler2D yuvTexture; // YUYV macropixel texture passed as RGBA format
+uniform mediump float imageWidth; // The YUYV texture appears to the shader with 1/2 the image width since we use the RGBA format to pass YUYV
+uniform mediump mat4 colorMatrix;
+uniform lowp float opacity;
+
+varying highp vec2 qt_TexCoord;
+
+void main()
+{
+ // For Y0 U0 Y1 V0 macropixel, lookup Y0 or Y1 based on whether
+ // the original texture x coord is even or odd.
+ mediump float Y;
+ if (fract(floor(qt_TexCoord.x * imageWidth + 0.5) / 2.0) > 0.0)
+ Y = texture2D(yuvTexture, qt_TexCoord).b; // odd so choose Y1
+ else
+ Y = texture2D(yuvTexture, qt_TexCoord).r; // even so choose Y0
+ mediump float Cb = texture2D(yuvTexture, qt_TexCoord).g;
+ mediump float Cr = texture2D(yuvTexture, qt_TexCoord).a;
+
+ mediump vec4 color = vec4(Y, Cb, Cr, 1.0);
+ gl_FragColor = colorMatrix * color * opacity;
+}
diff --git a/src/src.pro b/src/src.pro
index e8d430e51..17f3266c5 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -13,7 +13,7 @@ src_plugins.subdir = plugins
src_plugins.depends = multimedia
-qtHaveModule(quick) {
+qtHaveModule(quick):qtConfig(opengl) {
src_qtmultimediaquicktools.subdir = qtmultimediaquicktools
src_qtmultimediaquicktools.depends = multimedia
diff --git a/tests/auto/integration/qaudiodeviceinfo/tst_qaudiodeviceinfo.cpp b/tests/auto/integration/qaudiodeviceinfo/tst_qaudiodeviceinfo.cpp
index abc0b934b..9d44dc16f 100644
--- a/tests/auto/integration/qaudiodeviceinfo/tst_qaudiodeviceinfo.cpp
+++ b/tests/auto/integration/qaudiodeviceinfo/tst_qaudiodeviceinfo.cpp
@@ -190,7 +190,7 @@ void tst_QAudioDeviceInfo::supportedSampleRates()
void tst_QAudioDeviceInfo::assignOperator()
{
QAudioDeviceInfo dev;
- QVERIFY(dev.deviceName() == NULL);
+ QVERIFY(dev.deviceName().isNull());
QVERIFY(dev.isNull() == true);
QList<QAudioDeviceInfo> devices = QAudioDeviceInfo::availableDevices(QAudio::AudioOutput);
@@ -204,7 +204,7 @@ void tst_QAudioDeviceInfo::assignOperator()
// Returns human readable name of audio device
void tst_QAudioDeviceInfo::deviceName()
{
- QVERIFY(device->deviceName() != NULL);
+ QVERIFY(!device->deviceName().isNull());
QVERIFY(device->deviceName() == QAudioDeviceInfo::availableDevices(QAudio::AudioOutput).at(0).deviceName());
}
@@ -213,7 +213,7 @@ void tst_QAudioDeviceInfo::defaultConstructor()
{
QAudioDeviceInfo dev;
QVERIFY(dev.isNull() == true);
- QVERIFY(dev.deviceName() == NULL);
+ QVERIFY(dev.deviceName().isNull());
}
void tst_QAudioDeviceInfo::equalityOperator()
diff --git a/tests/auto/integration/qmediaplayerbackend/BLACKLIST b/tests/auto/integration/qmediaplayerbackend/BLACKLIST
index 43b8e8b26..5560abf75 100644
--- a/tests/auto/integration/qmediaplayerbackend/BLACKLIST
+++ b/tests/auto/integration/qmediaplayerbackend/BLACKLIST
@@ -19,13 +19,8 @@ opensuse-13.1 64bit
windows 64bit developer-build
[playPauseStop]
-opensuse-13.1 64bit
-redhatenterpriselinuxworkstation-6.6
-rhel-7.1
-ubuntu-14.04 64bit
-ubuntu-16.04 64bit
+linux
windows 64bit developer-build
-rhel-7.2
[processEOS]
opensuse-13.1 64bit
diff --git a/tests/auto/integration/qsoundeffect/BLACKLIST b/tests/auto/integration/qsoundeffect/BLACKLIST
new file mode 100644
index 000000000..692a9afd3
--- /dev/null
+++ b/tests/auto/integration/qsoundeffect/BLACKLIST
@@ -0,0 +1,2 @@
+[testSetSourceWhileLoading]
+linux
diff --git a/tests/auto/integration/qsoundeffect/qsoundeffect.pro b/tests/auto/integration/qsoundeffect/qsoundeffect.pro
index 7a0f63e4b..c4d965121 100644
--- a/tests/auto/integration/qsoundeffect/qsoundeffect.pro
+++ b/tests/auto/integration/qsoundeffect/qsoundeffect.pro
@@ -14,6 +14,3 @@ unix:!mac {
}
TESTDATA += test.wav
-
-
-config_pulseaudio: CONFIG += insignificant_testcase # Crashes in QSoundEffectPrivate::sampleReady with bufferAttr == 0
diff --git a/tests/auto/unit/multimediawidgets.pro b/tests/auto/unit/multimediawidgets.pro
index 31f8e546c..1bcfc6c2e 100644
--- a/tests/auto/unit/multimediawidgets.pro
+++ b/tests/auto/unit/multimediawidgets.pro
@@ -7,7 +7,7 @@ SUBDIRS += \
# Tests depending on private interfaces should only be built if
# these interfaces are exported.
-contains (QT_CONFIG, private_tests) {
+qtConfig(private_tests) {
SUBDIRS += \
qgraphicsvideoitem \
qpaintervideosurface \
diff --git a/tests/auto/unit/qaudionamespace/tst_qaudionamespace.cpp b/tests/auto/unit/qaudionamespace/tst_qaudionamespace.cpp
index ebc58b66b..5cd89ec3e 100644
--- a/tests/auto/unit/qaudionamespace/tst_qaudionamespace.cpp
+++ b/tests/auto/unit/qaudionamespace/tst_qaudionamespace.cpp
@@ -30,7 +30,7 @@
#include <QtTest/QtTest>
-#include "qaudio.h"
+#include <QtMultimedia/qaudio.h>
// Adds an enum, and the stringized version
#define ADD_ENUM_TEST(x) \
@@ -49,6 +49,10 @@ private slots:
void debugState_data();
void debugMode();
void debugMode_data();
+ void debugVolumeScale();
+ void debugVolumeScale_data();
+ void convertVolume();
+ void convertVolume_data();
};
void tst_QAudioNamespace::debugError_data()
@@ -109,6 +113,150 @@ void tst_QAudioNamespace::debugMode()
QTest::ignoreMessage(QtDebugMsg, stringized.toLatin1().constData());
qDebug() << mode;
}
+
+void tst_QAudioNamespace::debugVolumeScale_data()
+{
+ QTest::addColumn<QAudio::VolumeScale>("volumeScale");
+ QTest::addColumn<QString>("stringized");
+
+ ADD_ENUM_TEST(LinearVolumeScale);
+ ADD_ENUM_TEST(CubicVolumeScale);
+ ADD_ENUM_TEST(DecibelVolumeScale);
+}
+
+void tst_QAudioNamespace::debugVolumeScale()
+{
+ QFETCH(QAudio::VolumeScale, volumeScale);
+ QFETCH(QString, stringized);
+
+ QTest::ignoreMessage(QtDebugMsg, stringized.toLatin1().constData());
+ qDebug() << volumeScale;
+}
+
+void tst_QAudioNamespace::convertVolume_data()
+{
+ QTest::addColumn<qreal>("input");
+ QTest::addColumn<QAudio::VolumeScale>("from");
+ QTest::addColumn<QAudio::VolumeScale>("to");
+ QTest::addColumn<qreal>("expectedOutput");
+
+ QTest::newRow("-1.0 from linear to linear") << qreal(-1.0) << QAudio::LinearVolumeScale << QAudio::LinearVolumeScale << qreal(0.0);
+ QTest::newRow("0.0 from linear to linear") << qreal(0.0) << QAudio::LinearVolumeScale << QAudio::LinearVolumeScale << qreal(0.0);
+ QTest::newRow("0.5 from linear to linear") << qreal(0.5) << QAudio::LinearVolumeScale << QAudio::LinearVolumeScale << qreal(0.5);
+ QTest::newRow("1.0 from linear to linear") << qreal(1.0) << QAudio::LinearVolumeScale << QAudio::LinearVolumeScale << qreal(1.0);
+
+ QTest::newRow("-1.0 from linear to cubic") << qreal(-1.0) << QAudio::LinearVolumeScale << QAudio::CubicVolumeScale << qreal(0.0);
+ QTest::newRow("0.0 from linear to cubic") << qreal(0.0) << QAudio::LinearVolumeScale << QAudio::CubicVolumeScale << qreal(0.0);
+ QTest::newRow("0.33 from linear to cubic") << qreal(0.33) << QAudio::LinearVolumeScale << QAudio::CubicVolumeScale << qreal(0.69);
+ QTest::newRow("0.5 from linear to cubic") << qreal(0.5) << QAudio::LinearVolumeScale << QAudio::CubicVolumeScale << qreal(0.79);
+ QTest::newRow("0.72 from linear to cubic") << qreal(0.72) << QAudio::LinearVolumeScale << QAudio::CubicVolumeScale << qreal(0.89);
+ QTest::newRow("1.0 from linear to cubic") << qreal(1.0) << QAudio::LinearVolumeScale << QAudio::CubicVolumeScale << qreal(1.0);
+
+ QTest::newRow("-1.0 from linear to logarithmic") << qreal(-1.0) << QAudio::LinearVolumeScale << QAudio::LogarithmicVolumeScale << qreal(0.0);
+ QTest::newRow("0.0 from linear to logarithmic") << qreal(0.0) << QAudio::LinearVolumeScale << QAudio::LogarithmicVolumeScale << qreal(0.0);
+ QTest::newRow("0.33 from linear to logarithmic") << qreal(0.33) << QAudio::LinearVolumeScale << QAudio::LogarithmicVolumeScale << qreal(0.78);
+ QTest::newRow("0.5 from linear to logarithmic") << qreal(0.5) << QAudio::LinearVolumeScale << QAudio::LogarithmicVolumeScale << qreal(0.9);
+ QTest::newRow("0.72 from linear to logarithmic") << qreal(0.72) << QAudio::LinearVolumeScale << QAudio::LogarithmicVolumeScale << qreal(0.96);
+ QTest::newRow("1.0 from linear to logarithmic") << qreal(1.0) << QAudio::LinearVolumeScale << QAudio::LogarithmicVolumeScale << qreal(1.0);
+
+ QTest::newRow("-1.0 from linear to decibel") << qreal(-1.0) << QAudio::LinearVolumeScale << QAudio::DecibelVolumeScale << qreal(-200);
+ QTest::newRow("0.0 from linear to decibel") << qreal(0.0) << QAudio::LinearVolumeScale << QAudio::DecibelVolumeScale << qreal(-200);
+ QTest::newRow("0.33 from linear to decibel") << qreal(0.33) << QAudio::LinearVolumeScale << QAudio::DecibelVolumeScale << qreal(-9.63);
+ QTest::newRow("0.5 from linear to decibel") << qreal(0.5) << QAudio::LinearVolumeScale << QAudio::DecibelVolumeScale << qreal(-6.02);
+ QTest::newRow("0.72 from linear to decibel") << qreal(0.72) << QAudio::LinearVolumeScale << QAudio::DecibelVolumeScale << qreal(-2.85);
+ QTest::newRow("1.0 from linear to decibel") << qreal(1.0) << QAudio::LinearVolumeScale << QAudio::DecibelVolumeScale << qreal(0);
+
+ QTest::newRow("-1.0 from cubic to linear") << qreal(-1.0) << QAudio::CubicVolumeScale << QAudio::LinearVolumeScale << qreal(0.0);
+ QTest::newRow("0.0 from cubic to linear") << qreal(0.0) << QAudio::CubicVolumeScale << QAudio::LinearVolumeScale << qreal(0.0);
+ QTest::newRow("0.33 from cubic to linear") << qreal(0.33) << QAudio::CubicVolumeScale << QAudio::LinearVolumeScale << qreal(0.04);
+ QTest::newRow("0.5 from cubic to linear") << qreal(0.5) << QAudio::CubicVolumeScale << QAudio::LinearVolumeScale << qreal(0.13);
+ QTest::newRow("0.72 from cubic to linear") << qreal(0.72) << QAudio::CubicVolumeScale << QAudio::LinearVolumeScale << qreal(0.37);
+ QTest::newRow("1.0 from cubic to linear") << qreal(1.0) << QAudio::CubicVolumeScale << QAudio::LinearVolumeScale << qreal(1.0);
+
+ QTest::newRow("-1.0 from cubic to cubic") << qreal(-1.0) << QAudio::CubicVolumeScale << QAudio::CubicVolumeScale << qreal(0.0);
+ QTest::newRow("0.0 from cubic to cubic") << qreal(0.0) << QAudio::CubicVolumeScale << QAudio::CubicVolumeScale << qreal(0.0);
+ QTest::newRow("0.5 from cubic to cubic") << qreal(0.5) << QAudio::CubicVolumeScale << QAudio::CubicVolumeScale << qreal(0.5);
+ QTest::newRow("1.0 from cubic to cubic") << qreal(1.0) << QAudio::CubicVolumeScale << QAudio::CubicVolumeScale << qreal(1.0);
+
+ QTest::newRow("-1.0 from cubic to logarithmic") << qreal(-1.0) << QAudio::CubicVolumeScale << QAudio::LogarithmicVolumeScale << qreal(0.0);
+ QTest::newRow("0.0 from cubic to logarithmic") << qreal(0.0) << QAudio::CubicVolumeScale << QAudio::LogarithmicVolumeScale << qreal(0.0);
+ QTest::newRow("0.33 from cubic to logarithmic") << qreal(0.33) << QAudio::CubicVolumeScale << QAudio::LogarithmicVolumeScale << qreal(0.15);
+ QTest::newRow("0.5 from cubic to logarithmic") << qreal(0.5) << QAudio::CubicVolumeScale << QAudio::LogarithmicVolumeScale << qreal(0.44);
+ QTest::newRow("0.72 from cubic to logarithmic") << qreal(0.72) << QAudio::CubicVolumeScale << QAudio::LogarithmicVolumeScale << qreal(0.82);
+ QTest::newRow("1.0 from cubic to logarithmic") << qreal(1.0) << QAudio::CubicVolumeScale << QAudio::LogarithmicVolumeScale << qreal(1.0);
+
+ QTest::newRow("-1.0 from cubic to decibel") << qreal(-1.0) << QAudio::CubicVolumeScale << QAudio::DecibelVolumeScale << qreal(-200);
+ QTest::newRow("0.0 from cubic to decibel") << qreal(0.0) << QAudio::CubicVolumeScale << QAudio::DecibelVolumeScale << qreal(-200);
+ QTest::newRow("0.33 from cubic to decibel") << qreal(0.33) << QAudio::CubicVolumeScale << QAudio::DecibelVolumeScale << qreal(-28.89);
+ QTest::newRow("0.5 from cubic to decibel") << qreal(0.5) << QAudio::CubicVolumeScale << QAudio::DecibelVolumeScale << qreal(-18.06);
+ QTest::newRow("0.72 from cubic to decibel") << qreal(0.72) << QAudio::CubicVolumeScale << QAudio::DecibelVolumeScale << qreal(-8.56);
+ QTest::newRow("1.0 from cubic to decibel") << qreal(1.0) << QAudio::CubicVolumeScale << QAudio::DecibelVolumeScale << qreal(0);
+
+ QTest::newRow("-1.0 from logarithmic to linear") << qreal(-1.0) << QAudio::LogarithmicVolumeScale << QAudio::LinearVolumeScale << qreal(0.0);
+ QTest::newRow("0.0 from logarithmic to linear") << qreal(0.0) << QAudio::LogarithmicVolumeScale << QAudio::LinearVolumeScale << qreal(0.0);
+ QTest::newRow("0.33 from logarithmic to linear") << qreal(0.33) << QAudio::LogarithmicVolumeScale << QAudio::LinearVolumeScale << qreal(0.09);
+ QTest::newRow("0.5 from logarithmic to linear") << qreal(0.5) << QAudio::LogarithmicVolumeScale << QAudio::LinearVolumeScale << qreal(0.15);
+ QTest::newRow("0.72 from logarithmic to linear") << qreal(0.72) << QAudio::LogarithmicVolumeScale << QAudio::LinearVolumeScale << qreal(0.28);
+ QTest::newRow("1.0 from logarithmic to linear") << qreal(1.0) << QAudio::LogarithmicVolumeScale << QAudio::LinearVolumeScale << qreal(1.0);
+
+ QTest::newRow("-1.0 from logarithmic to cubic") << qreal(-1.0) << QAudio::LogarithmicVolumeScale << QAudio::CubicVolumeScale << qreal(0.0);
+ QTest::newRow("0.0 from logarithmic to cubic") << qreal(0.0) << QAudio::LogarithmicVolumeScale << QAudio::CubicVolumeScale << qreal(0.0);
+ QTest::newRow("0.33 from logarithmic to cubic") << qreal(0.33) << QAudio::LogarithmicVolumeScale << QAudio::CubicVolumeScale << qreal(0.44);
+ QTest::newRow("0.5 from logarithmic to cubic") << qreal(0.5) << QAudio::LogarithmicVolumeScale << QAudio::CubicVolumeScale << qreal(0.53);
+ QTest::newRow("0.72 from logarithmic to cubic") << qreal(0.72) << QAudio::LogarithmicVolumeScale << QAudio::CubicVolumeScale << qreal(0.65);
+ QTest::newRow("1.0 from logarithmic to cubic") << qreal(1.0) << QAudio::LogarithmicVolumeScale << QAudio::CubicVolumeScale << qreal(1.0);
+
+ QTest::newRow("-1.0 from logarithmic to logarithmic") << qreal(-1.0) << QAudio::LogarithmicVolumeScale << QAudio::LogarithmicVolumeScale << qreal(0.0);
+ QTest::newRow("0.0 from logarithmic to logarithmic") << qreal(0.0) << QAudio::LogarithmicVolumeScale << QAudio::LogarithmicVolumeScale << qreal(0.0);
+ QTest::newRow("0.5 from logarithmic to logarithmic") << qreal(0.5) << QAudio::LogarithmicVolumeScale << QAudio::LogarithmicVolumeScale << qreal(0.5);
+ QTest::newRow("1.0 from logarithmic to logarithmic") << qreal(1.0) << QAudio::LogarithmicVolumeScale << QAudio::LogarithmicVolumeScale << qreal(1.0);
+
+ QTest::newRow("-1.0 from logarithmic to decibel") << qreal(-1.0) << QAudio::LogarithmicVolumeScale << QAudio::DecibelVolumeScale << qreal(-200);
+ QTest::newRow("0.0 from logarithmic to decibel") << qreal(0.0) << QAudio::LogarithmicVolumeScale << QAudio::DecibelVolumeScale << qreal(-200);
+ QTest::newRow("0.33 from logarithmic to decibel") << qreal(0.33) << QAudio::LogarithmicVolumeScale << QAudio::DecibelVolumeScale << qreal(-21.21);
+ QTest::newRow("0.5 from logarithmic to decibel") << qreal(0.5) << QAudio::LogarithmicVolumeScale << QAudio::DecibelVolumeScale << qreal(-16.45);
+ QTest::newRow("0.72 from logarithmic to decibel") << qreal(0.72) << QAudio::LogarithmicVolumeScale << QAudio::DecibelVolumeScale << qreal(-11.17);
+ QTest::newRow("1.0 from logarithmic to decibel") << qreal(1.0) << QAudio::LogarithmicVolumeScale << QAudio::DecibelVolumeScale << qreal(0);
+
+ QTest::newRow("-1000 from decibel to linear") << qreal(-1000.0) << QAudio::DecibelVolumeScale << QAudio::LinearVolumeScale << qreal(0.0);
+ QTest::newRow("-200 from decibel to linear") << qreal(-200.0) << QAudio::DecibelVolumeScale << QAudio::LinearVolumeScale << qreal(0.0);
+ QTest::newRow("-40 from decibel to linear") << qreal(-40.0) << QAudio::DecibelVolumeScale << QAudio::LinearVolumeScale << qreal(0.01);
+ QTest::newRow("-10 from decibel to linear") << qreal(-10.0) << QAudio::DecibelVolumeScale << QAudio::LinearVolumeScale << qreal(0.32);
+ QTest::newRow("-5 from decibel to linear") << qreal(-5.0) << QAudio::DecibelVolumeScale << QAudio::LinearVolumeScale << qreal(0.56);
+ QTest::newRow("0 from decibel to linear") << qreal(0.0) << QAudio::DecibelVolumeScale << QAudio::LinearVolumeScale << qreal(1.0);
+
+ QTest::newRow("-1000 from decibel to cubic") << qreal(-1000.0) << QAudio::DecibelVolumeScale << QAudio::CubicVolumeScale << qreal(0.0);
+ QTest::newRow("-200 from decibel to cubic") << qreal(-200.0) << QAudio::DecibelVolumeScale << QAudio::CubicVolumeScale << qreal(0.0);
+ QTest::newRow("-40 from decibel to cubic") << qreal(-40.0) << QAudio::DecibelVolumeScale << QAudio::CubicVolumeScale << qreal(0.22);
+ QTest::newRow("-10 from decibel to cubic") << qreal(-10.0) << QAudio::DecibelVolumeScale << QAudio::CubicVolumeScale << qreal(0.68);
+ QTest::newRow("-5 from decibel to cubic") << qreal(-5.0) << QAudio::DecibelVolumeScale << QAudio::CubicVolumeScale << qreal(0.83);
+ QTest::newRow("0 from decibel to cubic") << qreal(0.0) << QAudio::DecibelVolumeScale << QAudio::CubicVolumeScale << qreal(1.0);
+
+ QTest::newRow("-1000 from decibel to logarithmic") << qreal(-1000.0) << QAudio::DecibelVolumeScale << QAudio::LogarithmicVolumeScale << qreal(0.0);
+ QTest::newRow("-200 from decibel to logarithmic") << qreal(-200.0) << QAudio::DecibelVolumeScale << QAudio::LogarithmicVolumeScale << qreal(0.0);
+ QTest::newRow("-40 from decibel to logarithmic") << qreal(-40.0) << QAudio::DecibelVolumeScale << QAudio::LogarithmicVolumeScale << qreal(0.05);
+ QTest::newRow("-10 from decibel to logarithmic") << qreal(-10.0) << QAudio::DecibelVolumeScale << QAudio::LogarithmicVolumeScale << qreal(0.77);
+ QTest::newRow("-5 from decibel to logarithmic") << qreal(-5.0) << QAudio::DecibelVolumeScale << QAudio::LogarithmicVolumeScale << qreal(0.92);
+ QTest::newRow("0 from decibel to logarithmic") << qreal(0.0) << QAudio::DecibelVolumeScale << QAudio::LogarithmicVolumeScale << qreal(1.0);
+
+ QTest::newRow("-1000 from decibel to decibel") << qreal(-1000.0) << QAudio::DecibelVolumeScale << QAudio::DecibelVolumeScale << qreal(-1000.0);
+ QTest::newRow("-200 from decibel to decibel") << qreal(-200.0) << QAudio::DecibelVolumeScale << QAudio::DecibelVolumeScale << qreal(-200.0);
+ QTest::newRow("-30 from decibel to decibel") << qreal(-30.0) << QAudio::DecibelVolumeScale << QAudio::DecibelVolumeScale << qreal(-30.0);
+ QTest::newRow("0 from decibel to decibel") << qreal(0.0) << QAudio::DecibelVolumeScale << QAudio::DecibelVolumeScale << qreal(0.0);
+}
+
+void tst_QAudioNamespace::convertVolume()
+{
+ QFETCH(qreal, input);
+ QFETCH(QAudio::VolumeScale, from);
+ QFETCH(QAudio::VolumeScale, to);
+ QFETCH(qreal, expectedOutput);
+
+ qreal actualOutput = QAudio::convertVolume(input, from, to);
+ QVERIFY2(qAbs(actualOutput - expectedOutput) < 0.01,
+ QString("actual: %1, expected: %2").arg(actualOutput).arg(expectedOutput).toLocal8Bit().constData());
+}
+
QTEST_MAIN(tst_QAudioNamespace)
#include "tst_qaudionamespace.moc"
diff --git a/tests/auto/unit/qdeclarativemultimediaglobal/tst_qdeclarativemultimediaglobal.qml b/tests/auto/unit/qdeclarativemultimediaglobal/tst_qdeclarativemultimediaglobal.qml
index bce0ca791..e44c68a29 100644
--- a/tests/auto/unit/qdeclarativemultimediaglobal/tst_qdeclarativemultimediaglobal.qml
+++ b/tests/auto/unit/qdeclarativemultimediaglobal/tst_qdeclarativemultimediaglobal.qml
@@ -63,4 +63,118 @@ TestCase {
compare(camera.orientation, 0, "orientation");
}
+ function test_convertVolume_data() {
+ return [
+ { tag: "-1.0 from linear to linear", input: -1, from: QtMultimedia.LinearVolumeScale, to: QtMultimedia.LinearVolumeScale, expectedOutput: 0 },
+ { tag: "0.0 from linear to linear", input: 0, from: QtMultimedia.LinearVolumeScale, to: QtMultimedia.LinearVolumeScale, expectedOutput: 0 },
+ { tag: "0.5 from linear to linear", input: 0.5, from: QtMultimedia.LinearVolumeScale, to: QtMultimedia.LinearVolumeScale, expectedOutput: 0.5 },
+ { tag: "1.0 from linear to linear", input: 1.0, from: QtMultimedia.LinearVolumeScale, to: QtMultimedia.LinearVolumeScale, expectedOutput: 1.0 },
+
+ { tag: "-1.0 from linear to cubic", input: -1, from: QtMultimedia.LinearVolumeScale, to: QtMultimedia.CubicVolumeScale, expectedOutput: 0 },
+ { tag: "0.0 from linear to cubic", input: 0, from: QtMultimedia.LinearVolumeScale, to: QtMultimedia.CubicVolumeScale, expectedOutput: 0 },
+ { tag: "0.33 from linear to cubic", input: 0.33, from: QtMultimedia.LinearVolumeScale, to: QtMultimedia.CubicVolumeScale, expectedOutput: 0.69 },
+ { tag: "0.5 from linear to cubic", input: 0.5, from: QtMultimedia.LinearVolumeScale, to: QtMultimedia.CubicVolumeScale, expectedOutput: 0.79 },
+ { tag: "0.72 from linear to cubic", input: 0.72, from: QtMultimedia.LinearVolumeScale, to: QtMultimedia.CubicVolumeScale, expectedOutput: 0.89 },
+ { tag: "1.0 from linear to cubic", input: 1.0, from: QtMultimedia.LinearVolumeScale, to: QtMultimedia.CubicVolumeScale, expectedOutput: 1.0 },
+
+ { tag: "-1.0 from linear to logarithmic", input: -1, from: QtMultimedia.LinearVolumeScale, to: QtMultimedia.LogarithmicVolumeScale, expectedOutput: 0 },
+ { tag: "0.0 from linear to logarithmic", input: 0, from: QtMultimedia.LinearVolumeScale, to: QtMultimedia.LogarithmicVolumeScale, expectedOutput: 0 },
+ { tag: "0.33 from linear to logarithmic", input: 0.33, from: QtMultimedia.LinearVolumeScale, to: QtMultimedia.LogarithmicVolumeScale, expectedOutput: 0.78 },
+ { tag: "0.5 from linear to logarithmic", input: 0.5, from: QtMultimedia.LinearVolumeScale, to: QtMultimedia.LogarithmicVolumeScale, expectedOutput: 0.9 },
+ { tag: "0.72 from linear to logarithmic", input: 0.72, from: QtMultimedia.LinearVolumeScale, to: QtMultimedia.LogarithmicVolumeScale, expectedOutput: 0.96 },
+ { tag: "1.0 from linear to logarithmic", input: 1.0, from: QtMultimedia.LinearVolumeScale, to: QtMultimedia.LogarithmicVolumeScale, expectedOutput: 1.0 },
+
+ { tag: "-1.0 from linear to decibel", input: -1, from: QtMultimedia.LinearVolumeScale, to: QtMultimedia.DecibelVolumeScale, expectedOutput: -200 },
+ { tag: "0.0 from linear to decibel", input: 0, from: QtMultimedia.LinearVolumeScale, to: QtMultimedia.DecibelVolumeScale, expectedOutput: -200 },
+ { tag: "0.33 from linear to decibel", input: 0.33, from: QtMultimedia.LinearVolumeScale, to: QtMultimedia.DecibelVolumeScale, expectedOutput: -9.63 },
+ { tag: "0.5 from linear to decibel", input: 0.5, from: QtMultimedia.LinearVolumeScale, to: QtMultimedia.DecibelVolumeScale, expectedOutput: -6.02 },
+ { tag: "0.72 from linear to decibel", input: 0.72, from: QtMultimedia.LinearVolumeScale, to: QtMultimedia.DecibelVolumeScale, expectedOutput: -2.85 },
+ { tag: "1.0 from linear to decibel", input: 1.0, from: QtMultimedia.LinearVolumeScale, to: QtMultimedia.DecibelVolumeScale, expectedOutput: 0 },
+
+ { tag: "-1.0 from cubic to linear", input: -1, from: QtMultimedia.CubicVolumeScale, to: QtMultimedia.LinearVolumeScale, expectedOutput: 0 },
+ { tag: "0.0 from cubic to linear", input: 0, from: QtMultimedia.CubicVolumeScale, to: QtMultimedia.LinearVolumeScale, expectedOutput: 0 },
+ { tag: "0.33 from cubic to linear", input: 0.33, from: QtMultimedia.CubicVolumeScale, to: QtMultimedia.LinearVolumeScale, expectedOutput: 0.04 },
+ { tag: "0.5 from cubic to linear", input: 0.5, from: QtMultimedia.CubicVolumeScale, to: QtMultimedia.LinearVolumeScale, expectedOutput: 0.13 },
+ { tag: "0.72 from cubic to linear", input: 0.72, from: QtMultimedia.CubicVolumeScale, to: QtMultimedia.LinearVolumeScale, expectedOutput: 0.37 },
+ { tag: "1.0 from cubic to linear", input: 1.0, from: QtMultimedia.CubicVolumeScale, to: QtMultimedia.LinearVolumeScale, expectedOutput: 1 },
+
+ { tag: "-1.0 from cubic to cubic", input: -1, from: QtMultimedia.CubicVolumeScale, to: QtMultimedia.CubicVolumeScale, expectedOutput: 0 },
+ { tag: "0.0 from cubic to cubic", input: 0, from: QtMultimedia.CubicVolumeScale, to: QtMultimedia.CubicVolumeScale, expectedOutput: 0 },
+ { tag: "0.5 from cubic to cubic", input: 0.5, from: QtMultimedia.CubicVolumeScale, to: QtMultimedia.CubicVolumeScale, expectedOutput: 0.5 },
+ { tag: "1.0 from cubic to cubic", input: 1.0, from: QtMultimedia.CubicVolumeScale, to: QtMultimedia.CubicVolumeScale, expectedOutput: 1.0 },
+
+ { tag: "-1.0 from cubic to logarithmic", input: -1, from: QtMultimedia.CubicVolumeScale, to: QtMultimedia.LogarithmicVolumeScale, expectedOutput: 0 },
+ { tag: "0.0 from cubic to logarithmic", input: 0, from: QtMultimedia.CubicVolumeScale, to: QtMultimedia.LogarithmicVolumeScale, expectedOutput: 0 },
+ { tag: "0.33 from cubic to logarithmic", input: 0.33, from: QtMultimedia.CubicVolumeScale, to: QtMultimedia.LogarithmicVolumeScale, expectedOutput: 0.15 },
+ { tag: "0.5 from cubic to logarithmic", input: 0.5, from: QtMultimedia.CubicVolumeScale, to: QtMultimedia.LogarithmicVolumeScale, expectedOutput: 0.44 },
+ { tag: "0.72 from cubic to logarithmic", input: 0.72, from: QtMultimedia.CubicVolumeScale, to: QtMultimedia.LogarithmicVolumeScale, expectedOutput: 0.82 },
+ { tag: "1.0 from cubic to logarithmic", input: 1.0, from: QtMultimedia.CubicVolumeScale, to: QtMultimedia.LogarithmicVolumeScale, expectedOutput: 1 },
+
+ { tag: "-1.0 from cubic to decibel", input: -1, from: QtMultimedia.CubicVolumeScale, to: QtMultimedia.DecibelVolumeScale, expectedOutput: -200 },
+ { tag: "0.0 from cubic to decibel", input: 0, from: QtMultimedia.CubicVolumeScale, to: QtMultimedia.DecibelVolumeScale, expectedOutput: -200 },
+ { tag: "0.33 from cubic to decibel", input: 0.33, from: QtMultimedia.CubicVolumeScale, to: QtMultimedia.DecibelVolumeScale, expectedOutput: -28.89 },
+ { tag: "0.5 from cubic to decibel", input: 0.5, from: QtMultimedia.CubicVolumeScale, to: QtMultimedia.DecibelVolumeScale, expectedOutput: -18.06 },
+ { tag: "0.72 from cubic to decibel", input: 0.72, from: QtMultimedia.CubicVolumeScale, to: QtMultimedia.DecibelVolumeScale, expectedOutput: -8.56 },
+ { tag: "1.0 from cubic to decibel", input: 1.0, from: QtMultimedia.CubicVolumeScale, to: QtMultimedia.DecibelVolumeScale, expectedOutput: 0 },
+
+ { tag: "-1.0 from logarithmic to linear", input: -1, from: QtMultimedia.LogarithmicVolumeScale, to: QtMultimedia.LinearVolumeScale, expectedOutput: 0 },
+ { tag: "0.0 from logarithmic to linear", input: 0, from: QtMultimedia.LogarithmicVolumeScale, to: QtMultimedia.LinearVolumeScale, expectedOutput: 0 },
+ { tag: "0.33 from logarithmic to linear", input: 0.33, from: QtMultimedia.LogarithmicVolumeScale, to: QtMultimedia.LinearVolumeScale, expectedOutput: 0.09 },
+ { tag: "0.5 from logarithmic to linear", input: 0.5, from: QtMultimedia.LogarithmicVolumeScale, to: QtMultimedia.LinearVolumeScale, expectedOutput: 0.15 },
+ { tag: "0.72 from logarithmic to linear", input: 0.72, from: QtMultimedia.LogarithmicVolumeScale, to: QtMultimedia.LinearVolumeScale, expectedOutput: 0.28 },
+ { tag: "1.0 from logarithmic to linear", input: 1.0, from: QtMultimedia.LogarithmicVolumeScale, to: QtMultimedia.LinearVolumeScale, expectedOutput: 1.0 },
+
+ { tag: "-1.0 from logarithmic to cubic", input: -1, from: QtMultimedia.LogarithmicVolumeScale, to: QtMultimedia.CubicVolumeScale, expectedOutput: 0 },
+ { tag: "0.0 from logarithmic to cubic", input: 0, from: QtMultimedia.LogarithmicVolumeScale, to: QtMultimedia.CubicVolumeScale, expectedOutput: 0 },
+ { tag: "0.33 from logarithmic to cubic", input: 0.33, from: QtMultimedia.LogarithmicVolumeScale, to: QtMultimedia.CubicVolumeScale, expectedOutput: 0.44 },
+ { tag: "0.5 from logarithmic to cubic", input: 0.5, from: QtMultimedia.LogarithmicVolumeScale, to: QtMultimedia.CubicVolumeScale, expectedOutput: 0.53 },
+ { tag: "0.72 from logarithmic to cubic", input: 0.72, from: QtMultimedia.LogarithmicVolumeScale, to: QtMultimedia.CubicVolumeScale, expectedOutput: 0.65 },
+ { tag: "1.0 from logarithmic to cubic", input: 1.0, from: QtMultimedia.LogarithmicVolumeScale, to: QtMultimedia.CubicVolumeScale, expectedOutput: 1.0 },
+
+ { tag: "-1.0 from logarithmic to logarithmic", input: -1, from: QtMultimedia.LogarithmicVolumeScale, to: QtMultimedia.LogarithmicVolumeScale, expectedOutput: 0 },
+ { tag: "0.0 from logarithmic to logarithmic", input: 0, from: QtMultimedia.LogarithmicVolumeScale, to: QtMultimedia.LogarithmicVolumeScale, expectedOutput: 0 },
+ { tag: "0.5 from logarithmic to logarithmic", input: 0.5, from: QtMultimedia.LogarithmicVolumeScale, to: QtMultimedia.LogarithmicVolumeScale, expectedOutput: 0.5 },
+ { tag: "1.0 from logarithmic to logarithmic", input: 1.0, from: QtMultimedia.LogarithmicVolumeScale, to: QtMultimedia.LogarithmicVolumeScale, expectedOutput: 1.0 },
+
+ { tag: "-1.0 from logarithmic to decibel", input: -1, from: QtMultimedia.LogarithmicVolumeScale, to: QtMultimedia.DecibelVolumeScale, expectedOutput: -200 },
+ { tag: "0.0 from logarithmic to decibel", input: 0, from: QtMultimedia.LogarithmicVolumeScale, to: QtMultimedia.DecibelVolumeScale, expectedOutput: -200 },
+ { tag: "0.33 from logarithmic to decibel", input: 0.33, from: QtMultimedia.LogarithmicVolumeScale, to: QtMultimedia.DecibelVolumeScale, expectedOutput: -21.21 },
+ { tag: "0.5 from logarithmic to decibel", input: 0.5, from: QtMultimedia.LogarithmicVolumeScale, to: QtMultimedia.DecibelVolumeScale, expectedOutput: -16.45 },
+ { tag: "0.72 from logarithmic to decibel", input: 0.72, from: QtMultimedia.LogarithmicVolumeScale, to: QtMultimedia.DecibelVolumeScale, expectedOutput: -11.17 },
+ { tag: "1.0 from logarithmic to decibel", input: 1.0, from: QtMultimedia.LogarithmicVolumeScale, to: QtMultimedia.DecibelVolumeScale, expectedOutput: 0 },
+
+ { tag: "-1000 from decibel to linear", input: -1000, from: QtMultimedia.DecibelVolumeScale, to: QtMultimedia.LinearVolumeScale, expectedOutput: 0 },
+ { tag: "-200 from decibel to linear", input: -200, from: QtMultimedia.DecibelVolumeScale, to: QtMultimedia.LinearVolumeScale, expectedOutput: 0 },
+ { tag: "-40 from decibel to linear", input: -40, from: QtMultimedia.DecibelVolumeScale, to: QtMultimedia.LinearVolumeScale, expectedOutput: 0.01 },
+ { tag: "-10 from decibel to linear", input: -10, from: QtMultimedia.DecibelVolumeScale, to: QtMultimedia.LinearVolumeScale, expectedOutput: 0.32 },
+ { tag: "-5 from decibel to linear", input: -5, from: QtMultimedia.DecibelVolumeScale, to: QtMultimedia.LinearVolumeScale, expectedOutput: 0.56 },
+ { tag: "0 from decibel to linear", input: 0, from: QtMultimedia.DecibelVolumeScale, to: QtMultimedia.LinearVolumeScale, expectedOutput: 1 },
+
+ { tag: "-1000 from decibel to cubic", input: -1000, from: QtMultimedia.DecibelVolumeScale, to: QtMultimedia.CubicVolumeScale, expectedOutput: 0 },
+ { tag: "-200 from decibel to cubic", input: -200, from: QtMultimedia.DecibelVolumeScale, to: QtMultimedia.CubicVolumeScale, expectedOutput: 0 },
+ { tag: "-40 from decibel to cubic", input: -40, from: QtMultimedia.DecibelVolumeScale, to: QtMultimedia.CubicVolumeScale, expectedOutput: 0.22 },
+ { tag: "-10 from decibel to cubic", input: -10, from: QtMultimedia.DecibelVolumeScale, to: QtMultimedia.CubicVolumeScale, expectedOutput: 0.68 },
+ { tag: "-5 from decibel to cubic", input: -5, from: QtMultimedia.DecibelVolumeScale, to: QtMultimedia.CubicVolumeScale, expectedOutput: 0.83 },
+ { tag: "0 from decibel to cubic", input: 0, from: QtMultimedia.DecibelVolumeScale, to: QtMultimedia.CubicVolumeScale, expectedOutput: 1 },
+
+ { tag: "-1000 from decibel to logarithmic", input: -1000, from: QtMultimedia.DecibelVolumeScale, to: QtMultimedia.LogarithmicVolumeScale, expectedOutput: 0 },
+ { tag: "-200 from decibel to logarithmic", input: -200, from: QtMultimedia.DecibelVolumeScale, to: QtMultimedia.LogarithmicVolumeScale, expectedOutput: 0 },
+ { tag: "-40 from decibel to logarithmic", input: -40, from: QtMultimedia.DecibelVolumeScale, to: QtMultimedia.LogarithmicVolumeScale, expectedOutput: 0.05 },
+ { tag: "-10 from decibel to logarithmic", input: -10, from: QtMultimedia.DecibelVolumeScale, to: QtMultimedia.LogarithmicVolumeScale, expectedOutput: 0.77 },
+ { tag: "-5 from decibel to logarithmic", input: -5, from: QtMultimedia.DecibelVolumeScale, to: QtMultimedia.LogarithmicVolumeScale, expectedOutput: 0.92 },
+ { tag: "0 from decibel to logarithmic", input: 0, from: QtMultimedia.DecibelVolumeScale, to: QtMultimedia.LogarithmicVolumeScale, expectedOutput: 1 },
+
+ { tag: "-1000 from decibel to decibel", input: -1000, from: QtMultimedia.DecibelVolumeScale, to: QtMultimedia.DecibelVolumeScale, expectedOutput: -1000 },
+ { tag: "-200 from decibel to decibel", input: -200, from: QtMultimedia.DecibelVolumeScale, to: QtMultimedia.DecibelVolumeScale, expectedOutput: -200 },
+ { tag: "-30 from decibel to decibel", input: -30, from: QtMultimedia.DecibelVolumeScale, to: QtMultimedia.DecibelVolumeScale, expectedOutput: -30 },
+ { tag: "0 from decibel to decibel", input: 0, from: QtMultimedia.DecibelVolumeScale, to: QtMultimedia.DecibelVolumeScale, expectedOutput: 0 },
+ ]
+ }
+
+ function test_convertVolume(data) {
+ fuzzyCompare(QtMultimedia.convertVolume(data.input, data.from, data.to),
+ data.expectedOutput,
+ 0.01);
+ }
+
}
diff --git a/tests/auto/unit/qmediapluginloader/qmediapluginloader.pro b/tests/auto/unit/qmediapluginloader/qmediapluginloader.pro
index 26f232010..90b02ac59 100644
--- a/tests/auto/unit/qmediapluginloader/qmediapluginloader.pro
+++ b/tests/auto/unit/qmediapluginloader/qmediapluginloader.pro
@@ -4,10 +4,3 @@ TARGET = tst_qmediapluginloader
QT += multimedia-private testlib
SOURCES += tst_qmediapluginloader.cpp
-
-wince* {
- PLUGIN_DEPLOY.sources = $$OUTPUT_DIR/plugins/mediaservice/*.dll
- PLUGIN_DEPLOY.path = mediaservice
- DEPLOYMENT += PLUGIN_DEPLOY
-}
-
diff --git a/tests/auto/unit/qpaintervideosurface/qpaintervideosurface.pro b/tests/auto/unit/qpaintervideosurface/qpaintervideosurface.pro
index 848b1c806..f1db2c5fb 100644
--- a/tests/auto/unit/qpaintervideosurface/qpaintervideosurface.pro
+++ b/tests/auto/unit/qpaintervideosurface/qpaintervideosurface.pro
@@ -2,11 +2,9 @@ CONFIG += testcase
TARGET = tst_qpaintervideosurface
QT += multimedia-private multimediawidgets-private testlib
-qtHaveModule(opengl) {
+qtHaveModule(opengl): \
QT += opengl
-} else {
- DEFINES += QT_NO_OPENGL
-}
+
SOURCES += tst_qpaintervideosurface.cpp