diff options
246 files changed, 4559 insertions, 4922 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/alsa/alsa.pro b/config.tests/alsa/alsa.pro index 26514b788..db488fe5c 100644 --- a/config.tests/alsa/alsa.pro +++ b/config.tests/alsa/alsa.pro @@ -1,6 +1,3 @@ SOURCES = alsatest.cpp - CONFIG -= qt dylib -LIBS+=-lasound - diff --git a/config.tests/avfoundation/avfoundation.pro b/config.tests/avfoundation/avfoundation.pro index ac680d71b..9ef3afea2 100644 --- a/config.tests/avfoundation/avfoundation.pro +++ b/config.tests/avfoundation/avfoundation.pro @@ -1,3 +1 @@ OBJECTIVE_SOURCES += main.mm - -LIBS += -framework AVFoundation -framework Foundation diff --git a/config.tests/directshow/directshow.pro b/config.tests/directshow/directshow.pro index 6dfc54a01..abb9ba83a 100644 --- a/config.tests/directshow/directshow.pro +++ b/config.tests/directshow/directshow.pro @@ -2,5 +2,3 @@ CONFIG -= qt CONFIG += console SOURCES += main.cpp - -!wince: 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/gstreamer/gstreamer.pro b/config.tests/gstreamer/gstreamer.pro index 6b9843ac3..3f6c64360 100644 --- a/config.tests/gstreamer/gstreamer.pro +++ b/config.tests/gstreamer/gstreamer.pro @@ -1,12 +1,2 @@ SOURCES += main.cpp -CONFIG += link_pkgconfig - -PKGCONFIG += \ - gstreamer-$$GST_VERSION \ - gstreamer-base-$$GST_VERSION \ - gstreamer-audio-$$GST_VERSION \ - gstreamer-video-$$GST_VERSION \ - gstreamer-pbutils-$$GST_VERSION - - diff --git a/config.tests/gstreamer_appsrc/gstreamer_appsrc.pro b/config.tests/gstreamer_appsrc/gstreamer_appsrc.pro index 0f3ca2b17..28dcadcbf 100644 --- a/config.tests/gstreamer_appsrc/gstreamer_appsrc.pro +++ b/config.tests/gstreamer_appsrc/gstreamer_appsrc.pro @@ -1,10 +1 @@ SOURCES += main.cpp - -CONFIG += link_pkgconfig - -PKGCONFIG += \ - gstreamer-$$GST_VERSION \ - gstreamer-base-$$GST_VERSION \ - gstreamer-audio-$$GST_VERSION \ - gstreamer-video-$$GST_VERSION \ - gstreamer-pbutils-$$GST_VERSION diff --git a/config.tests/gstreamer_encodingprofiles/gstreamer_encodingprofiles.pro b/config.tests/gstreamer_encodingprofiles/gstreamer_encodingprofiles.pro index fad40b0bd..28dcadcbf 100644 --- a/config.tests/gstreamer_encodingprofiles/gstreamer_encodingprofiles.pro +++ b/config.tests/gstreamer_encodingprofiles/gstreamer_encodingprofiles.pro @@ -1,11 +1 @@ SOURCES += main.cpp - -CONFIG += link_pkgconfig - - -PKGCONFIG += \ - gstreamer-$$GST_VERSION \ - gstreamer-base-$$GST_VERSION \ - gstreamer-audio-$$GST_VERSION \ - gstreamer-video-$$GST_VERSION \ - gstreamer-pbutils-$$GST_VERSION diff --git a/config.tests/gstreamer_photography/gstreamer_photography.pro b/config.tests/gstreamer_photography/gstreamer_photography.pro index 975991f93..28dcadcbf 100644 --- a/config.tests/gstreamer_photography/gstreamer_photography.pro +++ b/config.tests/gstreamer_photography/gstreamer_photography.pro @@ -1,13 +1 @@ SOURCES += main.cpp - -CONFIG += link_pkgconfig - -PKGCONFIG += \ - gstreamer-$$GST_VERSION \ - gstreamer-base-$$GST_VERSION \ - gstreamer-audio-$$GST_VERSION \ - gstreamer-video-$$GST_VERSION \ - gstreamer-pbutils-$$GST_VERSION - -LIBS += -lgstphotography-$$GST_VERSION - diff --git a/config.tests/mmrenderer/mmrenderer.pro b/config.tests/mmrenderer/mmrenderer.pro index cc1e21e82..571b51627 100644 --- a/config.tests/mmrenderer/mmrenderer.pro +++ b/config.tests/mmrenderer/mmrenderer.pro @@ -1,6 +1,3 @@ SOURCES = mmrenderertest.cpp - CONFIG -= qt -LIBS += -lmmrndclient -lstrm - diff --git a/config.tests/openal/openal.pro b/config.tests/openal/openal.pro index a4a7d1e86..1aa1271c6 100644 --- a/config.tests/openal/openal.pro +++ b/config.tests/openal/openal.pro @@ -1,7 +1,3 @@ SOURCES += main.cpp -win32: LIBS += -lOpenAL32 -unix:!mac:!blackberry: LIBS += -lopenal -blackberry: LIBS += -lOpenAL -mac: LIBS += -framework OpenAL mac: DEFINES += HEADER_OPENAL_PREFIX diff --git a/config.tests/pulseaudio/pulseaudio.pro b/config.tests/pulseaudio/pulseaudio.pro index 12ad7fba2..ff7082390 100644 --- a/config.tests/pulseaudio/pulseaudio.pro +++ b/config.tests/pulseaudio/pulseaudio.pro @@ -1,8 +1,2 @@ CONFIG -= qt -CONFIG += link_pkgconfig - -PKGCONFIG += \ - libpulse \ - libpulse-mainloop-glib - SOURCES = pulseaudio.cpp diff --git a/config.tests/resourcepolicy/resourcepolicy.pro b/config.tests/resourcepolicy/resourcepolicy.pro index 7627d4805..3f6c64360 100644 --- a/config.tests/resourcepolicy/resourcepolicy.pro +++ b/config.tests/resourcepolicy/resourcepolicy.pro @@ -1,7 +1,2 @@ SOURCES += main.cpp -CONFIG += link_pkgconfig - -PKGCONFIG += \ - libresourceqt5 - 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/config.tests/wmf/wmf.pro b/config.tests/wmf/wmf.pro index ac5643e4f..abb9ba83a 100644 --- a/config.tests/wmf/wmf.pro +++ b/config.tests/wmf/wmf.pro @@ -2,5 +2,3 @@ CONFIG -= qt CONFIG += console SOURCES += main.cpp - -LIBS += -lstrmiids -ldmoguids -luuid -lmsdmo -lole32 -loleaut32 -lMf -lMfuuid -lMfplat -lPropsys diff --git a/config_help.txt b/config_help.txt new file mode 100644 index 000000000..78c75acbd --- /dev/null +++ b/config_help.txt @@ -0,0 +1,8 @@ +Multimedia options: + + -pulseaudio .......... Enable PulseAudio support [auto] (Unix only) + -alsa ................ Enable ALSA support [auto] (Unix only) + -no-gstreamer ........ Disable support for GStreamer + -gstreamer [version] . Enable GStreamer support [auto] + With no parameter, 1.0 is tried first, then 0.10. + -wmf-backend ......... Enable WMF support [no] (Windows only) diff --git a/configure.json b/configure.json new file mode 100644 index 000000000..12ae19834 --- /dev/null +++ b/configure.json @@ -0,0 +1,5 @@ +{ + "subconfigs": [ + "src/multimedia" + ] +} 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/multimedia/multimedia.pro b/examples/multimedia/multimedia.pro index 449cb150f..0a01439c4 100644 --- a/examples/multimedia/multimedia.pro +++ b/examples/multimedia/multimedia.pro @@ -1,4 +1,5 @@ TEMPLATE = subdirs +QT_FOR_CONFIG += multimedia-private SUBDIRS += audiodecoder @@ -20,5 +21,5 @@ qtHaveModule(quick) { video } -config_openal: SUBDIRS += audioengine +qtConfig(openal): SUBDIRS += audioengine diff --git a/examples/multimediawidgets/player/player.cpp b/examples/multimediawidgets/player/player.cpp index e787aa269..ab048838a 100644 --- a/examples/multimediawidgets/player/player.cpp +++ b/examples/multimediawidgets/player/player.cpp @@ -55,9 +55,7 @@ Player::Player(QWidget *parent) , videoWidget(0) , coverLabel(0) , slider(0) -#ifndef PLAYER_NO_COLOROPTIONS , colorDialog(0) -#endif { //! [create-objs] player = new QMediaPlayer(this); @@ -135,11 +133,9 @@ Player::Player(QWidget *parent) fullScreenButton = new QPushButton(tr("FullScreen"), this); fullScreenButton->setCheckable(true); -#ifndef PLAYER_NO_COLOROPTIONS colorButton = new QPushButton(tr("Color Options..."), this); colorButton->setEnabled(false); connect(colorButton, SIGNAL(clicked()), this, SLOT(showColorDialog())); -#endif QBoxLayout *displayLayout = new QHBoxLayout; displayLayout->addWidget(videoWidget, 2); @@ -152,9 +148,7 @@ Player::Player(QWidget *parent) controlLayout->addWidget(controls); controlLayout->addStretch(1); controlLayout->addWidget(fullScreenButton); -#ifndef PLAYER_NO_COLOROPTIONS controlLayout->addWidget(colorButton); -#endif QBoxLayout *layout = new QVBoxLayout; layout->addLayout(displayLayout); @@ -175,9 +169,7 @@ Player::Player(QWidget *parent) controls->setEnabled(false); playlistView->setEnabled(false); openButton->setEnabled(false); -#ifndef PLAYER_NO_COLOROPTIONS colorButton->setEnabled(false); -#endif fullScreenButton->setEnabled(false); } @@ -347,9 +339,7 @@ void Player::videoAvailableChanged(bool available) if (fullScreenButton->isChecked()) videoWidget->setFullScreen(true); } -#ifndef PLAYER_NO_COLOROPTIONS colorButton->setEnabled(available); -#endif } void Player::setTrackInfo(const QString &info) @@ -389,7 +379,6 @@ void Player::updateDurationInfo(qint64 currentInfo) labelDuration->setText(tStr); } -#ifndef PLAYER_NO_COLOROPTIONS void Player::showColorDialog() { if (!colorDialog) { @@ -434,4 +423,3 @@ void Player::showColorDialog() } colorDialog->show(); } -#endif diff --git a/examples/multimediawidgets/player/player.h b/examples/multimediawidgets/player/player.h index 7f5d0881b..ca643bd7d 100644 --- a/examples/multimediawidgets/player/player.h +++ b/examples/multimediawidgets/player/player.h @@ -94,9 +94,7 @@ private slots: void displayErrorMessage(); -#ifndef PLAYER_NO_COLOROPTIONS void showColorDialog(); -#endif private: void setTrackInfo(const QString &info); @@ -111,10 +109,8 @@ private: QSlider *slider; QLabel *labelDuration; QPushButton *fullScreenButton; -#ifndef PLAYER_NO_COLOROPTIONS QPushButton *colorButton; QDialog *colorDialog; -#endif QLabel *labelHistogram; HistogramWidget *histogram; diff --git a/examples/multimediawidgets/player/player.pro b/examples/multimediawidgets/player/player.pro index 067b31b11..0c5be6888 100644 --- a/examples/multimediawidgets/player/player.pro +++ b/examples/multimediawidgets/player/player.pro @@ -20,9 +20,5 @@ SOURCES = main.cpp \ videowidget.cpp \ histogramwidget.cpp -maemo* { - DEFINES += PLAYER_NO_COLOROPTIONS -} - target.path = $$[QT_INSTALL_EXAMPLES]/multimediawidgets/player INSTALLS += target 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 e58ae1d67..00c82cd0f 100644 --- a/qtmultimedia.pro +++ b/qtmultimedia.pro @@ -1,40 +1,3 @@ requires(qtHaveModule(gui)) - -load(configure) -qtCompileTest(openal) -win32 { - qtCompileTest(directshow) { - qtCompileTest(wshellitem) - } - qtCompileTest(evr) - qtCompileTest(wmsdk) - qtCompileTest(wmf) -} else:mac { - qtCompileTest(avfoundation) -} else:qnx { - qtCompileTest(mmrenderer) -} else:!android { - contains(QT_CONFIG, alsa):qtCompileTest(alsa) - contains(QT_CONFIG, pulseaudio):qtCompileTest(pulseaudio) - - isEmpty(GST_VERSION) { - contains(QT_CONFIG, gstreamer-0.10) { - GST_VERSION = 0.10 - } else: contains(QT_CONFIG, gstreamer-1.0) { - GST_VERSION = 1.0 - } - } - cache(GST_VERSION, set) - !isEmpty(GST_VERSION):qtCompileTest(gstreamer) { - qtCompileTest(gstreamer_photography) - qtCompileTest(gstreamer_encodingprofiles) - qtCompileTest(gstreamer_appsrc) - qtCompileTest(linux_v4l) - } - - qtCompileTest(resourcepolicy) - contains(QT_CONFIG, opengles2):qtCompileTest(gpu_vivante) -} - load(qt_parts) diff --git a/src/gsttools/gsttools.pro b/src/gsttools/gsttools.pro index a5c1d9493..e84454980 100644 --- a/src/gsttools/gsttools.pro +++ b/src/gsttools/gsttools.pro @@ -8,29 +8,16 @@ QT = core-private multimedia-private gui-private !static:DEFINES += QT_MAKEDLL DEFINES += GLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_26 -unix:!maemo*:contains(QT_CONFIG, alsa) { -DEFINES += HAVE_ALSA -LIBS_PRIVATE += \ - -lasound +qtConfig(alsa) { + DEFINES += HAVE_ALSA + QMAKE_USE += alsa } -CONFIG += link_pkgconfig +QMAKE_USE += gstreamer -PKGCONFIG += \ - gstreamer-$$GST_VERSION \ - gstreamer-base-$$GST_VERSION \ - gstreamer-audio-$$GST_VERSION \ - gstreamer-video-$$GST_VERSION \ - gstreamer-pbutils-$$GST_VERSION - -equals(GST_VERSION,"0.10") { - PKGCONFIG_PRIVATE += gstreamer-interfaces-0.10 - maemo*: PKGCONFIG_PRIVATE +=gstreamer-plugins-bad-0.10 -} - -config_resourcepolicy { +qtConfig(resourcepolicy) { DEFINES += HAVE_RESOURCE_POLICY - PKGCONFIG_PRIVATE += libresourceqt5 + QMAKE_USE += libresourceqt5 } # Header files must go inside source directory of a module @@ -44,7 +31,6 @@ PRIVATE_HEADERS += \ qgstreamermessage_p.h \ qgstutils_p.h \ qgstvideobuffer_p.h \ - qvideosurfacegstsink_p.h \ qgstreamerbufferprobe_p.h \ qgstreamervideorendererinterface_p.h \ qgstreameraudioinputselector_p.h \ @@ -82,26 +68,16 @@ qtHaveModule(widgets) { qgstreamervideowidget.cpp } -equals(GST_VERSION,"0.10") { +qtConfig(gstreamer_0_10) { PRIVATE_HEADERS += \ qgstbufferpoolinterface_p.h \ - gstvideoconnector_p.h \ + qvideosurfacegstsink_p.h \ + gstvideoconnector_p.h SOURCES += \ qgstbufferpoolinterface.cpp \ qvideosurfacegstsink.cpp \ gstvideoconnector.c - - maemo6 { - PKGCONFIG_PRIVATE += qmsystem2 - - contains(QT_CONFIG, opengles2):qtHaveModule(widgets) { - PRIVATE_HEADERS += qgstreamergltexturerenderer_p.h - SOURCES += qgstreamergltexturerenderer.cpp - QT += opengl - LIBS_PRIVATE += -lEGL -lgstmeegointerfaces-0.10 - } - } } else { PRIVATE_HEADERS += \ qgstvideorendererplugin_p.h \ @@ -112,27 +88,23 @@ equals(GST_VERSION,"0.10") { qgstvideorenderersink.cpp } -mir: { - contains(QT_CONFIG, opengles2):qtHaveModule(widgets) { +qtConfig(mirclient): { + qtConfig(opengles2):qtHaveModule(widgets) { PRIVATE_HEADERS += qgstreamermirtexturerenderer_p.h SOURCES += qgstreamermirtexturerenderer.cpp QT += opengl quick LIBS += -lEGL } - DEFINES += HAVE_MIR } -config_gstreamer_appsrc { - PKGCONFIG_PRIVATE += gstreamer-app-$$GST_VERSION +qtConfig(gstreamer_app) { + QMAKE_USE += gstreamer_app PRIVATE_HEADERS += qgstappsrc_p.h SOURCES += qgstappsrc.cpp - DEFINES += HAVE_GST_APPSRC - - LIBS_PRIVATE += -lgstapp-$$GST_VERSION } -config_linux_v4l: DEFINES += USE_V4L +qtConfig(linux_v4l): DEFINES += USE_V4L HEADERS += $$PRIVATE_HEADERS diff --git a/src/gsttools/gstvideoconnector.c b/src/gsttools/gstvideoconnector.c index d79df2091..b85f5bdbe 100644 --- a/src/gsttools/gstvideoconnector.c +++ b/src/gsttools/gstvideoconnector.c @@ -410,11 +410,7 @@ gst_video_connector_chain (GstPad * pad, GstBuffer * buf) element->latest_buffer = NULL; } - //don't save the last video buffer on maemo6 because of buffers shortage - //with omapxvsink -#ifndef Q_WS_MAEMO_6 element->latest_buffer = gst_buffer_ref(buf); -#endif gst_buffer_unref(buf); gst_object_unref (element); diff --git a/src/gsttools/qgstreamergltexturerenderer.cpp b/src/gsttools/qgstreamergltexturerenderer.cpp deleted file mode 100644 index 3cd7eddf7..000000000 --- a/src/gsttools/qgstreamergltexturerenderer.cpp +++ /dev/null @@ -1,582 +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 <private/qvideosurfacegstsink_p.h> -#include <qabstractvideosurface.h> -#include <private/qgstutils_p.h> - -#include <QtGui/qevent.h> -#include <QtWidgets/qapplication.h> -#include <QtWidgets/qx11info_x11.h> -#include <QtCore/qdebug.h> -#include <QtCore/qthread.h> - -#include <QtOpenGL/qgl.h> - -#include <gst/gst.h> -#include <gst/interfaces/xoverlay.h> -#include <gst/interfaces/propertyprobe.h> -#include <gst/interfaces/meegovideotexture.h> -#include <gst/interfaces/meegovideorenderswitch.h> - - -#include <EGL/egl.h> -#include <EGL/eglext.h> - -#include "qgstreamergltexturerenderer_p.h" - -//#define GL_TEXTURE_SINK_DEBUG 1 - -//from extdefs.h -typedef void *EGLSyncKHR; -typedef khronos_utime_nanoseconds_t EGLTimeKHR; - -#define GL_TEXTURE_EXTERNAL_OES 0x8D65 -#define EGL_SYNC_FENCE_KHR 0x30F9 - -typedef EGLSyncKHR (EGLAPIENTRYP _PFNEGLCREATESYNCKHRPROC) (EGLDisplay dpy, - EGLenum type, const EGLint * attrib_list); -typedef EGLBoolean (EGLAPIENTRYP _PFNEGLDESTROYSYNCKHRPROC) (EGLDisplay dpy, - EGLSyncKHR sync); - - -const QAbstractVideoBuffer::HandleType EGLImageTextureHandle = - QAbstractVideoBuffer::HandleType(QAbstractVideoBuffer::UserHandle+3434); - -// EGLSync functions -_PFNEGLCREATESYNCKHRPROC eglCreateSyncKHR; -_PFNEGLDESTROYSYNCKHRPROC eglDestroySyncKHR; - -class QGStreamerGLTextureBuffer : public QAbstractVideoBuffer -{ -public: - QGStreamerGLTextureBuffer(MeegoGstVideoTexture *textureSink, int frameNumber) : - QAbstractVideoBuffer(EGLImageTextureHandle), - m_textureSink(MEEGO_GST_VIDEO_TEXTURE(textureSink)), - m_frameNumber(frameNumber) - { - } - - ~QGStreamerGLTextureBuffer() - { - } - - - MapMode mapMode() const { return NotMapped; } - uchar *map(MapMode mode, int *numBytes, int *bytesPerLine) - { - Q_UNUSED(mode); - Q_UNUSED(numBytes); - Q_UNUSED(bytesPerLine); - - //acquire_frame should really be called at buffer construction time - //but it conflicts with id-less implementation of gst texture sink. -#if defined(GL_TEXTURE_SINK_DEBUG) && GL_TEXTURE_SINK_DEBUG > 1 - qDebug() << "acquire frame" << m_frameNumber; -#endif - if (!meego_gst_video_texture_acquire_frame(m_textureSink,m_frameNumber)) - qWarning() << Q_FUNC_INFO << "acquire-frame failed" << m_frameNumber; - - -#if defined(GL_TEXTURE_SINK_DEBUG) && GL_TEXTURE_SINK_DEBUG > 1 - qDebug() << "map frame" << m_frameNumber; -#endif - - gboolean bind_status = meego_gst_video_texture_bind_frame(m_textureSink, GL_TEXTURE_EXTERNAL_OES, m_frameNumber); - if (!bind_status) - qWarning() << Q_FUNC_INFO << "bind-frame failed"; - - return (uchar*)1; - } - - void unmap() - { - gboolean bind_status = meego_gst_video_texture_bind_frame(m_textureSink, GL_TEXTURE_EXTERNAL_OES, -1); - -#if defined(GL_TEXTURE_SINK_DEBUG) && GL_TEXTURE_SINK_DEBUG > 1 - qDebug() << "unmap frame" << m_frameNumber; -#endif - - if (!bind_status) - qWarning() << Q_FUNC_INFO << "unbind-frame failed"; - - //release_frame should really be called in destructor - //but this conflicts with id-less implementation of gst texture sink. -#if defined(GL_TEXTURE_SINK_DEBUG) && GL_TEXTURE_SINK_DEBUG > 1 - qDebug() << "release frame" << m_frameNumber; -#endif - EGLSyncKHR sync = eglCreateSyncKHR(eglGetDisplay((EGLNativeDisplayType)QX11Info::display()), EGL_SYNC_FENCE_KHR, NULL); - meego_gst_video_texture_release_frame(m_textureSink, m_frameNumber, sync); - } - - QVariant handle() const - { - return m_frameNumber; - } - -private: - MeegoGstVideoTexture *m_textureSink; - int m_frameNumber; -}; - - -QGstreamerGLTextureRenderer::QGstreamerGLTextureRenderer(QObject *parent) : - QVideoRendererControl(parent), - m_videoSink(0), - m_surface(0), - m_context(0), - m_winId(0), - m_colorKey(49,0,49), - m_overlayEnabled(false), - m_bufferProbeId(-1) -{ - eglCreateSyncKHR = - (_PFNEGLCREATESYNCKHRPROC)eglGetProcAddress("eglCreateSyncKHR"); - eglDestroySyncKHR = - (_PFNEGLDESTROYSYNCKHRPROC)eglGetProcAddress("eglDestroySyncKHR"); -} - -QGstreamerGLTextureRenderer::~QGstreamerGLTextureRenderer() -{ - if (m_surface && m_surface->isActive()) - m_surface->stop(); - - if (m_videoSink) - gst_object_unref(GST_OBJECT(m_videoSink)); -} - -GstElement *QGstreamerGLTextureRenderer::videoSink() -{ - if (!m_videoSink && isReady()) { - if (m_context && !m_surface->supportedPixelFormats(EGLImageTextureHandle).isEmpty()) { -#ifdef GL_TEXTURE_SINK_DEBUG - qDebug() << Q_FUNC_INFO << ": using gltexture sink"; -#endif - if (m_context) - m_context->makeCurrent(); - m_videoSink = gst_element_factory_make("gltexturesink", "egl-texture-sink"); - g_object_set(G_OBJECT(m_videoSink), - "x-display", QX11Info::display(), - "egl-display", eglGetDisplay((EGLNativeDisplayType)QX11Info::display()), - "egl-context", eglGetCurrentContext(), - "colorkey", m_colorKey.rgb(), - "autopaint-colorkey", false, - "use-framebuffer-memory", true, - "render-mode", m_overlayEnabled ? VIDEO_RENDERSWITCH_XOVERLAY_MODE - : VIDEO_RENDERSWITCH_TEXTURE_STREAMING_MODE, - (char*)NULL); - - g_signal_connect(G_OBJECT(m_videoSink), "frame-ready", G_CALLBACK(handleFrameReady), (gpointer)this); - } else { - qWarning() << Q_FUNC_INFO << ": Fallback to QVideoSurfaceGstSink since EGLImageTextureHandle is not supported"; - m_videoSink = reinterpret_cast<GstElement*>(QVideoSurfaceGstSink::createSink(m_surface)); - } - - if (m_videoSink) { - gst_object_ref(GST_OBJECT(m_videoSink)); //Take ownership - gst_object_sink(GST_OBJECT(m_videoSink)); - - GstPad *pad = gst_element_get_static_pad(m_videoSink,"sink"); - m_bufferProbeId = gst_pad_add_buffer_probe(pad, G_CALLBACK(padBufferProbe), this); - gst_object_unref(GST_OBJECT(pad)); - } - } - - return m_videoSink; -} - -QAbstractVideoSurface *QGstreamerGLTextureRenderer::surface() const -{ - return m_surface; -} - -void QGstreamerGLTextureRenderer::setSurface(QAbstractVideoSurface *surface) -{ - if (m_surface != surface) { -#ifdef GL_TEXTURE_SINK_DEBUG - qDebug() << Q_FUNC_INFO << surface; -#endif - - bool oldReady = isReady(); - - m_context = const_cast<QGLContext*>(QGLContext::currentContext()); - - if (m_videoSink) - gst_object_unref(GST_OBJECT(m_videoSink)); - - m_videoSink = 0; - - if (m_surface) { - disconnect(m_surface, SIGNAL(supportedFormatsChanged()), - this, SLOT(handleFormatChange())); - } - - m_surface = surface; - - if (oldReady != isReady()) - emit readyChanged(!oldReady); - - if (m_surface) { - connect(m_surface, SIGNAL(supportedFormatsChanged()), - this, SLOT(handleFormatChange())); - } - - emit sinkChanged(); - } -} - -void QGstreamerGLTextureRenderer::handleFormatChange() -{ - if (m_videoSink) - gst_object_unref(GST_OBJECT(m_videoSink)); - - m_videoSink = 0; - emit sinkChanged(); -} - -void QGstreamerGLTextureRenderer::handleFrameReady(GstElement *sink, gint frame, gpointer data) -{ - Q_UNUSED(sink); - QGstreamerGLTextureRenderer* renderer = reinterpret_cast<QGstreamerGLTextureRenderer*>(data); - - QMutexLocker locker(&renderer->m_mutex); - QMetaObject::invokeMethod(renderer, "renderGLFrame", - Qt::QueuedConnection, - Q_ARG(int, frame)); - - //we have to wait to ensure the frame is not reused, - //timeout is added to avoid deadlocks when the main thread is - //waiting for rendering to complete, this is possible for example during state chages. - //If frame is not rendered during 60ms (~1-2 frames interval) it's better to unblock and drop it if necessary - renderer->m_renderCondition.wait(&renderer->m_mutex, 60); -} - -void QGstreamerGLTextureRenderer::renderGLFrame(int frame) -{ -#if defined(GL_TEXTURE_SINK_DEBUG) && GL_TEXTURE_SINK_DEBUG > 1 - qDebug() << Q_FUNC_INFO << "frame:" << frame << "surface active:" << m_surface->isActive(); -#endif - QMutexLocker locker(&m_mutex); - - if (!m_surface) { - m_renderCondition.wakeAll(); - return; - } - - MeegoGstVideoTexture *textureSink = MEEGO_GST_VIDEO_TEXTURE(m_videoSink); - - if (m_context) - m_context->makeCurrent(); - - //don't try to render the frame if state is changed to NULL or READY - GstState pendingState = GST_STATE_NULL; - GstState newState = GST_STATE_NULL; - GstStateChangeReturn res = gst_element_get_state(m_videoSink, - &newState, - &pendingState, - 0);//don't block and return immediately - - if (res == GST_STATE_CHANGE_FAILURE || - newState == GST_STATE_NULL || - pendingState == GST_STATE_NULL) { - stopRenderer(); - m_renderCondition.wakeAll(); - return; - } - - if (!m_surface->isActive()) { - //find the native video size - GstPad *pad = gst_element_get_static_pad(m_videoSink,"sink"); - GstCaps *caps = gst_pad_get_negotiated_caps(pad); - - if (caps) { - QSize newNativeSize = QGstUtils::capsCorrectedResolution(caps); - if (m_nativeSize != newNativeSize) { - m_nativeSize = newNativeSize; - emit nativeSizeChanged(); - } - gst_caps_unref(caps); - } - - //start the surface... - QVideoSurfaceFormat format(m_nativeSize, QVideoFrame::Format_RGB32, EGLImageTextureHandle); - if (!m_surface->start(format)) { - qWarning() << Q_FUNC_INFO << "failed to start video surface" << format; - m_renderCondition.wakeAll(); - return; - } - } - - QGStreamerGLTextureBuffer *buffer = new QGStreamerGLTextureBuffer(textureSink, frame); - QVideoFrame videoFrame(buffer, - m_surface->surfaceFormat().frameSize(), - m_surface->surfaceFormat().pixelFormat()); - m_surface->present(videoFrame); - m_renderCondition.wakeAll(); -} - -bool QGstreamerGLTextureRenderer::isReady() const -{ - if (!m_surface) - return false; - - if (m_winId > 0) - return true; - - //winId is required only for EGLImageTextureHandle compatible surfaces - return m_surface->supportedPixelFormats(EGLImageTextureHandle).isEmpty(); -} - -bool QGstreamerGLTextureRenderer::processBusMessage(const QGstreamerMessage &message) -{ - GstMessage* gm = message.rawMessage(); - -#ifdef GL_TEXTURE_SINK_DEBUG - qDebug() << Q_FUNC_INFO << GST_MESSAGE_TYPE_NAME(gm); -#endif - - if (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_STATE_CHANGED && - GST_MESSAGE_SRC(gm) == GST_OBJECT_CAST(m_videoSink)) { - GstState oldState; - GstState newState; - gst_message_parse_state_changed(gm, &oldState, &newState, 0); - -#ifdef GL_TEXTURE_SINK_DEBUG - qDebug() << Q_FUNC_INFO << "State changed:" << oldState << newState; -#endif - - if (newState == GST_STATE_READY || newState == GST_STATE_NULL) { - stopRenderer(); - } - - if (oldState == GST_STATE_READY && newState == GST_STATE_PAUSED) { - updateNativeVideoSize(); - } - } - - return false; -} - -bool QGstreamerGLTextureRenderer::processSyncMessage(const QGstreamerMessage &message) -{ - GstMessage* gm = message.rawMessage(); - - if ((GST_MESSAGE_TYPE(gm) == GST_MESSAGE_ELEMENT) && - gst_structure_has_name(gm->structure, "prepare-xwindow-id") && - m_videoSink && GST_IS_X_OVERLAY(m_videoSink)) { -#ifdef GL_TEXTURE_SINK_DEBUG - qDebug() << Q_FUNC_INFO; -#endif - GstXOverlay *overlay = GST_X_OVERLAY(m_videoSink); - - gst_x_overlay_set_xwindow_id(overlay, m_winId); - - if (!m_displayRect.isEmpty()) { - gst_x_overlay_set_render_rectangle(overlay, - m_displayRect.x(), - m_displayRect.y(), - m_displayRect.width(), - m_displayRect.height()); - } - - GstPad *pad = gst_element_get_static_pad(m_videoSink,"sink"); - m_bufferProbeId = gst_pad_add_buffer_probe(pad, G_CALLBACK(padBufferProbe), this); - - return true; - } - - return false; -} - -void QGstreamerGLTextureRenderer::stopRenderer() -{ -#ifdef GL_TEXTURE_SINK_DEBUG - qDebug() << Q_FUNC_INFO; -#endif - - if (m_surface && m_surface->isActive()) - m_surface->stop(); - - if (!m_nativeSize.isEmpty()) { - m_nativeSize = QSize(); - emit nativeSizeChanged(); - } -} - -bool QGstreamerGLTextureRenderer::overlayEnabled() const -{ - return m_overlayEnabled; -} - -void QGstreamerGLTextureRenderer::setOverlayEnabled(bool enabled) -{ - - if (m_videoSink && (m_overlayEnabled != enabled)) { - qDebug() << Q_FUNC_INFO << enabled; - g_object_set(G_OBJECT(m_videoSink), - "render-mode", - enabled ? VIDEO_RENDERSWITCH_XOVERLAY_MODE : VIDEO_RENDERSWITCH_TEXTURE_STREAMING_MODE, - (char *)NULL); - } - - m_overlayEnabled = enabled; -} - - -WId QGstreamerGLTextureRenderer::winId() const -{ - return m_winId; -} - -void QGstreamerGLTextureRenderer::setWinId(WId id) -{ -#ifdef GL_TEXTURE_SINK_DEBUG - qDebug() << Q_FUNC_INFO << id; -#endif - - if (m_winId == id) - return; - - bool oldReady = isReady(); - - m_winId = id; - - if (m_videoSink && GST_IS_X_OVERLAY(m_videoSink)) { - //don't set winId in NULL state, - //texture sink opens xvideo port on set_xwindow_id, - //this fails if video resource is not granted by resource policy yet. - //state is changed to READY/PAUSED/PLAYING only after resource is granted. - GstState pendingState = GST_STATE_NULL; - GstState newState = GST_STATE_NULL; - GstStateChangeReturn res = gst_element_get_state(m_videoSink, - &newState, - &pendingState, - 0);//don't block and return immediately - - if (res != GST_STATE_CHANGE_FAILURE && - newState != GST_STATE_NULL && - pendingState != GST_STATE_NULL) - gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(m_videoSink), m_winId); - } - - if (oldReady != isReady()) - emit readyChanged(!oldReady); -} - -QRect QGstreamerGLTextureRenderer::overlayGeometry() const -{ - return m_displayRect; -} - -void QGstreamerGLTextureRenderer::setOverlayGeometry(const QRect &geometry) -{ - if (m_displayRect != geometry) { -#ifdef GL_TEXTURE_SINK_DEBUG - qDebug() << Q_FUNC_INFO << geometry; -#endif - m_displayRect = geometry; - - if (m_videoSink && GST_IS_X_OVERLAY(m_videoSink)) { - if (m_displayRect.isEmpty()) - gst_x_overlay_set_render_rectangle(GST_X_OVERLAY(m_videoSink), -1, -1, -1, -1); - else - gst_x_overlay_set_render_rectangle(GST_X_OVERLAY(m_videoSink), - m_displayRect.x(), - m_displayRect.y(), - m_displayRect.width(), - m_displayRect.height()); - repaintOverlay(); - } - } -} - -QColor QGstreamerGLTextureRenderer::colorKey() const -{ - return m_colorKey; -} - -void QGstreamerGLTextureRenderer::repaintOverlay() -{ - if (m_videoSink && GST_IS_X_OVERLAY(m_videoSink)) { - //don't call gst_x_overlay_expose if the sink is in null state - GstState state = GST_STATE_NULL; - GstStateChangeReturn res = gst_element_get_state(m_videoSink, &state, NULL, 1000000); - if (res != GST_STATE_CHANGE_FAILURE && state != GST_STATE_NULL) { - gst_x_overlay_expose(GST_X_OVERLAY(m_videoSink)); - } - } -} - -QSize QGstreamerGLTextureRenderer::nativeSize() const -{ - return m_nativeSize; -} - -gboolean QGstreamerGLTextureRenderer::padBufferProbe(GstPad *pad, GstBuffer *buffer, gpointer user_data) -{ - QGstreamerGLTextureRenderer *control = reinterpret_cast<QGstreamerGLTextureRenderer*>(user_data); - QMetaObject::invokeMethod(control, "updateNativeVideoSize", Qt::QueuedConnection); - gst_pad_remove_buffer_probe(pad, control->m_bufferProbeId); - - return TRUE; -} - -void QGstreamerGLTextureRenderer::updateNativeVideoSize() -{ - const QSize oldSize = m_nativeSize; - - if (m_videoSink) { - //find video native size to update video widget size hint - GstPad *pad = gst_element_get_static_pad(m_videoSink,"sink"); - GstCaps *caps = gst_pad_get_negotiated_caps(pad); - - if (caps) { - m_nativeSize = QGstUtils::capsCorrectedResolution(caps); - gst_caps_unref(caps); - } - } else { - m_nativeSize = QSize(); - } -#ifdef GL_TEXTURE_SINK_DEBUG - qDebug() << Q_FUNC_INFO << oldSize << m_nativeSize << m_videoSink; -#endif - - if (m_nativeSize != oldSize) - emit nativeSizeChanged(); -} 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/audioengine/audioengine.pro b/src/imports/audioengine/audioengine.pro index c00a6ec6b..1d46dfa33 100644 --- a/src/imports/audioengine/audioengine.pro +++ b/src/imports/audioengine/audioengine.pro @@ -5,10 +5,7 @@ IMPORT_VERSION = 1.1 QT += quick qml multimedia-private -win32: LIBS += -lOpenAL32 -unix:!mac:!blackberry: LIBS += -lopenal -blackberry: LIBS += -lOpenAL -mac: LIBS += -framework OpenAL +QMAKE_USE += openal mac: DEFINES += HEADER_OPENAL_PREFIX INCLUDEPATH += ../../multimedia/audio diff --git a/src/imports/imports.pro b/src/imports/imports.pro index d24bba59f..fcd9e3466 100644 --- a/src/imports/imports.pro +++ b/src/imports/imports.pro @@ -1,5 +1,6 @@ TEMPLATE = subdirs +QT_FOR_CONFIG += multimedia-private SUBDIRS += multimedia -config_openal: SUBDIRS += audioengine +qtConfig(openal): SUBDIRS += audioengine 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..d6d74a316 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 \ @@ -39,20 +40,12 @@ SOURCES += \ audio/qaudiodecoder.cpp \ audio/qaudiohelpers.cpp -unix:!mac { - config_pulseaudio { - CONFIG += link_pkgconfig - PKGCONFIG_PRIVATE += libpulse +qtConfig(pulseaudio) { + QMAKE_USE += pulseaudio - DEFINES += QT_MULTIMEDIA_PULSEAUDIO - PRIVATE_HEADERS += audio/qsoundeffect_pulse_p.h - SOURCES += audio/qsoundeffect_pulse_p.cpp - !maemo*:DEFINES += QTM_PULSEAUDIO_DEFAULTBUFFER - } else { - DEFINES += QT_MULTIMEDIA_QAUDIO - PRIVATE_HEADERS += audio/qsoundeffect_qaudio_p.h - SOURCES += audio/qsoundeffect_qaudio_p.cpp - } + DEFINES += QT_MULTIMEDIA_PULSEAUDIO + PRIVATE_HEADERS += audio/qsoundeffect_pulse_p.h + SOURCES += audio/qsoundeffect_pulse_p.cpp } else { DEFINES += QT_MULTIMEDIA_QAUDIO PRIVATE_HEADERS += audio/qsoundeffect_qaudio_p.h 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..1c38e9f35 100644 --- a/src/multimedia/audio/qaudio.h +++ b/src/multimedia/audio/qaudio.h @@ -41,7 +41,7 @@ #ifndef QAUDIO_H #define QAUDIO_H -#include <QtMultimedia/qtmultimediadefs.h> +#include <QtMultimedia/qtmultimediaglobal.h> #include <QtMultimedia/qmultimedia.h> #include <QtCore/qmetatype.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/qaudiobuffer.h b/src/multimedia/audio/qaudiobuffer.h index c45b56ed3..bed387462 100644 --- a/src/multimedia/audio/qaudiobuffer.h +++ b/src/multimedia/audio/qaudiobuffer.h @@ -42,7 +42,7 @@ #include <QtCore/qshareddata.h> -#include <QtMultimedia/qtmultimediadefs.h> +#include <QtMultimedia/qtmultimediaglobal.h> #include <QtMultimedia/qmultimedia.h> #include <QtMultimedia/qaudio.h> diff --git a/src/multimedia/audio/qaudiobuffer_p.h b/src/multimedia/audio/qaudiobuffer_p.h index 06233ca7c..e770989f2 100644 --- a/src/multimedia/audio/qaudiobuffer_p.h +++ b/src/multimedia/audio/qaudiobuffer_p.h @@ -51,7 +51,7 @@ // We mean it. // -#include <qtmultimediadefs.h> +#include <qtmultimediaglobal.h> #include <qmultimedia.h> #include "qaudioformat.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..238be46a7 100644 --- a/src/multimedia/audio/qaudiodevicefactory_p.h +++ b/src/multimedia/audio/qaudiodevicefactory_p.h @@ -54,7 +54,7 @@ #include <QtCore/qbytearray.h> #include <QtCore/qlist.h> -#include <qtmultimediadefs.h> +#include <qtmultimediaglobal.h> #include <qmultimedia.h> #include "qaudiodeviceinfo.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/qaudiodeviceinfo.h b/src/multimedia/audio/qaudiodeviceinfo.h index 709e6830a..390458b39 100644 --- a/src/multimedia/audio/qaudiodeviceinfo.h +++ b/src/multimedia/audio/qaudiodeviceinfo.h @@ -47,7 +47,7 @@ #include <QtCore/qstringlist.h> #include <QtCore/qlist.h> -#include <QtMultimedia/qtmultimediadefs.h> +#include <QtMultimedia/qtmultimediaglobal.h> #include <QtMultimedia/qmultimedia.h> #include <QtMultimedia/qaudio.h> diff --git a/src/multimedia/audio/qaudioformat.h b/src/multimedia/audio/qaudioformat.h index 2ae6d6aef..97779ea2c 100644 --- a/src/multimedia/audio/qaudioformat.h +++ b/src/multimedia/audio/qaudioformat.h @@ -44,7 +44,7 @@ #include <QtCore/qobject.h> #include <QtCore/qshareddata.h> -#include <QtMultimedia/qtmultimediadefs.h> +#include <QtMultimedia/qtmultimediaglobal.h> #include <QtMultimedia/qmultimedia.h> QT_BEGIN_NAMESPACE diff --git a/src/multimedia/audio/qaudioinput.cpp b/src/multimedia/audio/qaudioinput.cpp index 07165240b..872dce819 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) @@ -343,7 +348,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/qaudioinput.h b/src/multimedia/audio/qaudioinput.h index d1a58424e..5794276d2 100644 --- a/src/multimedia/audio/qaudioinput.h +++ b/src/multimedia/audio/qaudioinput.h @@ -43,7 +43,7 @@ #include <QtCore/qiodevice.h> -#include <QtMultimedia/qtmultimediadefs.h> +#include <QtMultimedia/qtmultimediaglobal.h> #include <QtMultimedia/qmultimedia.h> #include <QtMultimedia/qaudio.h> diff --git a/src/multimedia/audio/qaudiooutput.cpp b/src/multimedia/audio/qaudiooutput.cpp index e96d24dd7..e37da9bdf 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/qaudiooutput.h b/src/multimedia/audio/qaudiooutput.h index fab562ae1..9f817271d 100644 --- a/src/multimedia/audio/qaudiooutput.h +++ b/src/multimedia/audio/qaudiooutput.h @@ -43,7 +43,7 @@ #include <QtCore/qiodevice.h> -#include <QtMultimedia/qtmultimediadefs.h> +#include <QtMultimedia/qtmultimediaglobal.h> #include <QtMultimedia/qmultimedia.h> #include <QtMultimedia/qaudio.h> diff --git a/src/multimedia/audio/qaudiosystem.h b/src/multimedia/audio/qaudiosystem.h index 1a927589d..dabf8df0b 100644 --- a/src/multimedia/audio/qaudiosystem.h +++ b/src/multimedia/audio/qaudiosystem.h @@ -40,7 +40,7 @@ #ifndef QAUDIOSYSTEM_H #define QAUDIOSYSTEM_H -#include <QtMultimedia/qtmultimediadefs.h> +#include <QtMultimedia/qtmultimediaglobal.h> #include <QtMultimedia/qmultimedia.h> #include <QtMultimedia/qaudio.h> 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/qaudiosystemplugin.h b/src/multimedia/audio/qaudiosystemplugin.h index b26b2a3b9..3368c9b98 100644 --- a/src/multimedia/audio/qaudiosystemplugin.h +++ b/src/multimedia/audio/qaudiosystemplugin.h @@ -44,7 +44,7 @@ #include <QtCore/qstring.h> #include <QtCore/qplugin.h> -#include <QtMultimedia/qtmultimediadefs.h> +#include <QtMultimedia/qtmultimediaglobal.h> #include <QtMultimedia/qmultimedia.h> #include <QtMultimedia/qaudioformat.h> diff --git a/src/plugins/directshow/player/directshowmediatypelist.h b/src/multimedia/audio/qaudiosystempluginext_p.h index 2bd8dca59..6493b7f77 100644 --- a/src/plugins/directshow/player/directshowmediatypelist.h +++ b/src/multimedia/audio/qaudiosystempluginext_p.h @@ -37,34 +37,35 @@ ** ****************************************************************************/ -#ifndef DIRECTSHOWMEDIATYPELIST_H -#define DIRECTSHOWMEDIATYPELIST_H +#ifndef QAUDIOSYSTEMPLUGINEXT_P_H +#define QAUDIOSYSTEMPLUGINEXT_P_H -#include <dshow.h> +#include <QtMultimedia/qtmultimediaglobal.h> +#include <QtMultimedia/qaudio.h> +#include <QtCore/qplugin.h> -#include <QtCore/qvector.h> +QT_BEGIN_NAMESPACE -class DirectShowMediaTypeList : public IUnknown -{ -public: - DirectShowMediaTypeList(); - virtual ~DirectShowMediaTypeList(); - - IEnumMediaTypes *createMediaTypeEnum(); - - void setMediaTypes(const QVector<AM_MEDIA_TYPE> &types); +// +// 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. +// - 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); +struct Q_MULTIMEDIA_EXPORT QAudioSystemPluginExtension +{ + virtual QByteArray defaultDevice(QAudio::Mode) const = 0; + virtual ~QAudioSystemPluginExtension(); +}; -protected: - QVector<AM_MEDIA_TYPE> m_mediaTypes; +#define QAudioSystemPluginExtension_iid "org.qt-project.qt.audiosystempluginextension" +Q_DECLARE_INTERFACE(QAudioSystemPluginExtension, QAudioSystemPluginExtension_iid) -private: - int m_mediaTypeToken; -}; +QT_END_NAMESPACE -#endif +#endif // QAUDIOSYSTEMPLUGINEXT_P_H diff --git a/src/multimedia/audio/qsound.h b/src/multimedia/audio/qsound.h index f8d47676f..304019ced 100644 --- a/src/multimedia/audio/qsound.h +++ b/src/multimedia/audio/qsound.h @@ -40,7 +40,7 @@ #ifndef QSOUND_H #define QSOUND_H -#include <QtMultimedia/qtmultimediadefs.h> +#include <QtMultimedia/qtmultimediaglobal.h> #include <QtCore/qobject.h> QT_BEGIN_NAMESPACE diff --git a/src/multimedia/audio/qsoundeffect.cpp b/src/multimedia/audio/qsoundeffect.cpp index f7237679b..f8b8d7b18 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/audio/qsoundeffect.h b/src/multimedia/audio/qsoundeffect.h index f59c4d91d..7420d7b81 100644 --- a/src/multimedia/audio/qsoundeffect.h +++ b/src/multimedia/audio/qsoundeffect.h @@ -40,7 +40,7 @@ #ifndef QSOUNDEFFECT_H #define QSOUNDEFFECT_H -#include <QtMultimedia/qtmultimediadefs.h> +#include <QtMultimedia/qtmultimediaglobal.h> #include <QtCore/qobject.h> #include <QtCore/qurl.h> #include <QtCore/qstringlist.h> diff --git a/src/multimedia/audio/qsoundeffect_pulse_p.cpp b/src/multimedia/audio/qsoundeffect_pulse_p.cpp index fcf4fee35..2e2dfc2db 100644 --- a/src/multimedia/audio/qsoundeffect_pulse_p.cpp +++ b/src/multimedia/audio/qsoundeffect_pulse_p.cpp @@ -62,9 +62,6 @@ #include <unistd.h> //#define QT_PA_DEBUG -#ifndef QTM_PULSEAUDIO_DEFAULTBUFFER -#define QT_PA_STREAM_BUFFER_SIZE_MAX (1024 * 64) //64KB is a trade-off for balancing control latency and uploading overhead -#endif QT_BEGIN_NAMESPACE @@ -679,7 +676,6 @@ void QSoundEffectPrivate::sampleReady() #ifdef QT_PA_DEBUG qDebug() << this << "reuse existing pulsestream"; #endif -#ifdef QTM_PULSEAUDIO_DEFAULTBUFFER const pa_buffer_attr *bufferAttr = pa_stream_get_buffer_attr(m_pulseStream); if (bufferAttr->prebuf > uint32_t(m_sample->data().size())) { pa_buffer_attr newBufferAttr; @@ -693,33 +689,6 @@ void QSoundEffectPrivate::sampleReady() } else { streamReady(); } -#else - const pa_buffer_attr *bufferAttr = pa_stream_get_buffer_attr(m_pulseStream); - if (bufferAttr->tlength < m_sample->data().size() && bufferAttr->tlength < QT_PA_STREAM_BUFFER_SIZE_MAX) { - pa_buffer_attr newBufferAttr; - newBufferAttr.maxlength = -1; - newBufferAttr.tlength = qMin(m_sample->data().size(), QT_PA_STREAM_BUFFER_SIZE_MAX); - newBufferAttr.minreq = bufferAttr->tlength / 2; - newBufferAttr.prebuf = -1; - newBufferAttr.fragsize = -1; - pa_operation *op = pa_stream_set_buffer_attr(m_pulseStream, &newBufferAttr, stream_reset_buffer_callback, m_ref->getRef()); - if (op) - pa_operation_unref(op); - else - qWarning("QSoundEffect(pulseaudio): failed to adjust pre-buffer attribute"); - } else if (bufferAttr->prebuf > uint32_t(m_sample->data().size())) { - pa_buffer_attr newBufferAttr; - newBufferAttr = *bufferAttr; - newBufferAttr.prebuf = m_sample->data().size(); - pa_operation *op = pa_stream_set_buffer_attr(m_pulseStream, &newBufferAttr, stream_adjust_prebuffer_callback, m_ref->getRef()); - if (op) - pa_operation_unref(op); - else - qWarning("QSoundEffect(pulseaudio): failed to adjust pre-buffer attribute"); - } else { - streamReady(); - } -#endif } else { if (!pulseDaemon()->context() || pa_context_get_state(pulseDaemon()->context()) != PA_CONTEXT_READY) { connect(pulseDaemon(), SIGNAL(contextReady()), SLOT(contextReady())); @@ -963,17 +932,7 @@ void QSoundEffectPrivate::createPulseStream() } m_pulseStream = stream; -#ifndef QTM_PULSEAUDIO_DEFAULTBUFFER - pa_buffer_attr bufferAttr; - bufferAttr.tlength = qMin(m_sample->data().size(), QT_PA_STREAM_BUFFER_SIZE_MAX); - bufferAttr.maxlength = -1; - bufferAttr.minreq = bufferAttr.tlength / 2; - bufferAttr.prebuf = -1; - bufferAttr.fragsize = -1; - if (pa_stream_connect_playback(m_pulseStream, 0, &bufferAttr, -#else if (pa_stream_connect_playback(m_pulseStream, 0, 0, -#endif PA_STREAM_START_CORKED, 0, 0) < 0) { qWarning("QSoundEffect(pulseaudio): Failed to connect stream, error = %s", pa_strerror(pa_context_errno(pulseDaemon()->context()))); @@ -1048,39 +1007,6 @@ void QSoundEffectPrivate::stream_state_callback(pa_stream *s, void *userdata) } } -void QSoundEffectPrivate::stream_reset_buffer_callback(pa_stream *s, int success, void *userdata) -{ -#ifdef QT_PA_DEBUG - qDebug() << "stream_reset_buffer_callback"; -#endif - Q_UNUSED(s); - QSoundEffectRef *ref = reinterpret_cast<QSoundEffectRef*>(userdata); - QSoundEffectPrivate *self = ref->soundEffect(); - ref->release(); - if (!self) - return; - - if (!success) - qWarning("QSoundEffect(pulseaudio): failed to reset buffer attribute"); -#ifdef QT_PA_DEBUG - qDebug() << self << "stream_reset_buffer_callback"; -#endif - const pa_buffer_attr *bufferAttr = pa_stream_get_buffer_attr(self->m_pulseStream); - self->m_pulseBufferSize = bufferAttr->tlength; - if (bufferAttr->prebuf > uint32_t(self->m_sample->data().size())) { - pa_buffer_attr newBufferAttr; - newBufferAttr = *bufferAttr; - newBufferAttr.prebuf = self->m_sample->data().size(); - pa_operation *op = pa_stream_set_buffer_attr(self->m_pulseStream, &newBufferAttr, stream_adjust_prebuffer_callback, userdata); - if (op) - pa_operation_unref(op); - else - qWarning("QSoundEffect(pulseaudio): failed to adjust pre-buffer attribute"); - } else { - QMetaObject::invokeMethod(self, "streamReady", Qt::QueuedConnection); - } -} - void QSoundEffectPrivate::stream_adjust_prebuffer_callback(pa_stream *s, int success, void *userdata) { #ifdef QT_PA_DEBUG diff --git a/src/multimedia/audio/qsoundeffect_pulse_p.h b/src/multimedia/audio/qsoundeffect_pulse_p.h index 020aa031a..7be88c55a 100644 --- a/src/multimedia/audio/qsoundeffect_pulse_p.h +++ b/src/multimedia/audio/qsoundeffect_pulse_p.h @@ -148,7 +148,6 @@ private: static void stream_flush_reload_callback(pa_stream *s, int success, void *userdata); static void stream_write_done_callback(void *p); static void stream_adjust_prebuffer_callback(pa_stream *s, int success, void *userdata); - static void stream_reset_buffer_callback(pa_stream *s, int success, void *userdata); pa_stream *m_pulseStream; int m_sinkInputId; diff --git a/src/multimedia/camera/qcameraviewfindersettings.h b/src/multimedia/camera/qcameraviewfindersettings.h index df544dd8f..432bdcf1f 100644 --- a/src/multimedia/camera/qcameraviewfindersettings.h +++ b/src/multimedia/camera/qcameraviewfindersettings.h @@ -40,7 +40,7 @@ #ifndef QCAMERAVIEWFINDERSETTINGS_H #define QCAMERAVIEWFINDERSETTINGS_H -#include <QtMultimedia/qtmultimediadefs.h> +#include <QtMultimedia/qtmultimediaglobal.h> #include <QtMultimedia/qvideoframe.h> #include <QtCore/qshareddata.h> diff --git a/src/multimedia/configure.json b/src/multimedia/configure.json new file mode 100644 index 000000000..19812d19b --- /dev/null +++ b/src/multimedia/configure.json @@ -0,0 +1,314 @@ +{ + "module": "multimedia", + "depends": [ + "gui" + ], + "testDir": "../../config.tests", + + "commandline": { + "options": { + "alsa": "boolean", + "gstreamer": { "type": "optionalString", "values": [ "no", "yes", "0.10", "1.0" ] }, + "pulseaudio": "boolean", + "wmf-backend": "boolean" + } + }, + + "libraries": { + "alsa": { + "label": "ALSA", + "test": "alsa", + "sources": [ + "-lasound" + ] + }, + "avfoundation": { + "label": "AVFoundation", + "test": "avfoundation", + "sources": [ + { "libs": "-framework AVFoundation -framework Foundation" } + ] + }, + "directshow": { + "label": "DirectShow", + "test": "directshow", + "sources": [ + { "libs": "-lstrmiids -ldmoguids -luuid -lmsdmo -lole32 -loleaut32" } + ] + }, + "gstreamer_0_10": { + "label": "GStreamer 0.10", + "export": "gstreamer", + "test": "gstreamer", + "sources": [ + { "type": "pkgConfig", + "args": "gstreamer-0.10 gstreamer-base-0.10 gstreamer-audio-0.10 gstreamer-video-0.10 gstreamer-pbutils-0.10 gstreamer-interfaces-0.10" } + ] + }, + "gstreamer_1_0": { + "label": "GStreamer 1.0", + "export": "gstreamer", + "test": "gstreamer", + "sources": [ + { "type": "pkgConfig", + "args": "gstreamer-1.0 gstreamer-base-1.0 gstreamer-audio-1.0 gstreamer-video-1.0 gstreamer-pbutils-1.0" } + ] + }, + "gstreamer_app_0_10": { + "label": "GStreamer App 0.10", + "export": "gstreamer_app", + "test": "gstreamer_appsrc", + "use": "gstreamer_0_10", + "sources": [ + { "type": "pkgConfig", "args": "gstreamer-app-0.10" } + ] + }, + "gstreamer_app_1_0": { + "label": "GStreamer App 1.0", + "export": "gstreamer_app", + "test": "gstreamer_appsrc", + "use": "gstreamer_1_0", + "sources": [ + { "type": "pkgConfig", "args": "gstreamer-app-1.0" } + ] + }, + "gstreamer_photography_0_10": { + "label": "GStreamer Photography 0.10", + "export": "gstreamer_photography", + "test": "gstreamer_photography", + "use": "gstreamer_0_10", + "sources": [ + { "libs": "-lgstphotography-0.10" } + ] + }, + "gstreamer_photography_1_0": { + "label": "GStreamer Photography 1.0", + "export": "gstreamer_photography", + "test": "gstreamer_photography", + "use": "gstreamer_1_0", + "sources": [ + { "libs": "-lgstphotography-1.0" } + ] + }, + "libresourceqt5": { + "label": "libresourceqt5", + "test": "resourcepolicy", + "sources": [ + { "type": "pkgConfig", "args": "libresourceqt5" } + ] + }, + "mmrenderer": { + "label": "MMRenderer", + "test": "mmrenderer", + "sources": [ + { "libs": "-lmmrndclient -lstrm" } + ] + }, + "openal": { + "label": "OpenAL", + "test": "openal", + "sources": [ + { "type": "pkgConfig", "args": "openal" }, + { "libs": "-lOpenAL32", "condition": "config.win32" }, + { "libs": "-framework OpenAL", "condition": "config.darwin" }, + { "libs": "-lopenal", "condition": "config.unix && !config.darwin" } + ] + }, + "pulseaudio": { + "label": "PulseAudio >= 0.9.10", + "test": "pulseaudio", + "sources": [ + { "type": "pkgConfig", "args": "libpulse >= 0.9.10 libpulse-mainloop-glib" } + ] + }, + "wmf": { + "label": "WMF", + "test": "wmf", + "sources": [ + { "libs": "-lstrmiids -ldmoguids -luuid -lmsdmo -lole32 -loleaut32 -lMf -lMfuuid -lMfplat -lPropsys" } + ] + } + }, + + "tests": { + "evr": { + "label": "evr.h", + "type": "compile", + "test": "evr" + }, + "gstreamer_encodingprofiles_1_0": { + "label": "GStreamer encoding-profile.h", + "type": "compile", + "use": "gstreamer_1_0", + "test": "gstreamer_encodingprofiles" + }, + "gstreamer_encodingprofiles_0_10": { + "label": "GStreamer encoding-profile.h", + "type": "compile", + "use": "gstreamer_0_10", + "test": "gstreamer_encodingprofiles" + }, + "gpu_vivante": { + "label": "Vivante GPU", + "type": "compile", + "test": "gpu_vivante" + }, + "linux_v4l": { + "label": "Video for Linux", + "type": "compile", + "test": "linux_v4l" + }, + "wasapi": { + "label": "Windows Audio Services", + "type": "compile", + "test": "wasapi" + }, + "wmsdk": { + "label": "wmsdk.h", + "type": "compile", + "test": "wmsdk" + }, + "wshellitem": { + "label": "WShellItem", + "type": "compile", + "test": "wshellitem" + } + }, + + "features": { + "alsa": { + "label": "ALSA", + "condition": "config.unix && libs.alsa", + "output": [ "feature", "privateFeature" ] + }, + "avfoundation": { + "label": "AVFoundation", + "emitIf": "config.darwin", + "condition": "libs.avfoundation", + "output": [ "feature", "privateFeature" ] + }, + "directshow": { + "label": "DirectShow", + "condition": "config.win32 && libs.directshow", + "output": [ "feature", "privateFeature" ] + }, + "evr": { + "label": "evr.h", + "condition": "config.win32 && tests.evr", + "output": [ "feature", "privateFeature" ] + }, + "gstreamer_0_10": { + "label": "GStreamer 0.10", + "disable": "input.gstreamer == '1.0' || input.gstreamer == 'no'", + "enable": "input.gstreamer == '0.10'", + "condition": "!features.gstreamer_1_0 && libs.gstreamer_0_10", + "output": [ "privateFeature" ] + }, + "gstreamer_1_0": { + "label": "GStreamer 1.0", + "disable": "input.gstreamer == '0.10' || input.gstreamer == 'no'", + "enable": "input.gstreamer == '1.0'", + "condition": "libs.gstreamer_1_0", + "output": [ "privateFeature" ] + }, + "gstreamer": { + "condition": "features.gstreamer_1_0 || features.gstreamer_0_10", + "output": [ "privateFeature" ] + }, + "gstreamer_app": { + "label": "GStreamer App", + "condition": "(features.gstreamer_1_0 && libs.gstreamer_app_1_0) + || (features.gstreamer_0_10 && libs.gstreamer_app_0_10)", + "output": [ "privateFeature" ] + }, + "gstreamer_encodingprofiles": { + "label": "GStreamer encoding-profile.h", + "condition": "(features.gstreamer_1_0 && tests.gstreamer_encodingprofiles_1_0) + || (features.gstreamer_0_10 && tests.gstreamer_encodingprofiles_0_10)", + "output": [ "privateFeature" ] + }, + "gstreamer_photography": { + "label": "GStreamer Photography", + "condition": "(features.gstreamer_1_0 && libs.gstreamer_photography_1_0) + || (features.gstreamer_0_10 && libs.gstreamer_photography_0_10)", + "output": [ "privateFeature" ] + }, + "gpu_vivante": { + "label": "Vivante GPU", + "condition": "features.opengles2 && tests.gpu_vivante", + "output": [ "privateFeature" ] + }, + "resourcepolicy": { + "label": "Resource Policy (libresourceqt5)", + "condition": "libs.libresourceqt5", + "output": [ "privateFeature" ] + }, + "linux_v4l": { + "label": "Video for Linux", + "condition": "config.unix && tests.linux_v4l", + "output": [ "privateFeature" ] + }, + "mmrenderer": { + "label": "MMRenderer", + "emitIf": "config.qnx", + "condition": "libs.mmrenderer", + "output": [ "feature", "privateFeature" ] + }, + "openal": { + "label": "OpenAL", + "condition": "libs.openal", + "output": [ "feature", "privateFeature" ] + }, + "pulseaudio": { + "label": "PulseAudio", + "autoDetect": "config.unix", + "condition": "libs.pulseaudio", + "output": [ "feature", "privateFeature" ] + }, + "wasapi": { + "label": "Windows Audio Services", + "autoDetect": "false", + "condition": "config.win32 && tests.wasapi", + "output": [ "privateFeature" ] + }, + "wmsdk": { + "label": "wmsdk.h", + "condition": "config.win32 && tests.wmsdk", + "output": [ "feature", "privateFeature" ] + }, + "wshellitem": { + "label": "WShellItem", + "condition": "config.win32 && features.directshow && tests.wshellitem", + "output": [ "feature", "privateFeature" ] + }, + "wmf-backend": { + "label": "Windows Media Foundation backend for Qt Multimedia", + "emitIf": "config.win32", + "autoDetect": false, + "condition": "libraries.wmf", + "output": [ "privateFeature" ] + } + }, + + "report": [ + ], + + "summary": [ + { + "section": "Qt Multimedia", + "entries": [ + "alsa", + "gstreamer_1_0", + "gstreamer_0_10", + "linux_v4l", + "openal", + "pulseaudio", + "resourcepolicy", + "mmrenderer", + "avfoundation", + "directshow", + "wmf-backend" + ] + } + ] +} 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 abffc6811..e4667d369 100644 --- a/src/multimedia/controls/qmediarecordercontrol.cpp +++ b/src/multimedia/controls/qmediarecordercontrol.cpp @@ -160,15 +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) + \fn void QMediaRecorderControl::setVolume(qreal volume) - Sets the audio \a gain of a media recorder control. + Sets the audio \a volume of a media recorder control. - The gain is scaled linearly, ranging from \c 0 (silence) to \c 100 (full volume). + The volume is scaled linearly, ranging from \c 0 (silence) to \c 100 (full volume). */ /*! diff --git a/src/multimedia/controls/qmediastreamscontrol.h b/src/multimedia/controls/qmediastreamscontrol.h index ea12dd188..3c36e96cb 100644 --- a/src/multimedia/controls/qmediastreamscontrol.h +++ b/src/multimedia/controls/qmediastreamscontrol.h @@ -43,7 +43,7 @@ #include <QtMultimedia/qmediacontrol.h> #include <QtMultimedia/qmultimedia.h> -#include <QtMultimedia/qtmultimediadefs.h> +#include <QtMultimedia/qtmultimediaglobal.h> #include <QtMultimedia/qmediaenumdebug.h> QT_BEGIN_NAMESPACE diff --git a/src/multimedia/controls/qmetadatareadercontrol.h b/src/multimedia/controls/qmetadatareadercontrol.h index 9162d6454..455ce814e 100644 --- a/src/multimedia/controls/qmetadatareadercontrol.h +++ b/src/multimedia/controls/qmetadatareadercontrol.h @@ -45,7 +45,7 @@ #include <QtMultimedia/qmediaresource.h> -#include <QtMultimedia/qtmultimediadefs.h> +#include <QtMultimedia/qtmultimediaglobal.h> #include <QtMultimedia/qmultimedia.h> QT_BEGIN_NAMESPACE diff --git a/src/multimedia/controls/qmetadatawritercontrol.h b/src/multimedia/controls/qmetadatawritercontrol.h index 1c2f4cf69..da3413f77 100644 --- a/src/multimedia/controls/qmetadatawritercontrol.h +++ b/src/multimedia/controls/qmetadatawritercontrol.h @@ -45,7 +45,7 @@ #include <QtMultimedia/qmediaresource.h> -#include <QtMultimedia/qtmultimediadefs.h> +#include <QtMultimedia/qtmultimediaglobal.h> #include <QtMultimedia/qmultimedia.h> QT_BEGIN_NAMESPACE diff --git a/src/multimedia/controls/qradiodatacontrol.cpp b/src/multimedia/controls/qradiodatacontrol.cpp index 59c7c8cb1..eaa9aaed6 100644 --- a/src/multimedia/controls/qradiodatacontrol.cpp +++ b/src/multimedia/controls/qradiodatacontrol.cpp @@ -37,7 +37,7 @@ ** ****************************************************************************/ -#include <qtmultimediadefs.h> +#include <qtmultimediaglobal.h> #include "qradiodatacontrol.h" #include "qmediacontrol_p.h" diff --git a/src/multimedia/controls/qradiotunercontrol.cpp b/src/multimedia/controls/qradiotunercontrol.cpp index 5e5c1d5a7..8b9e865e1 100644 --- a/src/multimedia/controls/qradiotunercontrol.cpp +++ b/src/multimedia/controls/qradiotunercontrol.cpp @@ -37,7 +37,7 @@ ** ****************************************************************************/ -#include <qtmultimediadefs.h> +#include <qtmultimediaglobal.h> #include "qradiotunercontrol.h" #include "qmediacontrol_p.h" 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/doc/src/blackberry.qdoc b/src/multimedia/doc/src/blackberry.qdoc deleted file mode 100644 index 28c176deb..000000000 --- a/src/multimedia/doc/src/blackberry.qdoc +++ /dev/null @@ -1,86 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Research In Motion -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the documentation of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:FDL$ -** 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 Free Documentation License Usage -** Alternatively, this file may be used under the terms of the GNU Free -** Documentation License version 1.3 as published by the Free Software -** Foundation and appearing in the file included in the packaging of -** this file. Please review the following information to ensure -** the GNU Free Documentation License version 1.3 requirements -** will be met: http://www.gnu.org/copyleft/fdl.html. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/*! -\page blackberry.html -\title Qt Multimedia on BlackBerry -\brief Platform notes for the BlackBerry Platform - -Qt Multimedia supports BlackBerry devices that run the BB10 operating system. -This page covers the availability of different features on BB10. - -\section1 Implementation - -BB10 ships with a few different multimedia libraries. The main library for audio -and video playback is \e mmrenderer. For low-latency output of raw audio samples, -\e libasound, a variant of the Linux ALSA library, is available. Finally, for -three-dimensional positional audio playback, \e OpenAL is supported and present -on BB10. - -The Qt Multimedia BlackBerry backend uses mmrenderer for media playback. - -For the positional audio classes in the \l{Qt Audio Engine QML Types}{Qt Audio Engine} -QML module, OpenAL is used as on all other platforms. - -For recording videos and taking photos, the camapi library is used. - -\section1 Supported Features - -Playback of audio and video with QMediaPlayer and related classes is supported. -This includes the corresponding QML elements like MediaPlayer and VideoOutput. -Since the playback is delegated to mmrenderer, the supported formats are the same as in -mmrenderer. As mmrenderer supports streaming from HTTP and other URLs, this is -supported in QMediaPlayer as well. Playlists as sources are also supported. - -mmrenderer does not allow access to the pixel data of video frames, hence Qt Multimedia -classes like QVideoFrame and QAbstractVideoSurface will not work since they require access -to the image data. QVideoWidget and the VideoOutput QML element are implemented with an overlay window; -mmrenderer creates a separate window displaying a video and puts that on top of the Qt application. -As a consequence, no other widget or QML element can be put on top of the video, and QML shaders have -no effect. - -The \l{Qt Audio Engine QML Types}{Qt Audio Engine} QML module is fully supported, as it is based on OpenAL which is available -in BB10. - -The \l {camera} {QCamera} support includes recording of videos and taking photos. The viewfinder -is available through QCameraViewfinder and the VideoOutput QML element. - -Note: To use the camera on BB10, your application needs the 'access_shared', 'use_camera' and 'record_audio' -permissions set in the bar-descriptor.xml file. - -\section1 Unsupported Features - -Low-latency output and input of raw audio samples with QAudioOutput, QAudioInput and related classes is -not yet supported. The SoundEffect QML element and QSoundEffect are based on these classes. In your -QML file, use the MediaPlayer element instead of the SoundEffect element, as the APIs are nearly identical. - -QMediaPlayer does not support QIODevice-based streaming sources. However, streaming by specifying, for example, -an HTTP URL as the source does work. In addition, QMediaPlayer does not yet provide metadata like -the artist and album of the current track. - -Radio and audio recording are not yet supported. -*/ diff --git a/src/multimedia/doc/src/multimedia.qdoc b/src/multimedia/doc/src/multimedia.qdoc index 84df488d2..944d8c4d7 100644 --- a/src/multimedia/doc/src/multimedia.qdoc +++ b/src/multimedia/doc/src/multimedia.qdoc @@ -177,7 +177,7 @@ what changed, and what you might need to change when porting code. \section2 QML Types The QML types are accessed by using: \code -import QtMultimedia 5.7 +import QtMultimedia 5.8 \endcode \annotatedlist multimedia_qml The following types are accessed by using \l{Qt Audio Engine QML Types}{Qt Audio Engine}: diff --git a/src/multimedia/doc/src/qtmultimedia-index.qdoc b/src/multimedia/doc/src/qtmultimedia-index.qdoc index a474a355e..553732fd1 100644 --- a/src/multimedia/doc/src/qtmultimedia-index.qdoc +++ b/src/multimedia/doc/src/qtmultimedia-index.qdoc @@ -54,7 +54,7 @@ import statement in your \c {.qml} file. \code - import QtMultimedia 5.7 + import QtMultimedia 5.8 \endcode If you intend to use the C++ classes in your application, include the C++ @@ -157,7 +157,6 @@ following topics provide more platform-specific information. \list - \li \l{Qt Multimedia on BlackBerry}{BlackBerry} \li \l{Qt Multimedia on Windows}{Windows} \endlist diff --git a/src/multimedia/doc/src/qtmultimedia5.qdoc b/src/multimedia/doc/src/qtmultimedia5.qdoc index bc200819b..29ef2734e 100644 --- a/src/multimedia/doc/src/qtmultimedia5.qdoc +++ b/src/multimedia/doc/src/qtmultimedia5.qdoc @@ -26,7 +26,7 @@ ****************************************************************************/ /*! -\qmlmodule QtMultimedia 5.7 +\qmlmodule QtMultimedia 5.8 \title Qt Multimedia QML Types \ingroup qmlmodules \brief Provides QML types for multimedia support. @@ -42,7 +42,7 @@ The QML types for \l{Qt Multimedia} support the basic use cases such as: The QML types can be imported into your application using the following import statement in your .qml file: \code -import QtMultimedia 5.7 +import QtMultimedia 5.8 \endcode \section1 QML types diff --git a/src/multimedia/gsttools_headers/qgstreamergltexturerenderer_p.h b/src/multimedia/gsttools_headers/qgstreamergltexturerenderer_p.h deleted file mode 100644 index 8abdd1e02..000000000 --- a/src/multimedia/gsttools_headers/qgstreamergltexturerenderer_p.h +++ /dev/null @@ -1,141 +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 QGSTREAMERGLTEXTURERENDERER_H -#define QGSTREAMERGLTEXTURERENDERER_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <qvideorenderercontrol.h> -#include <private/qvideosurfacegstsink_p.h> -#include <private/qgstreamerbushelper_p.h> - -#include "qgstreamervideorendererinterface_p.h" -#include <QtGui/qcolor.h> - -#include <X11/extensions/Xv.h> - -QT_BEGIN_NAMESPACE - -class QGLContext; - -class QGstreamerGLTextureRenderer : public QVideoRendererControl, - public QGstreamerVideoRendererInterface, - public QGstreamerSyncMessageFilter, - public QGstreamerBusMessageFilter -{ - Q_OBJECT - Q_INTERFACES(QGstreamerVideoRendererInterface QGstreamerSyncMessageFilter QGstreamerBusMessageFilter) - - Q_PROPERTY(bool overlayEnabled READ overlayEnabled WRITE setOverlayEnabled) - Q_PROPERTY(qulonglong winId READ winId WRITE setWinId) - Q_PROPERTY(QRect overlayGeometry READ overlayGeometry WRITE setOverlayGeometry) - Q_PROPERTY(QColor colorKey READ colorKey) - Q_PROPERTY(QSize nativeSize READ nativeSize NOTIFY nativeSizeChanged) - -public: - QGstreamerGLTextureRenderer(QObject *parent = 0); - virtual ~QGstreamerGLTextureRenderer(); - - QAbstractVideoSurface *surface() const; - void setSurface(QAbstractVideoSurface *surface); - - GstElement *videoSink(); - - bool isReady() const; - bool processBusMessage(const QGstreamerMessage &message); - bool processSyncMessage(const QGstreamerMessage &message); - void stopRenderer(); - - int framebufferNumber() const; - - bool overlayEnabled() const; - WId winId() const; - QRect overlayGeometry() const; - QColor colorKey() const; - QSize nativeSize() const; - -public slots: - void renderGLFrame(int); - - void setOverlayEnabled(bool); - void setWinId(WId id); - void setOverlayGeometry(const QRect &geometry); - void repaintOverlay(); - -signals: - void sinkChanged(); - void readyChanged(bool); - void nativeSizeChanged(); - -private slots: - void handleFormatChange(); - void updateNativeVideoSize(); - -private: - static void handleFrameReady(GstElement *sink, gint frame, gpointer data); - static gboolean padBufferProbe(GstPad *pad, GstBuffer *buffer, gpointer user_data); - - GstElement *m_videoSink; - QAbstractVideoSurface *m_surface; - QGLContext *m_context; - QSize m_nativeSize; - - WId m_winId; - QColor m_colorKey; - QRect m_displayRect; - bool m_overlayEnabled; - int m_bufferProbeId; - - QMutex m_mutex; - QWaitCondition m_renderCondition; -}; - -QT_END_NAMESPACE - -#endif // QGSTREAMERVIDEORENDRER_H diff --git a/src/multimedia/multimedia.pro b/src/multimedia/multimedia.pro index 761e488ba..0f3f3ff6b 100644 --- a/src/multimedia/multimedia.pro +++ b/src/multimedia/multimedia.pro @@ -15,6 +15,7 @@ QMAKE_DOCS = $$PWD/doc/qtmultimedia.qdocconf INCLUDEPATH *= . PRIVATE_HEADERS += \ + qtmultimediaglobal_p.h \ qmediacontrol_p.h \ qmediaobject_p.h \ qmediapluginloader_p.h \ @@ -28,6 +29,7 @@ PRIVATE_HEADERS += \ qmultimediautils_p.h PUBLIC_HEADERS += \ + qtmultimediaglobal.h \ qmediabindableinterface.h \ qmediacontrol.h \ qmediaenumdebug.h \ @@ -36,8 +38,7 @@ PUBLIC_HEADERS += \ qmediaservice.h \ qmediaserviceproviderplugin.h \ qmediatimerange.h \ - qmultimedia.h \ - qtmultimediadefs.h \ + qmultimedia.h SOURCES += \ qmediabindableinterface.cpp \ diff --git a/src/multimedia/playback/playlistfileparser_p.h b/src/multimedia/playback/playlistfileparser_p.h index 353da3eca..bdf95fe7a 100644 --- a/src/multimedia/playback/playlistfileparser_p.h +++ b/src/multimedia/playback/playlistfileparser_p.h @@ -51,7 +51,7 @@ // We mean it. // -#include "qtmultimediadefs.h" +#include "qtmultimediaglobal.h" #include <QtNetwork/QNetworkRequest> QT_BEGIN_NAMESPACE diff --git a/src/multimedia/playback/qmediacontent.h b/src/multimedia/playback/qmediacontent.h index 25db6ecf5..f7c086752 100644 --- a/src/multimedia/playback/qmediacontent.h +++ b/src/multimedia/playback/qmediacontent.h @@ -45,7 +45,7 @@ #include <QtMultimedia/qmediaresource.h> -#include <QtMultimedia/qtmultimediadefs.h> +#include <QtMultimedia/qtmultimediaglobal.h> QT_BEGIN_NAMESPACE diff --git a/src/multimedia/playback/qmediaplayer.cpp b/src/multimedia/playback/qmediaplayer.cpp index fdb7ef7fa..c9b9b4fc1 100644 --- a/src/multimedia/playback/qmediaplayer.cpp +++ b/src/multimedia/playback/qmediaplayer.cpp @@ -143,7 +143,7 @@ public: bool hasStreamPlaybackFeature; QMediaPlaylist *parentPlaylist(QMediaPlaylist *pls); - bool isInChain(QUrl url); + bool isInChain(const QUrl &url); 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/playback/qmediaplaylistioplugin_p.h b/src/multimedia/playback/qmediaplaylistioplugin_p.h index 62bb6757a..73281b2bf 100644 --- a/src/multimedia/playback/qmediaplaylistioplugin_p.h +++ b/src/multimedia/playback/qmediaplaylistioplugin_p.h @@ -54,7 +54,7 @@ #include <QtCore/qobject.h> #include <QtCore/qplugin.h> -#include <qtmultimediadefs.h> +#include <qtmultimediaglobal.h> #include "qmediacontent.h" diff --git a/src/multimedia/playback/qmediaresource.h b/src/multimedia/playback/qmediaresource.h index 83f998eb9..9740166c6 100644 --- a/src/multimedia/playback/qmediaresource.h +++ b/src/multimedia/playback/qmediaresource.h @@ -44,7 +44,7 @@ #include <QtCore/qmetatype.h> #include <QtNetwork/qnetworkrequest.h> -#include <QtMultimedia/qtmultimediadefs.h> +#include <QtMultimedia/qtmultimediaglobal.h> QT_BEGIN_NAMESPACE diff --git a/src/multimedia/qmediacontrol.h b/src/multimedia/qmediacontrol.h index 3c95444d0..680b18e7f 100644 --- a/src/multimedia/qmediacontrol.h +++ b/src/multimedia/qmediacontrol.h @@ -40,7 +40,7 @@ #ifndef QABSTRACTMEDIACONTROL_H #define QABSTRACTMEDIACONTROL_H -#include <QtMultimedia/qtmultimediadefs.h> +#include <QtMultimedia/qtmultimediaglobal.h> #include <QtCore/qobject.h> #include <QtCore/qstring.h> diff --git a/src/multimedia/qmediacontrol_p.h b/src/multimedia/qmediacontrol_p.h index 948f9fdd5..e9827fd1e 100644 --- a/src/multimedia/qmediacontrol_p.h +++ b/src/multimedia/qmediacontrol_p.h @@ -51,7 +51,7 @@ // We mean it. // -#include <qtmultimediadefs.h> +#include <qtmultimediaglobal.h> QT_BEGIN_NAMESPACE diff --git a/src/multimedia/qmediametadata.h b/src/multimedia/qmediametadata.h index 2fb49c88e..8d8744490 100644 --- a/src/multimedia/qmediametadata.h +++ b/src/multimedia/qmediametadata.h @@ -44,7 +44,7 @@ #include <QtCore/qmetatype.h> #include <QtCore/qstring.h> -#include <QtMultimedia/qtmultimediadefs.h> +#include <QtMultimedia/qtmultimediaglobal.h> QT_BEGIN_NAMESPACE diff --git a/src/multimedia/qmediaobject.h b/src/multimedia/qmediaobject.h index efd89f840..5788254b8 100644 --- a/src/multimedia/qmediaobject.h +++ b/src/multimedia/qmediaobject.h @@ -43,7 +43,7 @@ #include <QtCore/qobject.h> #include <QtCore/qstringlist.h> -#include <QtMultimedia/qtmultimediadefs.h> +#include <QtMultimedia/qtmultimediaglobal.h> #include <QtMultimedia/qmultimedia.h> QT_BEGIN_NAMESPACE 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/qmediapluginloader_p.h b/src/multimedia/qmediapluginloader_p.h index 9798f2ae8..a4e726544 100644 --- a/src/multimedia/qmediapluginloader_p.h +++ b/src/multimedia/qmediapluginloader_p.h @@ -51,7 +51,7 @@ // We mean it. // -#include <qtmultimediadefs.h> +#include <qtmultimediaglobal.h> #include <QtCore/qobject.h> #include <QtCore/qstring.h> #include <QtCore/qstringlist.h> diff --git a/src/multimedia/qmediaresourcepolicy_p.h b/src/multimedia/qmediaresourcepolicy_p.h index bfc89df84..13e3f4913 100644 --- a/src/multimedia/qmediaresourcepolicy_p.h +++ b/src/multimedia/qmediaresourcepolicy_p.h @@ -52,7 +52,7 @@ // #include <QObject> -#include "qtmultimediadefs.h" +#include "qtmultimediaglobal.h" QT_BEGIN_NAMESPACE diff --git a/src/multimedia/qmediaresourcepolicyplugin_p.h b/src/multimedia/qmediaresourcepolicyplugin_p.h index 66cef02d6..7b53c3b3a 100644 --- a/src/multimedia/qmediaresourcepolicyplugin_p.h +++ b/src/multimedia/qmediaresourcepolicyplugin_p.h @@ -52,7 +52,7 @@ // #include <QObject> -#include <qtmultimediadefs.h> +#include <qtmultimediaglobal.h> QT_BEGIN_NAMESPACE diff --git a/src/multimedia/qmediaresourceset_p.h b/src/multimedia/qmediaresourceset_p.h index 1df6e19e5..a0158877f 100644 --- a/src/multimedia/qmediaresourceset_p.h +++ b/src/multimedia/qmediaresourceset_p.h @@ -51,7 +51,7 @@ // We mean it. // #include <QObject> -#include <qtmultimediadefs.h> +#include <qtmultimediaglobal.h> QT_BEGIN_NAMESPACE diff --git a/src/multimedia/qmediaservice.h b/src/multimedia/qmediaservice.h index 64fe63b84..9e653b2d8 100644 --- a/src/multimedia/qmediaservice.h +++ b/src/multimedia/qmediaservice.h @@ -40,7 +40,7 @@ #ifndef QABSTRACTMEDIASERVICE_H #define QABSTRACTMEDIASERVICE_H -#include <QtMultimedia/qtmultimediadefs.h> +#include <QtMultimedia/qtmultimediaglobal.h> #include <QtCore/qobject.h> #include <QtCore/qstringlist.h> diff --git a/src/multimedia/qmediaserviceprovider_p.h b/src/multimedia/qmediaserviceprovider_p.h index 63e1bdd18..4ca9c9e8f 100644 --- a/src/multimedia/qmediaserviceprovider_p.h +++ b/src/multimedia/qmediaserviceprovider_p.h @@ -53,7 +53,7 @@ #include <QtCore/qobject.h> #include <QtCore/qshareddata.h> -#include <qtmultimediadefs.h> +#include <qtmultimediaglobal.h> #include "qmultimedia.h" #include "qmediaserviceproviderplugin.h" diff --git a/src/multimedia/qmediaserviceproviderplugin.h b/src/multimedia/qmediaserviceproviderplugin.h index 6cdc18d61..43fe55d43 100644 --- a/src/multimedia/qmediaserviceproviderplugin.h +++ b/src/multimedia/qmediaserviceproviderplugin.h @@ -43,7 +43,7 @@ #include <QtCore/qstringlist.h> #include <QtCore/qplugin.h> #include <QtMultimedia/qmultimedia.h> -#include <QtMultimedia/qtmultimediadefs.h> +#include <QtMultimedia/qtmultimediaglobal.h> #include <QtMultimedia/qcamera.h> #ifdef Q_MOC_RUN 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/qmediastoragelocation_p.h b/src/multimedia/qmediastoragelocation_p.h index 29e6a5775..13399b54d 100644 --- a/src/multimedia/qmediastoragelocation_p.h +++ b/src/multimedia/qmediastoragelocation_p.h @@ -51,7 +51,7 @@ // We mean it. // -#include <qtmultimediadefs.h> +#include <qtmultimediaglobal.h> #include <QDir> #include <QMap> #include <QHash> 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/qmediatimerange.h b/src/multimedia/qmediatimerange.h index a9eab2498..0b4fe8e67 100644 --- a/src/multimedia/qmediatimerange.h +++ b/src/multimedia/qmediatimerange.h @@ -40,7 +40,7 @@ #ifndef QMEDIATIMERANGE_H #define QMEDIATIMERANGE_H -#include <QtMultimedia/qtmultimediadefs.h> +#include <QtMultimedia/qtmultimediaglobal.h> #include <QtMultimedia/qmultimedia.h> #include <QtCore/qshareddata.h> diff --git a/src/multimedia/qmultimedia.h b/src/multimedia/qmultimedia.h index b517b5a32..a3dbc5e3e 100644 --- a/src/multimedia/qmultimedia.h +++ b/src/multimedia/qmultimedia.h @@ -44,7 +44,7 @@ #include <QtCore/qmetatype.h> #include <QtCore/qstring.h> -#include <QtMultimedia/qtmultimediadefs.h> +#include <QtMultimedia/qtmultimediaglobal.h> QT_BEGIN_NAMESPACE diff --git a/src/plugins/gstreamer/camerabin/camerabuttonlistener_meego.h b/src/multimedia/qtmultimediaglobal.h index 776640ed4..ae11ed271 100644 --- a/src/plugins/gstreamer/camerabin/camerabuttonlistener_meego.h +++ b/src/multimedia/qtmultimediaglobal.h @@ -3,7 +3,7 @@ ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Toolkit. +** This file is part of the QtQml module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage @@ -37,31 +37,23 @@ ** ****************************************************************************/ +#ifndef QTMULTIMEDIAGLOBAL_H +#define QTMULTIMEDIAGLOBAL_H -#ifndef CAMERABUTTONLISTENER_MEEGO_H -#define CAMERABUTTONLISTENER_MEEGO_H - -#include <QtCore/qobject.h> -#include <qmsystem2/qmkeys.h> +#include <QtGui/qtguiglobal.h> +#include <QtMultimedia/qtmultimedia-config.h> QT_BEGIN_NAMESPACE -class CameraButtonListener : public QObject -{ - Q_OBJECT -public: - CameraButtonListener(QObject *parent = 0); - ~CameraButtonListener(); - -private slots: - void handleQmKeyEvent(MeeGo::QmKeys::Key key, MeeGo::QmKeys::State state); - -private: - MeeGo::QmKeys *m_keys; - bool m_focusPressed; - bool m_shutterPressed; -}; +#ifndef QT_STATIC +# if defined(QT_BUILD_MULTIMEDIA_LIB) +# define Q_MULTIMEDIA_EXPORT Q_DECL_EXPORT +# else +# define Q_MULTIMEDIA_EXPORT Q_DECL_IMPORT +# endif +#else +# define Q_MULTIMEDIA_EXPORT +#endif QT_END_NAMESPACE - -#endif // CAMERABUTTONLISTENER_MEEGO_H +#endif // QTQMLGLOBAL_H diff --git a/src/multimedia/qtmultimediaglobal_p.h b/src/multimedia/qtmultimediaglobal_p.h new file mode 100644 index 000000000..797142029 --- /dev/null +++ b/src/multimedia/qtmultimediaglobal_p.h @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQml module 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 QTMULTIMEDIAGLOBAL_P_H +#define QTMULTIMEDIAGLOBAL_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtGui/private/qtguiglobal_p.h> +#include <QtMultimedia/private/qtmultimedia-config_p.h> +#include <QtMultimedia/qtmultimediaglobal.h> + +#endif // QTQMLGLOBAL_P_H diff --git a/src/multimedia/recording/qmediaencodersettings.h b/src/multimedia/recording/qmediaencodersettings.h index d6f92ca5c..0d6a9eddf 100644 --- a/src/multimedia/recording/qmediaencodersettings.h +++ b/src/multimedia/recording/qmediaencodersettings.h @@ -44,7 +44,7 @@ #include <QtCore/qstring.h> #include <QtCore/qsize.h> #include <QtCore/qvariant.h> -#include <QtMultimedia/qtmultimediadefs.h> +#include <QtMultimedia/qtmultimediaglobal.h> #include <QtMultimedia/qmultimedia.h> QT_BEGIN_NAMESPACE diff --git a/src/multimedia/recording/qmediarecorder.cpp b/src/multimedia/recording/qmediarecorder.cpp index 65eaed159..d3962b78f 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/multimedia/video/qabstractvideobuffer.h b/src/multimedia/video/qabstractvideobuffer.h index 7b246a712..dcefdf7bc 100644 --- a/src/multimedia/video/qabstractvideobuffer.h +++ b/src/multimedia/video/qabstractvideobuffer.h @@ -40,7 +40,7 @@ #ifndef QABSTRACTVIDEOBUFFER_H #define QABSTRACTVIDEOBUFFER_H -#include <QtMultimedia/qtmultimediadefs.h> +#include <QtMultimedia/qtmultimediaglobal.h> #include <QtMultimedia/qmultimedia.h> diff --git a/src/multimedia/video/qabstractvideobuffer_p.h b/src/multimedia/video/qabstractvideobuffer_p.h index cae018d3c..6fbd75a30 100644 --- a/src/multimedia/video/qabstractvideobuffer_p.h +++ b/src/multimedia/video/qabstractvideobuffer_p.h @@ -54,7 +54,7 @@ #include <QtCore/qshareddata.h> #include "qabstractvideobuffer.h" -#include <qtmultimediadefs.h> +#include <qtmultimediaglobal.h> #include <qmultimedia.h> diff --git a/src/multimedia/video/qvideooutputorientationhandler_p.h b/src/multimedia/video/qvideooutputorientationhandler_p.h index cf3ddbdb2..b5cfc089b 100644 --- a/src/multimedia/video/qvideooutputorientationhandler_p.h +++ b/src/multimedia/video/qvideooutputorientationhandler_p.h @@ -51,7 +51,7 @@ // We mean it. // -#include <qtmultimediadefs.h> +#include <qtmultimediaglobal.h> #include <QObject> diff --git a/src/multimediawidgets/multimediawidgets.pro b/src/multimediawidgets/multimediawidgets.pro index 60321fba8..c37868933 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 \ @@ -20,27 +17,11 @@ PUBLIC_HEADERS += \ SOURCES += \ qcameraviewfinder.cpp \ + qgraphicsvideoitem.cpp \ qpaintervideosurface.cpp \ qvideowidgetcontrol.cpp \ qvideowidget.cpp -maemo6 { - contains(QT_CONFIG, opengles2) { - PRIVATE_HEADERS += qeglimagetexturesurface_p.h - SOURCES += qeglimagetexturesurface.cpp - - SOURCES += qgraphicsvideoitem_maemo6.cpp - - LIBS_PRIVATE += -lX11 - } else { - SOURCES += qgraphicsvideoitem.cpp - } -} - -!maemo* { - SOURCES += qgraphicsvideoitem.cpp -} - HEADERS += $$PUBLIC_HEADERS $$PRIVATE_HEADERS load(qt_module) diff --git a/src/multimediawidgets/qeglimagetexturesurface.cpp b/src/multimediawidgets/qeglimagetexturesurface.cpp deleted file mode 100644 index 5e2073a48..000000000 --- a/src/multimediawidgets/qeglimagetexturesurface.cpp +++ /dev/null @@ -1,533 +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 <qeglimagetexturesurface_p.h> -#include <qpaintervideosurface_p.h> - -#include <QtCore/qmath.h> -#include <QtCore/qvariant.h> -#include <QtCore/qdebug.h> -#include <QtGui/qpainter.h> -#include <QtWidgets/qx11info_x11.h> -#include <qvideosurfaceformat.h> - - -QT_BEGIN_NAMESPACE - -//#define DEBUG_OMAPFB_SURFACE - -const QAbstractVideoBuffer::HandleType EGLImageTextureHandle = -QAbstractVideoBuffer::HandleType(QAbstractVideoBuffer::UserHandle+3434); - -/*! - \class QEglImageTextureSurface - \internal -*/ - -/*! -*/ -QEglImageTextureSurface::QEglImageTextureSurface(QObject *parent) - : QAbstractVideoSurface(parent) - , m_context(0) - , m_program(0) - , m_pixelFormat(QVideoFrame::Format_Invalid) - , m_ready(false) - , m_colorKey(49,0,49) - , m_fallbackSurface(0) - , m_fallbackSurfaceActive(false) -{ - m_fallbackSurface = new QPainterVideoSurface(this); -} - -/*! -*/ -QEglImageTextureSurface::~QEglImageTextureSurface() -{ - if (isActive()) - stop(); -} - -/*! -*/ -QList<QVideoFrame::PixelFormat> QEglImageTextureSurface::supportedPixelFormats( - QAbstractVideoBuffer::HandleType handleType) const -{ -#ifdef DEBUG_OMAPFB_SURFACE - qDebug() << Q_FUNC_INFO << handleType; -#endif - - if (handleType == EGLImageTextureHandle) { - return QList<QVideoFrame::PixelFormat>() - << QVideoFrame::Format_RGB32 - << QVideoFrame::Format_ARGB32; - } - - return m_fallbackSurface->supportedPixelFormats(handleType); -} - -const char *qt_glsl_eglTextureVertexShaderProgram = - "attribute highp vec4 vertexCoordArray;\n" - "attribute mediump vec2 textureCoordArray;\n" - "uniform highp mat4 positionMatrix;\n" - "varying mediump vec2 textureCoord;\n" - "void main (void)\n" - "{\n" - " gl_Position = positionMatrix * vertexCoordArray;\n" - " textureCoord = textureCoordArray;\n" - "}"; - -static const char* qt_glsl_eglTextureShaderProgram = - "#extension GL_OES_EGL_image_external: enable\n" - "\n" - "uniform samplerExternalOES texRgb;\n" - "varying mediump vec2 textureCoord;\n" - "\n" - "void main (void)\n" - "{\n" - " gl_FragColor = texture2D(texRgb, textureCoord);\n" - "}"; - - -/*! -*/ -bool QEglImageTextureSurface::start(const QVideoSurfaceFormat &format) -{ -#ifdef DEBUG_OMAPFB_SURFACE - qDebug() << Q_FUNC_INFO << format; -#endif - - m_fallbackSurfaceActive = false; - if (format.handleType() != EGLImageTextureHandle) { - qWarning() << Q_FUNC_INFO << "Non EGLImageTextureHandle based format requested, fallback to QPainterVideoSurface"; - connect(m_fallbackSurface, SIGNAL(activeChanged(bool)), - this, SIGNAL(activeChanged(bool))); - connect(m_fallbackSurface, SIGNAL(surfaceFormatChanged(QVideoSurfaceFormat)), - this, SIGNAL(surfaceFormatChanged(QVideoSurfaceFormat))); - connect(m_fallbackSurface, SIGNAL(supportedFormatsChanged()), - this, SIGNAL(supportedFormatsChanged())); - connect(m_fallbackSurface, SIGNAL(nativeResolutionChanged(QSize)), - this, SIGNAL(nativeResolutionChanged(QSize))); - connect(m_fallbackSurface, SIGNAL(frameChanged()), - this, SIGNAL(frameChanged())); - - if (m_fallbackSurface->start(format)) { - m_fallbackSurfaceActive = true; - QAbstractVideoSurface::start(format); - } else { - qWarning() << Q_FUNC_INFO << "failed to start video surface:" << m_fallbackSurface->error(); - setError(m_fallbackSurface->error()); - - disconnect(m_fallbackSurface, SIGNAL(activeChanged(bool)), - this, SIGNAL(activeChanged(bool))); - disconnect(m_fallbackSurface, SIGNAL(surfaceFormatChanged(QVideoSurfaceFormat)), - this, SIGNAL(surfaceFormatChanged(QVideoSurfaceFormat))); - disconnect(m_fallbackSurface, SIGNAL(supportedFormatsChanged()), - this, SIGNAL(supportedFormatsChanged())); - disconnect(m_fallbackSurface, SIGNAL(nativeResolutionChanged(QSize)), - this, SIGNAL(nativeResolutionChanged(QSize))); - disconnect(m_fallbackSurface, SIGNAL(frameChanged()), - this, SIGNAL(frameChanged())); - } - - return m_fallbackSurfaceActive; - } - - QAbstractVideoSurface::Error error = NoError; - - if (isActive()) - stop(); - - if (format.frameSize().isEmpty()) { - setError(UnsupportedFormatError); - } else if (m_context) { - m_context->makeCurrent(); - m_program = new QGLShaderProgram(m_context, this); - - if (!m_program->addShaderFromSourceCode(QGLShader::Vertex, qt_glsl_eglTextureVertexShaderProgram)) { - qWarning("QOmapFbVideoSurface: Vertex shader compile error %s", - qPrintable(m_program->log())); - error = ResourceError; - } - - if (error == NoError - && !m_program->addShaderFromSourceCode(QGLShader::Fragment, qt_glsl_eglTextureShaderProgram)) { - qWarning("QOmapFbVideoSurface: Vertex shader compile error %s", - qPrintable(m_program->log())); - error = QAbstractVideoSurface::ResourceError; - } - - if (error == NoError) { - m_program->bindAttributeLocation("textureCoordArray", 1); - if(!m_program->link()) { - qWarning("QOmapFbVideoSurface: Shader link error %s", qPrintable(m_program->log())); - m_program->removeAllShaders(); - error = QAbstractVideoSurface::ResourceError; - } - } - - if (error != QAbstractVideoSurface::NoError) { - delete m_program; - m_program = 0; - } - } - - if (error == QAbstractVideoSurface::NoError) { - m_scanLineDirection = format.scanLineDirection(); - m_frameSize = format.frameSize(); - m_pixelFormat = format.pixelFormat(); - m_frameSize = format.frameSize(); - m_sourceRect = format.viewport(); - m_ready = true; - - return QAbstractVideoSurface::start(format); - } - - QAbstractVideoSurface::stop(); - return false; -} - -/*! -*/ -void QEglImageTextureSurface::stop() -{ -#ifdef DEBUG_OMAPFB_SURFACE - qDebug() << Q_FUNC_INFO; -#endif - - if (m_fallbackSurfaceActive) { - m_fallbackSurface->stop(); - m_fallbackSurfaceActive = false; - - disconnect(m_fallbackSurface, SIGNAL(activeChanged(bool)), - this, SIGNAL(activeChanged(bool))); - disconnect(m_fallbackSurface, SIGNAL(surfaceFormatChanged(QVideoSurfaceFormat)), - this, SIGNAL(surfaceFormatChanged(QVideoSurfaceFormat))); - disconnect(m_fallbackSurface, SIGNAL(supportedFormatsChanged()), - this, SIGNAL(supportedFormatsChanged())); - disconnect(m_fallbackSurface, SIGNAL(nativeResolutionChanged(QSize)), - this, SIGNAL(nativeResolutionChanged(QSize))); - disconnect(m_fallbackSurface, SIGNAL(frameChanged()), - this, SIGNAL(frameChanged())); - - m_ready = false; - QAbstractVideoSurface::stop(); - } - - if (isActive()) { - if (m_context) - m_context->makeCurrent(); - m_frame = QVideoFrame(); - - m_program->removeAllShaders(); - delete m_program; - m_program = 0; - m_ready = false; - - QAbstractVideoSurface::stop(); - } -} - -/*! -*/ -bool QEglImageTextureSurface::present(const QVideoFrame &frame) -{ - if (m_fallbackSurfaceActive) { - if (m_fallbackSurface->present(frame)) { - return true; - } else { - setError(m_fallbackSurface->error()); - stop(); - return false; - } - } - - if (!m_ready) { - if (!isActive()) - setError(StoppedError); - else - m_frame = frame; - } else if (frame.isValid() - && (frame.pixelFormat() != m_pixelFormat || frame.size() != m_frameSize)) { - setError(IncorrectFormatError); - qWarning() << "Received frame of incorrect format, stopping the surface"; - - stop(); - } else { - if (m_context) - m_context->makeCurrent(); - m_frame = frame; - m_ready = false; - emit frameChanged(); - return true; - } - return false; -} - -/*! -*/ -int QEglImageTextureSurface::brightness() const -{ - return m_fallbackSurface->brightness(); -} - -/*! -*/ -void QEglImageTextureSurface::setBrightness(int brightness) -{ - m_fallbackSurface->setBrightness(brightness); -} - -/*! -*/ -int QEglImageTextureSurface::contrast() const -{ - return m_fallbackSurface->contrast(); -} - -/*! -*/ -void QEglImageTextureSurface::setContrast(int contrast) -{ - m_fallbackSurface->setContrast(contrast); -} - -/*! -*/ -int QEglImageTextureSurface::hue() const -{ - return m_fallbackSurface->hue(); -} - -/*! -*/ -void QEglImageTextureSurface::setHue(int hue) -{ - m_fallbackSurface->setHue(hue); -} - -/*! -*/ -int QEglImageTextureSurface::saturation() const -{ - return m_fallbackSurface->saturation(); -} - -/*! -*/ -void QEglImageTextureSurface::setSaturation(int saturation) -{ - m_fallbackSurface->setSaturation(saturation); -} - -/*! -*/ -bool QEglImageTextureSurface::isReady() const -{ - return m_fallbackSurfaceActive ? m_fallbackSurface->isReady() : m_ready; -} - -/*! -*/ -void QEglImageTextureSurface::setReady(bool ready) -{ - m_ready = ready; - if (m_fallbackSurfaceActive) - m_fallbackSurface->setReady(ready); -} - -/*! -*/ -void QEglImageTextureSurface::paint(QPainter *painter, const QRectF &target, const QRectF &sourceRect) -{ - if (m_fallbackSurfaceActive) { - m_fallbackSurface->paint(painter, target, sourceRect); - return; - } - - if (!isActive() || !m_frame.isValid()) { - painter->fillRect(target, QBrush(Qt::black)); - } else { - const QRectF source( - m_sourceRect.x() + m_sourceRect.width() * sourceRect.x(), - m_sourceRect.y() + m_sourceRect.height() * sourceRect.y(), - m_sourceRect.width() * sourceRect.width(), - m_sourceRect.height() * sourceRect.height()); - - bool stencilTestEnabled = glIsEnabled(GL_STENCIL_TEST); - bool scissorTestEnabled = glIsEnabled(GL_SCISSOR_TEST); - - painter->beginNativePainting(); - - if (stencilTestEnabled) - glEnable(GL_STENCIL_TEST); - if (scissorTestEnabled) - glEnable(GL_SCISSOR_TEST); - - const int width = QGLContext::currentContext()->device()->width(); - const int height = QGLContext::currentContext()->device()->height(); - - const QTransform transform = painter->deviceTransform(); - - const GLfloat wfactor = 2.0 / width; - const GLfloat hfactor = -2.0 / height; - - const GLfloat positionMatrix[4][4] = - { - { - /*(0,0)*/ GLfloat(wfactor * transform.m11() - transform.m13()), - /*(0,1)*/ GLfloat(hfactor * transform.m12() + transform.m13()), - /*(0,2)*/ 0.0, - /*(0,3)*/ GLfloat(transform.m13()) - }, { - /*(1,0)*/ GLfloat(wfactor * transform.m21() - transform.m23()), - /*(1,1)*/ GLfloat(hfactor * transform.m22() + transform.m23()), - /*(1,2)*/ 0.0, - /*(1,3)*/ GLfloat(transform.m23()) - }, { - /*(2,0)*/ 0.0, - /*(2,1)*/ 0.0, - /*(2,2)*/ -1.0, - /*(2,3)*/ 0.0 - }, { - /*(3,0)*/ GLfloat(wfactor * transform.dx() - transform.m33()), - /*(3,1)*/ GLfloat(hfactor * transform.dy() + transform.m33()), - /*(3,2)*/ 0.0, - /*(3,3)*/ GLfloat(transform.m33()) - } - }; - - const GLfloat vTop = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom - ? target.top() - : target.bottom() + 1; - const GLfloat vBottom = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom - ? target.bottom() + 1 - : target.top(); - - - const GLfloat vertexCoordArray[] = - { - GLfloat(target.left()) , GLfloat(vBottom), - GLfloat(target.right() + 1), GLfloat(vBottom), - GLfloat(target.left()) , GLfloat(vTop), - GLfloat(target.right() + 1), GLfloat(vTop) - }; - - const GLfloat txLeft = source.left() / m_frameSize.width(); - const GLfloat txRight = source.right() / m_frameSize.width(); - const GLfloat txTop = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom - ? source.top() / m_frameSize.height() - : source.bottom() / m_frameSize.height(); - const GLfloat txBottom = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom - ? source.bottom() / m_frameSize.height() - : source.top() / m_frameSize.height(); - - const GLfloat textureCoordArray[] = - { - txLeft , txBottom, - txRight, txBottom, - txLeft , txTop, - txRight, txTop - }; - - m_program->bind(); - - m_program->enableAttributeArray("vertexCoordArray"); - m_program->enableAttributeArray("textureCoordArray"); - m_program->setAttributeArray("vertexCoordArray", vertexCoordArray, 2); - m_program->setAttributeArray("textureCoordArray", textureCoordArray, 2); - m_program->setUniformValue("positionMatrix", positionMatrix); - m_program->setUniformValue("texRgb", 0); - - //map() binds the external texture - m_frame.map(QAbstractVideoBuffer::ReadOnly); - - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - - //it's necessary to unbind the external texture - m_frame.unmap(); - - m_program->release(); - - painter->endNativePainting(); - } -} - -/*! - \fn QEglImageTextureSurface::frameChanged() -*/ - -/*! -*/ -const QGLContext *QEglImageTextureSurface::glContext() const -{ - return m_context; -} - -/*! -*/ -void QEglImageTextureSurface::setGLContext(QGLContext *context) -{ - if (m_context == context) - return; - - stop(); - - m_context = context; - - m_fallbackSurface->setGLContext(context); - if (m_fallbackSurface->supportedShaderTypes() & QPainterVideoSurface::GlslShader) { - m_fallbackSurface->setShaderType(QPainterVideoSurface::GlslShader); - } else { - m_fallbackSurface->setShaderType(QPainterVideoSurface::FragmentProgramShader); - } - - emit supportedFormatsChanged(); -} - -void QEglImageTextureSurface::viewportDestroyed() -{ - m_context = 0; - m_fallbackSurface->viewportDestroyed(); - - setError(ResourceError); - stop(); -} - -#include "moc_qeglimagetexturesurface_p.cpp" -QT_END_NAMESPACE diff --git a/src/multimediawidgets/qeglimagetexturesurface_p.h b/src/multimediawidgets/qeglimagetexturesurface_p.h deleted file mode 100644 index 8affe4dc3..000000000 --- a/src/multimediawidgets/qeglimagetexturesurface_p.h +++ /dev/null @@ -1,142 +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 QEGLIMAGETEXTURESURFACE_P_H -#define QEGLIMAGETEXTURESURFACE_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <qtmultimediawidgetdefs.h> -#include <QtCore/qsize.h> -#include <QtGui/qimage.h> -#include <QtGui/qmatrix4x4.h> -#include <QtGui/qpaintengine.h> - -#include <QtOpenGL/qglshaderprogram.h> - -#include <qabstractvideosurface.h> -#include <qvideosurfaceformat.h> -#include <qvideoframe.h> - -QT_BEGIN_NAMESPACE - -class QGLContext; -class QGLShaderProgram; -class QPainterVideoSurface; - -class QEglImageTextureSurface : public QAbstractVideoSurface -{ - Q_OBJECT -public: - explicit QEglImageTextureSurface(QObject *parent = 0); - ~QEglImageTextureSurface(); - - QList<QVideoFrame::PixelFormat> supportedPixelFormats( - QAbstractVideoBuffer::HandleType handleType = QAbstractVideoBuffer::NoHandle) const; - - bool start(const QVideoSurfaceFormat &format); - void stop(); - - bool present(const QVideoFrame &frame); - - int brightness() const; - void setBrightness(int brightness); - - int contrast() const; - void setContrast(int contrast); - - int hue() const; - void setHue(int hue); - - int saturation() const; - void setSaturation(int saturation); - - bool isReady() const; - void setReady(bool ready); - - void paint(QPainter *painter, const QRectF &target, const QRectF &source = QRectF(0, 0, 1, 1)); - - const QGLContext *glContext() const; - void setGLContext(QGLContext *context); - - bool isOverlayEnabled() const; - void setOverlayEnabled(bool enabled); - - QRect displayRect() const; - void setDisplayRect(const QRect &rect); - -public Q_SLOTS: - void viewportDestroyed(); - -Q_SIGNALS: - void frameChanged(); - -private: - QGLContext *m_context; - QGLShaderProgram *m_program; - - QVideoFrame m_frame; - - QVideoFrame::PixelFormat m_pixelFormat; - QVideoSurfaceFormat::Direction m_scanLineDirection; - QSize m_frameSize; - QRect m_sourceRect; - bool m_ready; - - QRect m_viewport; - QRect m_displayRect; - QColor m_colorKey; - - QPainterVideoSurface *m_fallbackSurface; - bool m_fallbackSurfaceActive; -}; - -QT_END_NAMESPACE - - -#endif diff --git a/src/multimediawidgets/qgraphicsvideoitem.cpp b/src/multimediawidgets/qgraphicsvideoitem.cpp index 1259f1583..584cb429a 100644 --- a/src/multimediawidgets/qgraphicsvideoitem.cpp +++ b/src/multimediawidgets/qgraphicsvideoitem.cpp @@ -48,7 +48,7 @@ #include <QtCore/qcoreevent.h> #include <QtCore/qpointer.h> -#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1) +#if QT_CONFIG(opengl) #include <QtOpenGL/qgl.h> #endif @@ -372,7 +372,7 @@ void QGraphicsVideoItem::paint( if (d->surface && d->updatePaintDevice) { d->updatePaintDevice = false; -#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1) +#if QT_CONFIG(opengl) if (widget) connect(widget, SIGNAL(destroyed()), d->surface, SLOT(viewportDestroyed())); diff --git a/src/multimediawidgets/qgraphicsvideoitem_maemo6.cpp b/src/multimediawidgets/qgraphicsvideoitem_maemo6.cpp deleted file mode 100644 index caedaeee1..000000000 --- a/src/multimediawidgets/qgraphicsvideoitem_maemo6.cpp +++ /dev/null @@ -1,497 +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 "qgraphicsvideoitem.h" - -#include <QtCore/qcoreevent.h> -#include <QtCore/qpointer.h> -#include <QtCore/qbasictimer.h> - -#include <QtWidgets/qgraphicsscene.h> - -#include <qmediaobject.h> -#include <qmediaservice.h> -#include <qpaintervideosurface_p.h> -#include <qeglimagetexturesurface_p.h> -#include <qvideorenderercontrol.h> - -#include <qvideosurfaceformat.h> - -#include <X11/Xlib.h> - -#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1) -#include <QtOpenGL/qgl.h> -#endif - -//#define ENABLE_OVERLAY - -namespace -{ -//XInitThreads is necessary for gltexturesink element. -//To ensure it's called before main() it's better to link to -//libQtMultimedia.so directly, not when QML multimedia plugin is loaded. -class InitThreads -{ -public: - InitThreads() - { - XInitThreads(); - } -} _initThreads; -} - -Q_DECLARE_METATYPE(QVideoSurfaceFormat) - -QT_BEGIN_NAMESPACE - -class QGraphicsVideoItemPrivate -{ -public: - QGraphicsVideoItemPrivate() - : q_ptr(0) - , surface(0) - , mediaObject(0) - , service(0) - , rendererControl(0) - , aspectRatioMode(Qt::KeepAspectRatio) - , updatePaintDevice(true) - , rect(0.0, 0.0, 320, 240) - { - } - - QGraphicsVideoItem *q_ptr; - - QEglImageTextureSurface *surface; - QPointer<QMediaObject> mediaObject; - QMediaService *service; - QVideoRendererControl *rendererControl; - Qt::AspectRatioMode aspectRatioMode; - bool updatePaintDevice; - QRectF rect; - QRectF boundingRect; - QRectF sourceRect; - QSizeF nativeSize; - - void clearService(); - void updateRects(); - - void _q_present(); - void _q_formatChanged(const QVideoSurfaceFormat &format); - void _q_updateNativeSize(); - void _q_serviceDestroyed(); -}; - -void QGraphicsVideoItemPrivate::clearService() -{ - if (rendererControl) { - surface->stop(); - rendererControl->setSurface(0); - service->releaseControl(rendererControl); - rendererControl = 0; - } - if (service) { - QObject::disconnect(service, SIGNAL(destroyed()), q_ptr, SLOT(_q_serviceDestroyed())); - service = 0; - } -} - -void QGraphicsVideoItemPrivate::updateRects() -{ - q_ptr->prepareGeometryChange(); - - if (nativeSize.isEmpty()) { - //this is necessary for item to receive the - //first paint event and configure video surface. - boundingRect = rect; - } else if (aspectRatioMode == Qt::IgnoreAspectRatio) { - boundingRect = rect; - sourceRect = QRectF(0, 0, 1, 1); - } else if (aspectRatioMode == Qt::KeepAspectRatio) { - QSizeF size = nativeSize; - size.scale(rect.size(), Qt::KeepAspectRatio); - - boundingRect = QRectF(0, 0, size.width(), size.height()); - boundingRect.moveCenter(rect.center()); - - sourceRect = QRectF(0, 0, 1, 1); - } else if (aspectRatioMode == Qt::KeepAspectRatioByExpanding) { - boundingRect = rect; - - QSizeF size = rect.size(); - size.scale(nativeSize, Qt::KeepAspectRatio); - - sourceRect = QRectF( - 0, 0, size.width() / nativeSize.width(), size.height() / nativeSize.height()); - sourceRect.moveCenter(QPointF(0.5, 0.5)); - } -} - -void QGraphicsVideoItemPrivate::_q_present() -{ - if (q_ptr->isObscured()) { - q_ptr->update(boundingRect); - surface->setReady(true); - } else { - q_ptr->update(boundingRect); - } -} - -void QGraphicsVideoItemPrivate::_q_updateNativeSize() -{ - QSize size = surface->surfaceFormat().sizeHint(); - if (size.isEmpty()) - size = rendererControl->property("nativeSize").toSize(); - - if (nativeSize != size) { - nativeSize = size; - - updateRects(); - emit q_ptr->nativeSizeChanged(nativeSize); - } -} - -void QGraphicsVideoItemPrivate::_q_serviceDestroyed() -{ - rendererControl = 0; - service = 0; - - surface->stop(); -} - - -/* - \class QGraphicsVideoItem - - - \brief The QGraphicsVideoItem class provides a graphics item which display video produced by a QMediaObject. - - \inmodule QtMultimediaWidgets - \ingroup multimedia - - Attaching a QGraphicsVideoItem to a QMediaObject allows it to display - the video or image output of that media object. A QGraphicsVideoItem - is attached to a media object by passing a pointer to the QMediaObject - to the setMediaObject() function. - - \code - player = new QMediaPlayer(this); - - QGraphicsVideoItem *item = new QGraphicsVideoItem; - player->setVideoOutput(item); - graphicsView->scene()->addItem(item); - graphicsView->show(); - - player->setMedia(video); - player->play(); - \endcode - - \b {Note}: Only a single display output can be attached to a media - object at one time. - - \sa QMediaObject, QMediaPlayer, QVideoWidget -*/ - -/* - Constructs a graphics item that displays video. - - The \a parent is passed to QGraphicsItem. -*/ -QGraphicsVideoItem::QGraphicsVideoItem(QGraphicsItem *parent) - : QGraphicsObject(parent) - , d_ptr(new QGraphicsVideoItemPrivate) -{ - d_ptr->q_ptr = this; - d_ptr->surface = new QEglImageTextureSurface(this); - - qRegisterMetaType<QVideoSurfaceFormat>(); - - connect(d_ptr->surface, SIGNAL(frameChanged()), this, SLOT(_q_present())); - connect(d_ptr->surface, SIGNAL(surfaceFormatChanged(QVideoSurfaceFormat)), - this, SLOT(_q_updateNativeSize()), Qt::QueuedConnection); -} - -/* - Destroys a video graphics item. -*/ -QGraphicsVideoItem::~QGraphicsVideoItem() -{ - if (d_ptr->rendererControl) { - d_ptr->rendererControl->setSurface(0); - d_ptr->service->releaseControl(d_ptr->rendererControl); - } - - delete d_ptr->surface; - delete d_ptr; -} - -/* - \property QGraphicsVideoItem::mediaObject - \brief the media object which provides the video displayed by a graphics - item. -*/ - -QMediaObject *QGraphicsVideoItem::mediaObject() const -{ - return d_func()->mediaObject; -} - -/* - \internal -*/ -bool QGraphicsVideoItem::setMediaObject(QMediaObject *object) -{ - Q_D(QGraphicsVideoItem); - - if (object == d->mediaObject) - return true; - - d->clearService(); - - d->mediaObject = object; - - if (d->mediaObject) { - d->service = d->mediaObject->service(); - - if (d->service) { - QMediaControl *control = d->service->requestControl(QVideoRendererControl_iid); - if (control) { - d->rendererControl = qobject_cast<QVideoRendererControl *>(control); - - if (d->rendererControl) { - connect(d->rendererControl, SIGNAL(nativeSizeChanged()), - this, SLOT(_q_updateNativeSize()), Qt::QueuedConnection); - d->_q_updateNativeSize(); - //don't set the surface untill the item is painted - //at least once and the surface is configured - if (!d->updatePaintDevice) - d->rendererControl->setSurface(d->surface); - else - update(boundingRect()); - - connect(d->service, SIGNAL(destroyed()), this, SLOT(_q_serviceDestroyed())); - - return true; - } - if (control) - d->service->releaseControl(control); - } - } - } - - d->mediaObject = 0; - return false; -} - -/* - \property QGraphicsVideoItem::aspectRatioMode - \brief how a video is scaled to fit the graphics item's size. -*/ - -Qt::AspectRatioMode QGraphicsVideoItem::aspectRatioMode() const -{ - return d_func()->aspectRatioMode; -} - -void QGraphicsVideoItem::setAspectRatioMode(Qt::AspectRatioMode mode) -{ - Q_D(QGraphicsVideoItem); - - d->aspectRatioMode = mode; - d->updateRects(); -} - -/* - \property QGraphicsVideoItem::offset - \brief the video item's offset. - - QGraphicsVideoItem will draw video using the offset for its top left - corner. -*/ - -QPointF QGraphicsVideoItem::offset() const -{ - return d_func()->rect.topLeft(); -} - -void QGraphicsVideoItem::setOffset(const QPointF &offset) -{ - Q_D(QGraphicsVideoItem); - - d->rect.moveTo(offset); - d->updateRects(); -} - -/* - \property QGraphicsVideoItem::size - \brief the video item's size. - - QGraphicsVideoItem will draw video scaled to fit size according to its - fillMode. -*/ - -QSizeF QGraphicsVideoItem::size() const -{ - return d_func()->rect.size(); -} - -void QGraphicsVideoItem::setSize(const QSizeF &size) -{ - Q_D(QGraphicsVideoItem); - - d->rect.setSize(size.isValid() ? size : QSizeF(0, 0)); - d->updateRects(); -} - -/* - \property QGraphicsVideoItem::nativeSize - \brief the native size of the video. -*/ - -QSizeF QGraphicsVideoItem::nativeSize() const -{ - return d_func()->nativeSize; -} - -/* - \fn QGraphicsVideoItem::nativeSizeChanged(const QSizeF &size) - - Signals that the native \a size of the video has changed. -*/ - -/* - \reimp -*/ -QRectF QGraphicsVideoItem::boundingRect() const -{ - return d_func()->boundingRect; -} - -/* - \reimp -*/ -void QGraphicsVideoItem::paint( - QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) -{ - Q_D(QGraphicsVideoItem); - - Q_UNUSED(option); - Q_UNUSED(widget); - - if (d->surface && d->rendererControl && d->updatePaintDevice) { - d->updatePaintDevice = false; - - if (widget) - d->rendererControl->setProperty("winId", qulonglong(widget->winId())); - -#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1) - if (widget) - connect(widget, SIGNAL(destroyed()), d->surface, SLOT(viewportDestroyed())); - - d->surface->setGLContext(const_cast<QGLContext *>(QGLContext::currentContext())); -#endif - if (d->rendererControl->surface() != d->surface) - d->rendererControl->setSurface(d->surface); - } - - - //overlay doesn't work reliably - - //check if the item is obscured: -#ifdef ENABLE_OVERLAY - if (!isObscured()) { - bool obscured = false; - - if (scene()) { - const auto items = scene()->items(mapToScene(boundingRect()), Qt::IntersectsItemBoundingRect); - for (QGraphicsItem *item : items) { - if (item->flags() & QGraphicsItem::ItemHasNoContents) - continue; - - if (item == this) - break; - - if (collidesWithItem(item)) { - obscured = true; - break; - } - } - } - - d->rendererControl->setProperty("overlayEnabled", !obscured); - } - - if (d->rendererControl->property("overlayEnabled").toBool()) { - QTransform transform = painter->combinedTransform(); - QRect overlayRect = transform.mapRect(d->boundingRect).toRect(); - - d->rendererControl->setProperty("overlayGeometry", overlayRect); - QMetaObject::invokeMethod(d->rendererControl, "repaintOverlay"); - - painter->fillRect(d->boundingRect, - d->rendererControl->property("colorKey").value<QColor>()); - } else -#endif //ENABLE_OVERLAY - { - if (d->surface && d->surface->isActive()) { - d->surface->paint(painter, d->boundingRect, d->sourceRect); - d->surface->setReady(true); - } - } -} - -/* - \reimp - - \internal -*/ -QVariant QGraphicsVideoItem::itemChange(GraphicsItemChange change, const QVariant &value) -{ - return QGraphicsItem::itemChange(change, value); -} - -/* - \internal -*/ -void QGraphicsVideoItem::timerEvent(QTimerEvent *event) -{ - QGraphicsObject::timerEvent(event); -} - -#include "moc_qgraphicsvideoitem.cpp" -QT_END_NAMESPACE diff --git a/src/multimediawidgets/qpaintervideosurface.cpp b/src/multimediawidgets/qpaintervideosurface.cpp index 0d060dbce..9a6ad11ed 100644 --- a/src/multimediawidgets/qpaintervideosurface.cpp +++ b/src/multimediawidgets/qpaintervideosurface.cpp @@ -46,7 +46,7 @@ #include <qvideosurfaceformat.h> #include <private/qmediaopenglhelper_p.h> -#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1) +#if QT_CONFIG(opengl) #include <qglshaderprogram.h> #include <QtGui/QOpenGLContext> #include <QtGui/QOpenGLFunctions> @@ -222,7 +222,7 @@ void QVideoSurfaceGenericPainter::updateColors(int, int, int, int) { } -#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1) +#if QT_CONFIG(opengl) #ifndef APIENTRYP # ifdef APIENTRY @@ -1362,7 +1362,7 @@ QAbstractVideoSurface::Error QVideoSurfaceGlslPainter::paint( QPainterVideoSurface::QPainterVideoSurface(QObject *parent) : QAbstractVideoSurface(parent) , m_painter(0) -#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1) +#if QT_CONFIG(opengl) , m_glContext(0) , m_shaderTypes(NoShaders) , m_shaderType(NoShaders) @@ -1593,7 +1593,7 @@ void QPainterVideoSurface::paint(QPainter *painter, const QRectF &target, const \fn QPainterVideoSurface::frameChanged() */ -#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1) +#if QT_CONFIG(opengl) /*! */ @@ -1723,7 +1723,7 @@ void QPainterVideoSurface::createPainter() { Q_ASSERT(!m_painter); -#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1) +#if QT_CONFIG(opengl) switch (m_shaderType) { #if !defined(QT_OPENGL_ES) && !defined(QT_OPENGL_DYNAMIC) case FragmentProgramShader: diff --git a/src/multimediawidgets/qpaintervideosurface_p.h b/src/multimediawidgets/qpaintervideosurface_p.h index a254947d2..2e89393e9 100644 --- a/src/multimediawidgets/qpaintervideosurface_p.h +++ b/src/multimediawidgets/qpaintervideosurface_p.h @@ -125,7 +125,7 @@ public: void paint(QPainter *painter, const QRectF &target, const QRectF &source = QRectF(0, 0, 1, 1)); -#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1) +#if QT_CONFIG(opengl) const QGLContext *glContext() const; void setGLContext(QGLContext *context); @@ -154,7 +154,7 @@ private: void createPainter(); QVideoSurfacePainter *m_painter; -#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1) +#if QT_CONFIG(opengl) QGLContext *m_glContext; ShaderTypes m_shaderTypes; ShaderType m_shaderType; @@ -171,7 +171,7 @@ private: bool m_ready; }; -#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1) +#if QT_CONFIG(opengl) Q_DECLARE_OPERATORS_FOR_FLAGS(QPainterVideoSurface::ShaderTypes) #endif diff --git a/src/multimediawidgets/qvideowidget.cpp b/src/multimediawidgets/qvideowidget.cpp index 828ec2e22..3d5e5c830 100644 --- a/src/multimediawidgets/qvideowidget.cpp +++ b/src/multimediawidgets/qvideowidget.cpp @@ -210,7 +210,7 @@ void QRendererVideoWidgetBackend::showEvent() void QRendererVideoWidgetBackend::hideEvent(QHideEvent *) { -#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1) +#if QT_CONFIG(opengl) m_updatePaintDevice = true; m_surface->setGLContext(0); #endif @@ -246,7 +246,7 @@ void QRendererVideoWidgetBackend::paintEvent(QPaintEvent *event) m_surface->setReady(true); } else { - #if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1) +#if QT_CONFIG(opengl) if (m_updatePaintDevice && (painter.paintEngine()->type() == QPaintEngine::OpenGL || painter.paintEngine()->type() == QPaintEngine::OpenGL2)) { m_updatePaintDevice = false; 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/qalsaaudioinput.cpp b/src/plugins/alsa/qalsaaudioinput.cpp index 8109e6932..5a4111a90 100644 --- a/src/plugins/alsa/qalsaaudioinput.cpp +++ b/src/plugins/alsa/qalsaaudioinput.cpp @@ -49,6 +49,7 @@ // #include <QtCore/qcoreapplication.h> +#include <QtCore/qvarlengtharray.h> #include <QtMultimedia/private/qaudiohelpers_p.h> #include "qalsaaudioinput.h" #include "qalsaaudiodeviceinfo.h" @@ -526,20 +527,22 @@ qint64 QAlsaAudioInput::read(char* data, qint64 len) int count=0; int err = 0; + QVarLengthArray<char, 4096> buffer(bytesToRead); while(count < 5 && bytesToRead > 0) { - char buffer[bytesToRead]; int chunks = bytesToRead / period_size; int frames = chunks * period_frames; if (frames > (int)buffer_frames) frames = buffer_frames; - int readFrames = snd_pcm_readi(handle, buffer, frames); + int readFrames = snd_pcm_readi(handle, buffer.data(), frames); bytesRead = snd_pcm_frames_to_bytes(handle, readFrames); if (m_volume < 1.0f) - QAudioHelperInternal::qMultiplySamples(m_volume, settings, buffer, buffer, bytesRead); + QAudioHelperInternal::qMultiplySamples(m_volume, settings, + buffer.constData(), + buffer.data(), bytesRead); if (readFrames >= 0) { - ringBuffer.write(buffer, bytesRead); + ringBuffer.write(buffer.data(), bytesRead); #ifdef DEBUG_AUDIO qDebug() << QString::fromLatin1("read in bytes = %1 (frames=%2)").arg(bytesRead).arg(readFrames).toLatin1().constData(); #endif diff --git a/src/plugins/alsa/qalsaaudiooutput.cpp b/src/plugins/alsa/qalsaaudiooutput.cpp index 5e444a0a9..cd97ae85b 100644 --- a/src/plugins/alsa/qalsaaudiooutput.cpp +++ b/src/plugins/alsa/qalsaaudiooutput.cpp @@ -49,6 +49,7 @@ // #include <QtCore/qcoreapplication.h> +#include <QtCore/qvarlengtharray.h> #include <QtMultimedia/private/qaudiohelpers_p.h> #include "qalsaaudiooutput.h" #include "qalsaaudiodeviceinfo.h" @@ -567,9 +568,9 @@ qint64 QAlsaAudioOutput::write( const char *data, qint64 len ) frames = snd_pcm_bytes_to_frames(handle, space); if (m_volume < 1.0f) { - char out[space]; - QAudioHelperInternal::qMultiplySamples(m_volume, settings, data, out, space); - err = snd_pcm_writei(handle, out, frames); + QVarLengthArray<char, 4096> out(space); + QAudioHelperInternal::qMultiplySamples(m_volume, settings, data, out.data(), space); + err = snd_pcm_writei(handle, out.constData(), frames); } else { err = snd_pcm_writei(handle, data, frames); } 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 2a66fa2c4..7fb4a8690 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 @@ -448,17 +448,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) @@ -486,7 +475,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/audiocapture/audiocapturesession.cpp b/src/plugins/audiocapture/audiocapturesession.cpp index e4a9688e8..7ed3313d8 100644 --- a/src/plugins/audiocapture/audiocapturesession.cpp +++ b/src/plugins/audiocapture/audiocapturesession.cpp @@ -206,10 +206,6 @@ QDir AudioCaptureSession::defaultDir() const { QStringList dirCandidates; -#if defined(Q_WS_MAEMO_6) - dirCandidates << QLatin1String("/home/user/MyDocs"); -#endif - dirCandidates << QDir::home().filePath("Documents"); dirCandidates << QDir::home().filePath("My Documents"); dirCandidates << QDir::homePath(); diff --git a/src/plugins/avfoundation/camera/avfcameradebug.h b/src/plugins/avfoundation/camera/avfcameradebug.h index 79bf8eb0e..8838122e0 100644 --- a/src/plugins/avfoundation/camera/avfcameradebug.h +++ b/src/plugins/avfoundation/camera/avfcameradebug.h @@ -40,7 +40,7 @@ #ifndef AVFDEBUG_H #define AVFDEBUG_H -#include "qtmultimediadefs.h" +#include "qtmultimediaglobal.h" #include <QtCore/qdebug.h> 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/camera/avfstoragelocation.h b/src/plugins/avfoundation/camera/avfstoragelocation.h index e3267c1e7..76621983d 100644 --- a/src/plugins/avfoundation/camera/avfstoragelocation.h +++ b/src/plugins/avfoundation/camera/avfstoragelocation.h @@ -40,7 +40,7 @@ #ifndef AVFSTORAGE_H #define AVFSTORAGE_H -#include "qtmultimediadefs.h" +#include "qtmultimediaglobal.h" #include <QtCore/qdir.h> #include <QtMultimedia/qcamera.h> diff --git a/src/plugins/avfoundation/camera/camera.pro b/src/plugins/avfoundation/camera/camera.pro index a17ff5a73..ab70c25c3 100644 --- a/src/plugins/avfoundation/camera/camera.pro +++ b/src/plugins/avfoundation/camera/camera.pro @@ -8,12 +8,13 @@ QT += multimedia-private network LIBS += -framework AudioToolbox \ -framework CoreAudio \ -framework QuartzCore \ - -framework AVFoundation \ -framework CoreMedia osx:LIBS += -framework AppKit \ -framework AudioUnit ios:LIBS += -framework CoreVideo +QMAKE_USE += avfoundation + OTHER_FILES += avfcamera.json DEFINES += QMEDIA_AVF_CAMERA diff --git a/src/plugins/avfoundation/mediaplayer/mediaplayer.pro b/src/plugins/avfoundation/mediaplayer/mediaplayer.pro index 779d5ff2d..f9a086b33 100644 --- a/src/plugins/avfoundation/mediaplayer/mediaplayer.pro +++ b/src/plugins/avfoundation/mediaplayer/mediaplayer.pro @@ -6,7 +6,9 @@ CONFIG += no_keywords QT += multimedia-private network -LIBS += -framework AVFoundation -framework CoreMedia -framework CoreVideo -framework QuartzCore +LIBS += -framework CoreMedia -framework CoreVideo -framework QuartzCore + +QMAKE_USE += avfoundation DEFINES += QMEDIA_AVF_MEDIAPLAYER @@ -40,7 +42,7 @@ OBJECTIVE_SOURCES += \ } ios|tvos { - contains(QT_CONFIG, opengl.*) { + qtConfig(opengl) { HEADERS += \ avfvideoframerenderer_ios.h \ avfvideorenderercontrol.h \ @@ -55,7 +57,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..fb7fbd3f5 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 @@ -28,4 +28,4 @@ SOURCES += \ $$PWD/dscameraimageprocessingcontrol.cpp *-msvc*:INCLUDEPATH += $$(DXSDK_DIR)/include -LIBS += -lstrmiids -ldmoguids -luuid -lmsdmo -lole32 -loleaut32 +QMAKE_USE += directshow 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 182f232c0..5eb4fbc96 100644 --- a/src/plugins/directshow/directshow.pro +++ b/src/plugins/directshow/directshow.pro @@ -1,19 +1,20 @@ TARGET = dsengine -win32:!qtHaveModule(opengl)|contains(QT_CONFIG,dynamicgl) { +QT += multimedia-private + +win32:!qtHaveModule(opengl)|qtConfig(dynamicgl) { LIBS_PRIVATE += -lgdi32 -luser32 } -QT += multimedia-private - HEADERS += dsserviceplugin.h SOURCES += dsserviceplugin.cpp -!config_wmsdk: DEFINES += QT_NO_WMSDK +!qtConfig(wmsdk): DEFINES += QT_NO_WMSDK mingw: DEFINES += NO_DSHOW_STRSAFE -!config_wmf|!contains(QT_CONFIG, wmf-backend): include(player/player.pri) -!wince: include(camera/camera.pri) +include(helpers/helpers.pri) +!qtConfig(wmf-backend): include(player/player.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/qnx/mediaplayer/bpsmediaplayercontrol.h b/src/plugins/directshow/helpers/directshowobject.cpp index d9789d689..b9d989f6e 100644 --- a/src/plugins/qnx/mediaplayer/bpsmediaplayercontrol.h +++ b/src/plugins/directshow/helpers/directshowobject.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 Research In Motion +** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Toolkit. @@ -36,29 +36,48 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ -#ifndef BPSMEDIAPLAYERCONTROL_H -#define BPSMEDIAPLAYERCONTROL_H -#include "mmrenderermediaplayercontrol.h" +#include "directshowobject.h" -QT_BEGIN_NAMESPACE +DirectShowObject::DirectShowObject() + : m_ref(1) +{ +} + +DirectShowObject::~DirectShowObject() +{ + Q_ASSERT(m_ref == 0); +} + +HRESULT DirectShowObject::getInterface(const IID &riid, void **ppvObject) +{ + Q_UNUSED(riid) + *ppvObject = NULL; + return E_NOINTERFACE; +} + +ULONG DirectShowObject::ref() +{ + return InterlockedIncrement(&m_ref); +} -class BpsMediaPlayerControl Q_DECL_FINAL : public MmRendererMediaPlayerControl +ULONG DirectShowObject::unref() { - Q_OBJECT -public: - explicit BpsMediaPlayerControl(QObject *parent = 0); - ~BpsMediaPlayerControl(); + ULONG ref = InterlockedDecrement(&m_ref); + if (ref == 0) + delete this; - void startMonitoring(int contextId, const QString &contextName) Q_DECL_OVERRIDE; - void stopMonitoring() Q_DECL_OVERRIDE; + return ref; +} - bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) Q_DECL_OVERRIDE; +HRESULT GetInterface(IUnknown *pUnk, void **ppv) +{ + if (!ppv) + return E_POINTER; -private: - mmrenderer_monitor_t *m_eventMonitor; -}; + *ppv = pUnk; + pUnk->AddRef(); -QT_END_NAMESPACE + 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(¤tTime) == 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..7391ec7f0 100644 --- a/src/plugins/directshow/player/player.pri +++ b/src/plugins/directshow/player/player.pri @@ -1,55 +1,35 @@ INCLUDEPATH += $$PWD -LIBS += -lstrmiids -ldmoguids -luuid -lole32 -loleaut32 -!wince: LIBS += -lmsdmo -lgdi32 - +QMAKE_USE += directshow +LIBS += -lgdi32 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 { +qtConfig(evr) { DEFINES += HAVE_EVR include($$PWD/../../common/evr.pri) @@ -61,7 +41,7 @@ config_evr { $$PWD/directshowevrvideowindowcontrol.cpp } -config_wshellitem { +qtConfig(wshellitem) { QT += core-private } else { DEFINES += QT_NO_SHELLITEM 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(¤tTime); + 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/camerabin/camerabin.pro b/src/plugins/gstreamer/camerabin/camerabin.pro index 214489f3e..d214d61c6 100644 --- a/src/plugins/gstreamer/camerabin/camerabin.pro +++ b/src/plugins/gstreamer/camerabin/camerabin.pro @@ -52,17 +52,7 @@ SOURCES += \ $$PWD/camerabincapturebufferformat.cpp \ $$PWD/camerabininfocontrol.cpp -maemo6 { - HEADERS += \ - $$PWD/camerabuttonlistener_meego.h - - SOURCES += \ - $$PWD/camerabuttonlistener_meego.cpp - - CONFIG += have_gst_photography -} - -config_gstreamer_photography { +qtConfig(gstreamer_photography) { DEFINES += HAVE_GST_PHOTOGRAPHY HEADERS += \ @@ -77,15 +67,15 @@ config_gstreamer_photography { $$PWD/camerabinfocus.cpp \ $$PWD/camerabinlocks.cpp - LIBS += -lgstphotography-$$GST_VERSION + QMAKE_USE += gstreamer_photography DEFINES += GST_USE_UNSTABLE_API #prevents warnings because of unstable photography API } -config_gstreamer_encodingprofiles { +qtConfig(gstreamer_encodingprofiles) { DEFINES += HAVE_GST_ENCODING_PROFILES } -config_linux_v4l: { +qtConfig(linux_v4l) { DEFINES += USE_V4L HEADERS += \ diff --git a/src/plugins/gstreamer/camerabin/camerabincapturebufferformat.cpp b/src/plugins/gstreamer/camerabin/camerabincapturebufferformat.cpp index d4570b8b1..8b3e10546 100644 --- a/src/plugins/gstreamer/camerabin/camerabincapturebufferformat.cpp +++ b/src/plugins/gstreamer/camerabin/camerabincapturebufferformat.cpp @@ -57,11 +57,7 @@ QList<QVideoFrame::PixelFormat> CameraBinCaptureBufferFormat::supportedBufferFor { //the exact YUV format is unknown with camerabin until the first capture is requested return QList<QVideoFrame::PixelFormat>() - << QVideoFrame::Format_Jpeg -#ifdef Q_WS_MAEMO_6 - << QVideoFrame::Format_UYVY -#endif - ; + << QVideoFrame::Format_Jpeg; } QVideoFrame::PixelFormat CameraBinCaptureBufferFormat::bufferFormat() const diff --git a/src/plugins/gstreamer/camerabin/camerabinexposure.h b/src/plugins/gstreamer/camerabin/camerabinexposure.h index a7de86627..0435569d4 100644 --- a/src/plugins/gstreamer/camerabin/camerabinexposure.h +++ b/src/plugins/gstreamer/camerabin/camerabinexposure.h @@ -37,8 +37,8 @@ ** ****************************************************************************/ -#ifndef CAMERABINEXPOSURECONTROL_MAEMO_H -#define CAMERABINEXPOSURECONTROL_MAEMO_H +#ifndef CAMERABINEXPOSURECONTROL_H +#define CAMERABINEXPOSURECONTROL_H #include <qcamera.h> #include <qcameraexposurecontrol.h> @@ -72,4 +72,4 @@ private: QT_END_NAMESPACE -#endif // CAMERABINEXPOSURECONTROL_MAEMO_H +#endif // CAMERABINEXPOSURECONTROL_H diff --git a/src/plugins/gstreamer/camerabin/camerabinservice.cpp b/src/plugins/gstreamer/camerabin/camerabinservice.cpp index d9131e545..3fbd1a60e 100644 --- a/src/plugins/gstreamer/camerabin/camerabinservice.cpp +++ b/src/plugins/gstreamer/camerabin/camerabinservice.cpp @@ -73,20 +73,11 @@ #endif #include <private/qgstreamervideowindow_p.h> #include <private/qgstreamervideorenderer_p.h> - -#if defined(Q_WS_MAEMO_6) && defined(__arm__) -#include "qgstreamergltexturerenderer.h" -#endif - #include <private/qmediaserviceprovider_p.h> #include <QtCore/qdebug.h> #include <QtCore/qprocess.h> -#if defined(Q_WS_MAEMO_6) -#include "camerabuttonlistener_meego.h" -#endif - QT_BEGIN_NAMESPACE CameraBinService::CameraBinService(GstElementFactory *sourceFactory, QObject *parent): @@ -119,17 +110,9 @@ CameraBinService::CameraBinService(GstElementFactory *sourceFactory, QObject *pa if (m_videoInputDevice->deviceCount()) m_captureSession->setDevice(m_videoInputDevice->deviceName(m_videoInputDevice->selectedDevice())); -#if defined(Q_WS_MAEMO_6) && defined(__arm__) && defined(HAVE_WIDGETS) - m_videoRenderer = new QGstreamerGLTextureRenderer(this); -#else m_videoRenderer = new QGstreamerVideoRenderer(this); -#endif -#ifdef Q_WS_MAEMO_6 - m_videoWindow = new QGstreamerVideoWindow(this, "omapxvsink"); -#else m_videoWindow = new QGstreamerVideoWindow(this); -#endif // If the GStreamer video sink is not available, don't provide the video window control since // it won't work anyway. if (!m_videoWindow->videoSink()) { @@ -156,10 +139,6 @@ CameraBinService::CameraBinService(GstElementFactory *sourceFactory, QObject *pa m_metaDataControl = new CameraBinMetaData(this); connect(m_metaDataControl, SIGNAL(metaDataChanged(QMap<QByteArray,QVariant>)), m_captureSession, SLOT(setMetaData(QMap<QByteArray,QVariant>))); - -#if defined(Q_WS_MAEMO_6) - new CameraButtonListener(this); -#endif } CameraBinService::~CameraBinService() @@ -189,6 +168,9 @@ QMediaControl *CameraBinService::requestControl(const char *name) } } + if (qstrcmp(name, QMediaVideoProbeControl_iid) == 0) + return m_captureSession->videoProbe(); + if (qstrcmp(name,QAudioInputSelectorControl_iid) == 0) return m_audioInputSelector; diff --git a/src/plugins/gstreamer/camerabin/camerabinsession.cpp b/src/plugins/gstreamer/camerabin/camerabinsession.cpp index 3cb4c6161..64c8780d3 100644 --- a/src/plugins/gstreamer/camerabin/camerabinsession.cpp +++ b/src/plugins/gstreamer/camerabin/camerabinsession.cpp @@ -674,6 +674,8 @@ QCameraViewfinderSettings CameraBinSession::viewfinderSettings() const void CameraBinSession::ViewfinderProbe::probeCaps(GstCaps *caps) { + QGstreamerVideoProbeControl::probeCaps(caps); + // Update actual viewfinder settings on viewfinder caps change const GstStructure *s = gst_caps_get_structure(caps, 0); const QPair<qreal, qreal> frameRate = QGstUtils::structureFrameRateRange(s); @@ -1074,6 +1076,11 @@ bool CameraBinSession::processBusMessage(const QGstreamerMessage &message) return false; } +QGstreamerVideoProbeControl *CameraBinSession::videoProbe() +{ + return &m_viewfinderProbe; +} + QString CameraBinSession::currentContainerFormat() const { if (!m_muxer) diff --git a/src/plugins/gstreamer/camerabin/camerabinsession.h b/src/plugins/gstreamer/camerabin/camerabinsession.h index 44faaf701..ca0b22761 100644 --- a/src/plugins/gstreamer/camerabin/camerabinsession.h +++ b/src/plugins/gstreamer/camerabin/camerabinsession.h @@ -37,8 +37,8 @@ ** ****************************************************************************/ -#ifndef CAMERABINCAPTURESESSION_MAEMO_H -#define CAMERABINCAPTURESESSION_MAEMO_H +#ifndef CAMERABINCAPTURESESSION_H +#define CAMERABINCAPTURESESSION_H #include <qmediarecordercontrol.h> @@ -51,7 +51,7 @@ #endif #include <private/qgstreamerbushelper_p.h> -#include <private/qgstreamerbufferprobe_p.h> +#include <private/qgstreamervideoprobecontrol_p.h> #include <private/qmediastoragelocation_p.h> #include "qcamera.h" @@ -164,6 +164,8 @@ public: bool processSyncMessage(const QGstreamerMessage &message); bool processBusMessage(const QGstreamerMessage &message); + QGstreamerVideoProbeControl *videoProbe(); + signals: void statusChanged(QCamera::Status status); void pendingStateChanged(QCamera::State state); @@ -258,14 +260,14 @@ private: bool m_inputDeviceHasChanged; bool m_usingWrapperCameraBinSrc; - class ViewfinderProbe : public QGstreamerBufferProbe { + class ViewfinderProbe : public QGstreamerVideoProbeControl { public: ViewfinderProbe(CameraBinSession *s) - : QGstreamerBufferProbe(QGstreamerBufferProbe::ProbeCaps) + : QGstreamerVideoProbeControl(s) , session(s) {} - void probeCaps(GstCaps *caps); + void probeCaps(GstCaps *caps) override; private: CameraBinSession * const session; @@ -286,4 +288,4 @@ public: QT_END_NAMESPACE -#endif // CAMERABINCAPTURESESSION_MAEMO_H +#endif // CAMERABINCAPTURESESSION_H diff --git a/src/plugins/gstreamer/camerabin/camerabuttonlistener_meego.cpp b/src/plugins/gstreamer/camerabin/camerabuttonlistener_meego.cpp deleted file mode 100644 index 0516f338b..000000000 --- a/src/plugins/gstreamer/camerabin/camerabuttonlistener_meego.cpp +++ /dev/null @@ -1,94 +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 "camerabuttonlistener_meego.h" - -#include <QtWidgets/qapplication.h> -#include <QtGui/qevent.h> -#include <QtWidgets/qwidget.h> -#include <QtCore/qdebug.h> - -QT_BEGIN_NAMESPACE - -CameraButtonListener::CameraButtonListener(QObject *parent) : - QObject(parent), - m_focusPressed(false), - m_shutterPressed(false) -{ - m_keys = new MeeGo::QmKeys(this); - connect(m_keys, SIGNAL(keyEvent(MeeGo::QmKeys::Key,MeeGo::QmKeys::State)), - this, SLOT(handleQmKeyEvent(MeeGo::QmKeys::Key,MeeGo::QmKeys::State))); -} - -CameraButtonListener::~CameraButtonListener() -{ -} - -void CameraButtonListener::handleQmKeyEvent(MeeGo::QmKeys::Key key, MeeGo::QmKeys::State state) -{ - if (key == MeeGo::QmKeys::Camera) { - QWidget *window = QApplication::focusWidget(); - - bool focusPressed = (state == MeeGo::QmKeys::KeyHalfDown) || - (state == MeeGo::QmKeys::KeyDown); - - if (m_focusPressed != focusPressed) { - m_focusPressed = focusPressed; - if (window) { - QApplication::postEvent(window, - new QKeyEvent(focusPressed ? QEvent::KeyPress : QEvent::KeyRelease, - Qt::Key_CameraFocus, - Qt::NoModifier)); - } - } - - bool shutterPressed = (state == MeeGo::QmKeys::KeyDown); - if (m_shutterPressed != shutterPressed) { - m_shutterPressed = shutterPressed; - if (window) { - QApplication::postEvent(window, - new QKeyEvent(shutterPressed ? QEvent::KeyPress : QEvent::KeyRelease, - Qt::Key_Camera, - Qt::NoModifier)); - } - } - } -} - -QT_END_NAMESPACE diff --git a/src/plugins/gstreamer/common.pri b/src/plugins/gstreamer/common.pri index babdb7cfb..110bc8549 100644 --- a/src/plugins/gstreamer/common.pri +++ b/src/plugins/gstreamer/common.pri @@ -1,4 +1,3 @@ - QT += core-private multimedia-private network qtHaveModule(widgets) { @@ -8,30 +7,15 @@ qtHaveModule(widgets) { LIBS += -lqgsttools_p -CONFIG += link_pkgconfig - -PKGCONFIG += \ - gstreamer-$$GST_VERSION \ - gstreamer-base-$$GST_VERSION \ - gstreamer-audio-$$GST_VERSION \ - gstreamer-video-$$GST_VERSION \ - gstreamer-pbutils-$$GST_VERSION - -maemo*:PKGCONFIG +=gstreamer-plugins-bad-$$GST_VERSION - -mir: { - DEFINES += HAVE_MIR -} - +QMAKE_USE += gstreamer -config_resourcepolicy { +qtConfig(resourcepolicy) { + QMAKE_USE += libresourceqt5 DEFINES += HAVE_RESOURCE_POLICY - PKGCONFIG += libresourceqt5 } -config_gstreamer_appsrc { - PKGCONFIG += gstreamer-app-$$GST_VERSION +qtConfig(gstreamer_app) { + QMAKE_USE += gstreamer_app DEFINES += HAVE_GST_APPSRC - LIBS += -lgstapp-$$GST_VERSION } diff --git a/src/plugins/gstreamer/mediacapture/mediacapture.pro b/src/plugins/gstreamer/mediacapture/mediacapture.pro index db5210d4d..17248a495 100644 --- a/src/plugins/gstreamer/mediacapture/mediacapture.pro +++ b/src/plugins/gstreamer/mediacapture/mediacapture.pro @@ -31,7 +31,7 @@ SOURCES += $$PWD/qgstreamercaptureservice.cpp \ # Camera usage with gstreamer needs to have #CONFIG += use_gstreamer_camera -use_gstreamer_camera:config_linux_v4l { +use_gstreamer_camera:qtConfig(linux_v4l) { DEFINES += USE_GSTREAMER_CAMERA OTHER_FILES += \ diff --git a/src/plugins/gstreamer/mediacapture/qgstreameraudioencode.cpp b/src/plugins/gstreamer/mediacapture/qgstreameraudioencode.cpp index 5f45567cc..abb58c963 100644 --- a/src/plugins/gstreamer/mediacapture/qgstreameraudioencode.cpp +++ b/src/plugins/gstreamer/mediacapture/qgstreameraudioencode.cpp @@ -51,23 +51,12 @@ QGstreamerAudioEncode::QGstreamerAudioEncode(QObject *parent) { QList<QByteArray> codecCandidates; -#if defined(Q_WS_MAEMO_6) - codecCandidates << "audio/AAC" << "audio/mpeg" << "audio/vorbis" << "audio/speex" << "audio/GSM" - << "audio/PCM" << "audio/AMR" << "audio/AMR-WB" << "audio/FLAC"; -#else codecCandidates << "audio/mpeg" << "audio/vorbis" << "audio/speex" << "audio/GSM" << "audio/PCM" << "audio/AMR" << "audio/AMR-WB" << "audio/FLAC"; -#endif -#if defined(Q_WS_MAEMO_6) - m_elementNames["audio/AMR"] = "nokiaamrnbenc"; - m_elementNames["audio/AMR-WB"] = "nokiaamrwbenc"; - m_elementNames["audio/AAC"] = "nokiaaacenc"; -#else m_elementNames["audio/mpeg"] = "lamemp3enc"; m_elementNames["audio/AMR"] = "amrnbenc"; m_elementNames["audio/AMR-WB"] = "amrwbenc"; -#endif m_elementNames["audio/vorbis"] = "vorbisenc"; m_elementNames["audio/speex"] = "speexenc"; diff --git a/src/plugins/gstreamer/mediacapture/qgstreamerrecordercontrol.cpp b/src/plugins/gstreamer/mediacapture/qgstreamerrecordercontrol.cpp index 7b216b63b..958204803 100644 --- a/src/plugins/gstreamer/mediacapture/qgstreamerrecordercontrol.cpp +++ b/src/plugins/gstreamer/mediacapture/qgstreamerrecordercontrol.cpp @@ -330,10 +330,6 @@ QDir QGstreamerRecorderControl::defaultDir() const { QStringList dirCandidates; -#if defined(Q_WS_MAEMO_6) - dirCandidates << QLatin1String("/home/user/MyDocs"); -#endif - if (m_session->captureMode() & QGstreamerCaptureSession::Video) dirCandidates << QStandardPaths::writableLocation(QStandardPaths::MoviesLocation); else 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/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp b/src/plugins/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp index 9ecd9b79c..3e7286e51 100644 --- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp +++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp @@ -239,14 +239,6 @@ void QGstreamerPlayerControl::playOrPause(QMediaPlayer::State newState) setMedia(m_currentResource, m_stream); } -#ifdef Q_WS_MAEMO_6 - //this is a work around for the gstreamer bug, - //should be remove once it get fixed - if (newState == QMediaPlayer::PlayingState && m_mediaStatus == QMediaPlayer::InvalidMedia) { - setMedia(m_currentResource, m_stream); - } -#endif - if (m_mediaStatus == QMediaPlayer::EndOfMedia && m_pendingSeekPosition == -1) { m_pendingSeekPosition = 0; } diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayerservice.cpp b/src/plugins/gstreamer/mediaplayer/qgstreamerplayerservice.cpp index f233a487f..2c2de1bbc 100644 --- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayerservice.cpp +++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayerservice.cpp @@ -37,6 +37,7 @@ ** ****************************************************************************/ +#include <QtMultimedia/private/qtmultimediaglobal_p.h> #include <QtCore/qvariant.h> #include <QtCore/qdebug.h> @@ -56,11 +57,7 @@ #include <private/qgstreamervideowindow_p.h> #include <private/qgstreamervideorenderer_p.h> -#if defined(Q_WS_MAEMO_6) && defined(__arm__) -#include "private/qgstreamergltexturerenderer.h" -#endif - -#if defined(HAVE_MIR) && defined (__arm__) +#if QT_CONFIG(mirclient) && defined (__arm__) #include "private/qgstreamermirtexturerenderer_p.h" #endif @@ -92,20 +89,14 @@ QGstreamerPlayerService::QGstreamerPlayerService(QObject *parent): m_streamsControl = new QGstreamerStreamsControl(m_session,this); m_availabilityControl = new QGStreamerAvailabilityControl(m_control->resources(), this); -#if defined(Q_WS_MAEMO_6) && defined(__arm__) - m_videoRenderer = new QGstreamerGLTextureRenderer(this); -#elif defined(HAVE_MIR) && defined (__arm__) +#if QT_CONFIG(mirclient) && defined (__arm__) m_videoRenderer = new QGstreamerMirTextureRenderer(this, m_session); #else m_videoRenderer = new QGstreamerVideoRenderer(this); #endif -#ifdef Q_WS_MAEMO_6 - m_videoWindow = new QGstreamerVideoWindow(this, "omapxvsink"); -#else m_videoWindow = new QGstreamerVideoWindow(this); -#endif - // If the GStreamer video sink is not available, don't provide the video window control since + // If the GStreamer video sink is not available, don't provide the video window control since // it won't work anyway. if (!m_videoWindow->videoSink()) { delete m_videoWindow; diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp b/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp index ed07e4054..09b74148e 100644 --- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp +++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp @@ -155,10 +155,6 @@ QGstreamerPlayerSession::QGstreamerPlayerSession(QObject *parent) if (m_playbin) { //GST_PLAY_FLAG_NATIVE_VIDEO omits configuration of ffmpegcolorspace and videoscale, //since those elements are included in the video output bin when necessary. -#ifdef Q_WS_MAEMO_6 - int flags = GST_PLAY_FLAG_VIDEO | GST_PLAY_FLAG_AUDIO | - GST_PLAY_FLAG_NATIVE_VIDEO | GST_PLAY_FLAG_NATIVE_AUDIO; -#else int flags = GST_PLAY_FLAG_VIDEO | GST_PLAY_FLAG_AUDIO; QByteArray envFlags = qgetenv("QT_GSTREAMER_PLAYBIN_FLAGS"); if (!envFlags.isEmpty()) { @@ -168,7 +164,6 @@ QGstreamerPlayerSession::QGstreamerPlayerSession(QObject *parent) flags |= GST_PLAY_FLAG_NATIVE_VIDEO; #endif } -#endif g_object_set(G_OBJECT(m_playbin), "flags", flags, NULL); GstElement *audioSink = gst_element_factory_make("autoaudiosink", "audiosink"); 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..099e472da 100644 --- a/src/plugins/plugins.pro +++ b/src/plugins/plugins.pro @@ -5,6 +5,7 @@ ###################################################################### TEMPLATE = subdirs +QT_FOR_CONFIG += multimedia-private SUBDIRS += m3u @@ -17,50 +18,53 @@ android { } qnx { - config_mmrenderer: SUBDIRS += qnx + qtConfig(mmrenderer): SUBDIRS += qnx SUBDIRS += audiocapture } -qnx:!blackberry { +qnx { SUBDIRS += qnx-audio } -win32:!winrt:!wince { +win32 { + qtConfig(wasapi): SUBDIRS += wasapi +} + +win32:!winrt { SUBDIRS += audiocapture \ windowsaudio - config_directshow: SUBDIRS += directshow - config_wmf: SUBDIRS += wmf + qtConfig(directshow): SUBDIRS += directshow + qtConfig(wmf-backend): SUBDIRS += wmf } + winrt { - SUBDIRS += wasapi \ - winrt + SUBDIRS += winrt } unix:!mac:!android { - config_gstreamer { + qtConfig(gstreamer) { SUBDIRS += gstreamer } else { SUBDIRS += audiocapture } - config_pulseaudio: SUBDIRS += pulseaudio - config_alsa: SUBDIRS += alsa + qtConfig(pulseaudio): SUBDIRS += pulseaudio + qtConfig(alsa): SUBDIRS += alsa # v4l is turned off because it is not supported in Qt 5 - # config_linux_v4l { - # !maemo*:SUBDIRS += v4l + # qtConfig(linux_v4l) { + # SUBDIRS += v4l # } } -mac:!simulator { +darwin:!watchos { SUBDIRS += audiocapture coreaudio - - config_avfoundation: SUBDIRS += avfoundation + qtConfig(avfoundation): SUBDIRS += avfoundation } -config_resourcepolicy { +qtConfig(resourcepolicy) { SUBDIRS += resourcepolicy } diff --git a/src/plugins/pulseaudio/pulseaudio.pro b/src/plugins/pulseaudio/pulseaudio.pro index 7f4d3de22..c6339e9e8 100644 --- a/src/plugins/pulseaudio/pulseaudio.pro +++ b/src/plugins/pulseaudio/pulseaudio.pro @@ -1,8 +1,7 @@ TARGET = qtmedia_pulse QT += multimedia-private -CONFIG += link_pkgconfig -PKGCONFIG += libpulse +QMAKE_USE += pulseaudio HEADERS += qpulseaudioplugin.h \ qaudiodeviceinfo_pulse.h \ diff --git a/src/plugins/pulseaudio/qpulseaudioengine.cpp b/src/plugins/pulseaudio/qpulseaudioengine.cpp index 41aba378a..67ad10af1 100644 --- a/src/plugins/pulseaudio/qpulseaudioengine.cpp +++ b/src/plugins/pulseaudio/qpulseaudioengine.cpp @@ -474,4 +474,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/qnx/bbserviceplugin.cpp b/src/plugins/qnx/bbserviceplugin.cpp deleted file mode 100644 index e83d1caa3..000000000 --- a/src/plugins/qnx/bbserviceplugin.cpp +++ /dev/null @@ -1,139 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Research In Motion -** 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 "bbserviceplugin.h" - -#include "bbcamerainfocontrol.h" -#include "bbcameraservice.h" -#include "bbcamerasession.h" -#include "bbvideodeviceselectorcontrol.h" -#include "mmrenderermediaplayerservice.h" - -#include <QDebug> - -QT_BEGIN_NAMESPACE - -BbServicePlugin::BbServicePlugin() -{ -} - -QMediaService *BbServicePlugin::create(const QString &key) -{ - if (key == QLatin1String(Q_MEDIASERVICE_CAMERA)) - return new BbCameraService(); - - if (key == QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER)) - return new MmRendererMediaPlayerService(); - - return 0; -} - -void BbServicePlugin::release(QMediaService *service) -{ - delete service; -} - -QMediaServiceProviderHint::Features BbServicePlugin::supportedFeatures(const QByteArray &service) const -{ - Q_UNUSED(service) - return QMediaServiceProviderHint::Features(); -} - -QByteArray BbServicePlugin::defaultDevice(const QByteArray &service) const -{ - if (service == Q_MEDIASERVICE_CAMERA) { - if (m_cameraDevices.isEmpty()) - updateDevices(); - - return m_defaultCameraDevice; - } - - return QByteArray(); -} - -QList<QByteArray> BbServicePlugin::devices(const QByteArray &service) const -{ - if (service == Q_MEDIASERVICE_CAMERA) { - if (m_cameraDevices.isEmpty()) - updateDevices(); - - return m_cameraDevices; - } - - return QList<QByteArray>(); -} - -QString BbServicePlugin::deviceDescription(const QByteArray &service, const QByteArray &device) -{ - if (service == Q_MEDIASERVICE_CAMERA) { - if (m_cameraDevices.isEmpty()) - updateDevices(); - - for (int i = 0; i < m_cameraDevices.count(); i++) - if (m_cameraDevices[i] == device) - return m_cameraDescriptions[i]; - } - - return QString(); -} - -void BbServicePlugin::updateDevices() const -{ - m_defaultCameraDevice.clear(); - BbVideoDeviceSelectorControl::enumerateDevices(&m_cameraDevices, &m_cameraDescriptions); - - if (m_cameraDevices.isEmpty()) { - qWarning() << "No camera devices found"; - } else { - m_defaultCameraDevice = m_cameraDevices.contains(BbCameraSession::cameraIdentifierRear()) - ? BbCameraSession::cameraIdentifierRear() - : m_cameraDevices.first(); - } -} - -QCamera::Position BbServicePlugin::cameraPosition(const QByteArray &device) const -{ - return BbCameraInfoControl::position(device); -} - -int BbServicePlugin::cameraOrientation(const QByteArray &device) const -{ - return BbCameraInfoControl::orientation(device); -} - -QT_END_NAMESPACE diff --git a/src/plugins/qnx/bbserviceplugin.h b/src/plugins/qnx/bbserviceplugin.h deleted file mode 100644 index e2e77c233..000000000 --- a/src/plugins/qnx/bbserviceplugin.h +++ /dev/null @@ -1,84 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Research In Motion -** 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 BBRSERVICEPLUGIN_H -#define BBRSERVICEPLUGIN_H - -#include <qmediaserviceproviderplugin.h> - -QT_BEGIN_NAMESPACE - -class BbServicePlugin - : public QMediaServiceProviderPlugin, - public QMediaServiceSupportedDevicesInterface, - public QMediaServiceDefaultDeviceInterface, - public QMediaServiceCameraInfoInterface, - public QMediaServiceFeaturesInterface -{ - Q_OBJECT - Q_INTERFACES(QMediaServiceSupportedDevicesInterface) - Q_INTERFACES(QMediaServiceDefaultDeviceInterface) - Q_INTERFACES(QMediaServiceCameraInfoInterface) - Q_INTERFACES(QMediaServiceFeaturesInterface) - Q_PLUGIN_METADATA(IID "org.qt-project.qt.mediaserviceproviderfactory/5.0" FILE "blackberry_mediaservice.json") -public: - BbServicePlugin(); - - QMediaService *create(const QString &key) Q_DECL_OVERRIDE; - void release(QMediaService *service) Q_DECL_OVERRIDE; - QMediaServiceProviderHint::Features supportedFeatures(const QByteArray &service) const Q_DECL_OVERRIDE; - - QByteArray defaultDevice(const QByteArray &service) const Q_DECL_OVERRIDE; - QList<QByteArray> devices(const QByteArray &service) const Q_DECL_OVERRIDE; - QString deviceDescription(const QByteArray &service, const QByteArray &device) Q_DECL_OVERRIDE; - QVariant deviceProperty(const QByteArray &service, const QByteArray &device, const QByteArray &property) Q_DECL_OVERRIDE; - - QCamera::Position cameraPosition(const QByteArray &device) const Q_DECL_OVERRIDE; - int cameraOrientation(const QByteArray &device) const Q_DECL_OVERRIDE; - -private: - void updateDevices() const; - - mutable QByteArray m_defaultCameraDevice; - mutable QList<QByteArray> m_cameraDevices; - mutable QStringList m_cameraDescriptions; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/plugins/qnx/blackberry_mediaservice.json b/src/plugins/qnx/blackberry_mediaservice.json deleted file mode 100644 index 2a59cc770..000000000 --- a/src/plugins/qnx/blackberry_mediaservice.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "Keys": ["blackberrymultimedia"], - "Services": ["org.qt-project.qt.camera", "org.qt-project.qt.mediaplayer"] -} diff --git a/src/plugins/qnx/mediaplayer/bpsmediaplayercontrol.cpp b/src/plugins/qnx/mediaplayer/bpsmediaplayercontrol.cpp deleted file mode 100644 index 35bdb8360..000000000 --- a/src/plugins/qnx/mediaplayer/bpsmediaplayercontrol.cpp +++ /dev/null @@ -1,119 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Research In Motion -** 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 "bpsmediaplayercontrol.h" -#include "mmrenderervideowindowcontrol.h" - -#include <bps/mmrenderer.h> -#include <bps/screen.h> - -QT_BEGIN_NAMESPACE - -BpsMediaPlayerControl::BpsMediaPlayerControl(QObject *parent) - : MmRendererMediaPlayerControl(parent), - m_eventMonitor(0) -{ - openConnection(); -} - -BpsMediaPlayerControl::~BpsMediaPlayerControl() -{ - destroy(); -} - -void BpsMediaPlayerControl::startMonitoring(int contextId, const QString &contextName) -{ - m_eventMonitor = mmrenderer_request_events(contextName.toLatin1().constData(), 0, contextId); - if (!m_eventMonitor) { - qDebug() << "Unable to request multimedia events"; - emit error(0, "Unable to request multimedia events"); - } -} - -void BpsMediaPlayerControl::stopMonitoring() -{ - if (m_eventMonitor) { - mmrenderer_stop_events(m_eventMonitor); - m_eventMonitor = 0; - } -} - -bool BpsMediaPlayerControl::nativeEventFilter(const QByteArray &eventType, void *message, long *result) -{ - Q_UNUSED(result) - Q_UNUSED(eventType) - - bps_event_t * const event = static_cast<bps_event_t *>(message); - if (!event || - (bps_event_get_domain(event) != mmrenderer_get_domain() && - bps_event_get_domain(event) != screen_get_domain())) - return false; - - if (event && bps_event_get_domain(event) == screen_get_domain()) { - const screen_event_t screen_event = screen_event_get_event(event); - if (MmRendererVideoWindowControl *control = videoWindowControl()) - control->screenEventHandler(screen_event); - } - - if (bps_event_get_domain(event) == mmrenderer_get_domain()) { - if (bps_event_get_code(event) == MMRENDERER_STATE_CHANGE) { - const mmrenderer_state_t newState = mmrenderer_event_get_state(event); - if (newState == MMR_STOPPED) { - handleMmStopped(); - return false; - } - } - - if (bps_event_get_code(event) == MMRENDERER_STATUS_UPDATE) { - const qint64 newPosition = QString::fromLatin1(mmrenderer_event_get_position(event)). - toLongLong(); - handleMmStatusUpdate(newPosition); - - const QString status = QString::fromLatin1(mmrenderer_event_get_bufferstatus(event)); - setMmBufferStatus(status); - - const QString level = QString::fromLatin1(mmrenderer_event_get_bufferlevel(event)); - setMmBufferLevel(level); - } - } - - return false; -} - -QT_END_NAMESPACE diff --git a/src/plugins/qnx/mediaplayer/mediaplayer.pri b/src/plugins/qnx/mediaplayer/mediaplayer.pri index 9dedab0fd..756857cce 100644 --- a/src/plugins/qnx/mediaplayer/mediaplayer.pri +++ b/src/plugins/qnx/mediaplayer/mediaplayer.pri @@ -7,8 +7,8 @@ HEADERS += \ $$PWD/mmrenderermetadatareadercontrol.h \ $$PWD/mmrendererplayervideorenderercontrol.h \ $$PWD/mmrendererutil.h \ - $$PWD/mmrenderervideowindowcontrol.h - + $$PWD/mmrenderervideowindowcontrol.h \ + $$PWD/ppsmediaplayercontrol.h SOURCES += \ $$PWD/mmrenderermediaplayercontrol.cpp \ $$PWD/mmrenderermediaplayerservice.cpp \ @@ -16,16 +16,7 @@ SOURCES += \ $$PWD/mmrenderermetadatareadercontrol.cpp \ $$PWD/mmrendererplayervideorenderercontrol.cpp \ $$PWD/mmrendererutil.cpp \ - $$PWD/mmrenderervideowindowcontrol.cpp - -LIBS += -lmmrndclient -lstrm + $$PWD/mmrenderervideowindowcontrol.cpp \ + $$PWD/ppsmediaplayercontrol.cpp -blackberry { - HEADERS += $$PWD/bpsmediaplayercontrol.h - SOURCES += $$PWD/bpsmediaplayercontrol.cpp -} else { - HEADERS += $$PWD/ppsmediaplayercontrol.h - SOURCES += $$PWD/ppsmediaplayercontrol.cpp - QT += core-private - LIBS += -lpps -} +QMAKE_USE += mmrenderer pps diff --git a/src/plugins/qnx/mediaplayer/mmrenderermediaplayerservice.cpp b/src/plugins/qnx/mediaplayer/mmrenderermediaplayerservice.cpp index 2709a99dd..e253c68d8 100644 --- a/src/plugins/qnx/mediaplayer/mmrenderermediaplayerservice.cpp +++ b/src/plugins/qnx/mediaplayer/mmrenderermediaplayerservice.cpp @@ -44,13 +44,7 @@ #include "mmrendererutil.h" #include "mmrenderervideowindowcontrol.h" -#ifdef Q_OS_BLACKBERRY -#include "bpsmediaplayercontrol.h" -typedef BpsMediaPlayerControl PlatformSpecificMediaPlayerControl; -#else #include "ppsmediaplayercontrol.h" -typedef PpsMediaPlayerControl PlatformSpecificMediaPlayerControl; -#endif QT_BEGIN_NAMESPACE @@ -78,7 +72,7 @@ QMediaControl *MmRendererMediaPlayerService::requestControl(const char *name) { if (qstrcmp(name, QMediaPlayerControl_iid) == 0) { if (!m_mediaPlayerControl) { - m_mediaPlayerControl = new PlatformSpecificMediaPlayerControl; + m_mediaPlayerControl = new PpsMediaPlayerControl; updateControls(); } return m_mediaPlayerControl; diff --git a/src/plugins/qnx/qnx.pro b/src/plugins/qnx/qnx.pro index 2ad5110d6..960c614e0 100644 --- a/src/plugins/qnx/qnx.pro +++ b/src/plugins/qnx/qnx.pro @@ -1,23 +1,15 @@ TARGET = qtmedia_qnx -QT += multimedia-private gui-private +QT += multimedia-private gui-private core-private LIBS += -lscreen include(common/common.pri) include(mediaplayer/mediaplayer.pri) -blackberry { - include(camera/camera.pri) - HEADERS += bbserviceplugin.h - SOURCES += bbserviceplugin.cpp - OTHER_FILES += blackberry_mediaservice.json - PLUGIN_CLASS_NAME = BbServicePlugin -} else { - HEADERS += neutrinoserviceplugin.h - SOURCES += neutrinoserviceplugin.cpp - OTHER_FILES += neutrino_mediaservice.json - PLUGIN_CLASS_NAME = NeutrinoServicePlugin -} +HEADERS += neutrinoserviceplugin.h +SOURCES += neutrinoserviceplugin.cpp +OTHER_FILES += neutrino_mediaservice.json +PLUGIN_CLASS_NAME = NeutrinoServicePlugin PLUGIN_TYPE = mediaservice load(qt_plugin) diff --git a/src/plugins/resourcepolicy/resourcepolicy.pro b/src/plugins/resourcepolicy/resourcepolicy.pro index 91a946665..89e75be1b 100644 --- a/src/plugins/resourcepolicy/resourcepolicy.pro +++ b/src/plugins/resourcepolicy/resourcepolicy.pro @@ -1,8 +1,8 @@ TARGET = resourceqt QT += multimedia-private -CONFIG += link_pkgconfig -PKGCONFIG += libresourceqt5 + +QMAKE_USE += libresourceqt5 INCLUDEPATH += $$PWD \ $${SOURCE_DIR}/src/multimedia diff --git a/src/plugins/videonode/videonode.pro b/src/plugins/videonode/videonode.pro index e38b0a6a0..ab7295406 100644 --- a/src/plugins/videonode/videonode.pro +++ b/src/plugins/videonode/videonode.pro @@ -1,7 +1,8 @@ TEMPLATE = subdirs +QT_FOR_CONFIG += gui-private multimedia-private -config_gpu_vivante { +qtConfig(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..a28d57219 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); @@ -875,7 +884,8 @@ HRESULT QWinRTCameraControl::initialize() emit statusChanged(d->status); } - HRESULT hr = QEventDispatcherWinRT::runOnXamlThread([this, d]() { + boolean isFocusSupported; + HRESULT hr = QEventDispatcherWinRT::runOnXamlThread([this, d, &isFocusSupported]() { HRESULT hr; ComPtr<IInspectable> capture; hr = RoActivateInstance(Wrappers::HString::MakeReference(RuntimeClass_Windows_Media_Capture_MediaCapture).Get(), @@ -940,7 +950,8 @@ HRESULT QWinRTCameraControl::initialize() hr = advancedVideoDeviceController->get_FocusControl(&d->focusControl); Q_ASSERT_SUCCEEDED(hr); - boolean isFocusSupported; + d->cameraFlashControl->initialize(advancedVideoDeviceController); + hr = d->focusControl->get_Supported(&isFocusSupported); Q_ASSERT_SUCCEEDED(hr); if (isFocusSupported) { @@ -949,11 +960,7 @@ HRESULT QWinRTCameraControl::initialize() qCDebug(lcMMCamera) << "Focus supported, but no control for regions of interest available"; hr = initializeFocus(); Q_ASSERT_SUCCEEDED(hr); - } else { - d->cameraFocusControl->setSupportedFocusMode(0); - d->cameraFocusControl->setSupportedFocusPointMode(QSet<QCameraFocus::FocusPointMode>()); } - d->cameraLocksControl->initialize(); Q_ASSERT_SUCCEEDED(hr); ComPtr<IMediaDeviceController> deviceController; @@ -1029,6 +1036,12 @@ HRESULT QWinRTCameraControl::initialize() return S_OK; }); + if (!isFocusSupported) { + d->cameraFocusControl->setSupportedFocusMode(0); + d->cameraFocusControl->setSupportedFocusPointMode(QSet<QCameraFocus::FocusPointMode>()); + } + d->cameraLocksControl->initialize(); + if (SUCCEEDED(hr) && d->state != QCamera::LoadedState) { d->state = QCamera::LoadedState; emit stateChanged(d->state); @@ -1228,30 +1241,34 @@ bool QWinRTCameraControl::focus() { Q_D(QWinRTCameraControl); HRESULT hr; - AsyncStatus status = AsyncStatus::Completed; - if (d->focusOperation) { - ComPtr<IAsyncInfo> info; - hr = d->focusOperation.As(&info); - Q_ASSERT_SUCCEEDED(hr); - info->get_Status(&status); - } - - if (!d->focusControl || status == AsyncStatus::Started) + if (!d->focusControl) return false; QEventDispatcherWinRT::runOnXamlThread([&d, &hr]() { + if (d->focusOperation) { + ComPtr<IAsyncInfo> info; + hr = d->focusOperation.As(&info); + Q_ASSERT_SUCCEEDED(hr); + + AsyncStatus status = AsyncStatus::Completed; + hr = info->get_Status(&status); + Q_ASSERT_SUCCEEDED(hr); + if (status == AsyncStatus::Started) + return E_ASYNC_OPERATION_NOT_STARTED; + } + hr = d->focusControl->FocusAsync(&d->focusOperation); Q_ASSERT_SUCCEEDED(hr); + + const long errorCode = HRESULT_CODE(hr); + if (errorCode == ERROR_OPERATION_IN_PROGRESS + || errorCode == ERROR_WRITE_PROTECT) { + return E_ASYNC_OPERATION_NOT_STARTED; + } + Q_ASSERT_SUCCEEDED(hr); return S_OK; }); - const long errorCode = HRESULT_CODE(hr); - if (errorCode == ERROR_OPERATION_IN_PROGRESS - || errorCode == ERROR_WRITE_PROTECT) { - return false; - } - Q_ASSERT_SUCCEEDED(hr); - hr = QWinRTFunctions::await(d->focusOperation, QWinRTFunctions::ProcessThreadEvents); - Q_ASSERT_SUCCEEDED(hr); + return hr == S_OK; } @@ -1272,15 +1289,22 @@ bool QWinRTCameraControl::lockFocus() Q_D(QWinRTCameraControl); if (!d->focusControl) return false; - ComPtr<IFocusControl2> focusControl2; - HRESULT hr = d->focusControl.As(&focusControl2); - Q_ASSERT_SUCCEEDED(hr); + + bool result = false; ComPtr<IAsyncAction> op; - hr = focusControl2->LockAsync(&op); - if (HRESULT_CODE(hr) == ERROR_WRITE_PROTECT) - return false; - Q_ASSERT_SUCCEEDED(hr); - return QWinRTFunctions::await(op) == S_OK; + HRESULT hr; + hr = QEventDispatcherWinRT::runOnXamlThread([d, &result, &op]() { + ComPtr<IFocusControl2> focusControl2; + HRESULT hr = d->focusControl.As(&focusControl2); + Q_ASSERT_SUCCEEDED(hr); + hr = focusControl2->LockAsync(&op); + if (HRESULT_CODE(hr) == ERROR_WRITE_PROTECT) + return S_OK; + Q_ASSERT_SUCCEEDED(hr); + result = true; + return hr; + }); + return result ? (QWinRTFunctions::await(op) == S_OK) : false; } bool QWinRTCameraControl::unlockFocus() @@ -1288,15 +1312,22 @@ bool QWinRTCameraControl::unlockFocus() Q_D(QWinRTCameraControl); if (!d->focusControl) return false; - ComPtr<IFocusControl2> focusControl2; - HRESULT hr = d->focusControl.As(&focusControl2); - Q_ASSERT_SUCCEEDED(hr); + + bool result = false; ComPtr<IAsyncAction> op; - hr = focusControl2->UnlockAsync(&op); - if (HRESULT_CODE(hr) == ERROR_WRITE_PROTECT) - return false; - Q_ASSERT_SUCCEEDED(hr); - return QWinRTFunctions::await(op) == S_OK; + HRESULT hr; + hr = QEventDispatcherWinRT::runOnXamlThread([d, &result, &op]() { + ComPtr<IFocusControl2> focusControl2; + HRESULT hr = d->focusControl.As(&focusControl2); + Q_ASSERT_SUCCEEDED(hr); + hr = focusControl2->UnlockAsync(&op); + if (HRESULT_CODE(hr) == ERROR_WRITE_PROTECT) + return S_OK; + Q_ASSERT_SUCCEEDED(hr); + result = true; + return hr; + }); + return result ? (QWinRTFunctions::await(op) == S_OK) : false; } #else // !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP) 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/plugins/wmf/decoder/decoder.pri b/src/plugins/wmf/decoder/decoder.pri index 992e710fe..7637ac848 100644 --- a/src/plugins/wmf/decoder/decoder.pri +++ b/src/plugins/wmf/decoder/decoder.pri @@ -1,7 +1,7 @@ INCLUDEPATH += $$PWD -LIBS += -lstrmiids -ldmoguids -luuid -lmsdmo -lole32 -loleaut32 -lMf -lMfuuid -lMfplat \ - -lPropsys -lmfreadwrite -lwmcodecdspuuid +LIBS += -lmfreadwrite -lwmcodecdspuuid +QMAKE_USE += wmf HEADERS += \ $$PWD/mfdecoderservice.h \ @@ -11,4 +11,4 @@ HEADERS += \ SOURCES += \ $$PWD/mfdecoderservice.cpp \ $$PWD/mfdecodersourcereader.cpp \ - $$PWD/mfaudiodecodercontrol.cpp
\ No newline at end of file + $$PWD/mfaudiodecodercontrol.cpp diff --git a/src/plugins/wmf/player/player.pri b/src/plugins/wmf/player/player.pri index a10e2df60..38ccb82a6 100644 --- a/src/plugins/wmf/player/player.pri +++ b/src/plugins/wmf/player/player.pri @@ -1,6 +1,7 @@ INCLUDEPATH += $$PWD -LIBS += -lstrmiids -ldmoguids -luuid -lmsdmo -lgdi32 -luser32 -lole32 -loleaut32 -lMf -lMfuuid -lMfplat -lPropsys +LIBS += -lgdi32 -luser32 +QMAKE_USE += wmf DEFINES += QMEDIA_MEDIAFOUNDATION_PLAYER diff --git a/src/plugins/wmf/wmfserviceplugin.cpp b/src/plugins/wmf/wmfserviceplugin.cpp index c6597ed78..e19154aee 100644 --- a/src/plugins/wmf/wmfserviceplugin.cpp +++ b/src/plugins/wmf/wmfserviceplugin.cpp @@ -101,6 +101,8 @@ QMediaServiceProviderHint::Features WMFServicePlugin::supportedFeatures( if (service == Q_MEDIASERVICE_MEDIAPLAYER) return QMediaServiceProviderHint::StreamPlayback; else +#else + Q_UNUSED(service); #endif return QMediaServiceProviderHint::Features(); } 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..97a053379 100644 --- a/src/src.pro +++ b/src/src.pro @@ -2,6 +2,9 @@ TEMPLATE = subdirs SUBDIRS += multimedia +include($$OUT_PWD/multimedia/qtmultimedia-config.pri) +QT_FOR_CONFIG += multimedia-private + # Everything else depends on multimedia src_qgsttools.subdir = gsttools src_qgsttools.depends = multimedia @@ -13,7 +16,7 @@ src_plugins.subdir = plugins src_plugins.depends = multimedia -qtHaveModule(quick) { +qtHaveModule(quick):qtConfig(opengl) { src_qtmultimediaquicktools.subdir = qtmultimediaquicktools src_qtmultimediaquicktools.depends = multimedia @@ -39,7 +42,7 @@ qtHaveModule(widgets) { src_qgsttools.depends += src_qtmmwidgets } -config_gstreamer { +qtConfig(gstreamer) { SUBDIRS += src_qgsttools # If gstreamer is present, then plugins should depend on it diff --git a/sync.profile b/sync.profile index b3a788aa3..4623849da 100644 --- a/sync.profile +++ b/sync.profile @@ -12,3 +12,8 @@ "qmediametadata.h" => "QMediaMetaData", "qmultimedia.h" => "QMultimedia" ); +%deprecatedheaders = ( + "QtMultimedia" => { + "qtmultimediadefs.h" => "QtMultimedia/qtmultimediaglobal.h" + }, +); 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/qcamerabackend/tst_qcamerabackend.cpp b/tests/auto/integration/qcamerabackend/tst_qcamerabackend.cpp index 9529f1bc4..5035cb6b1 100644 --- a/tests/auto/integration/qcamerabackend/tst_qcamerabackend.cpp +++ b/tests/auto/integration/qcamerabackend/tst_qcamerabackend.cpp @@ -229,11 +229,6 @@ void tst_QCameraBackend::testCameraStates() QTRY_COMPARE(camera.status(), QCamera::UnloadedStatus); QCOMPARE(statusChangedSignal.last().first().value<QCamera::Status>(), QCamera::UnloadedStatus); -#ifdef Q_WS_MAEMO_6 - //resource policy doesn't work correctly when resource is released and immediately requested again. - QTest::qWait(250); -#endif - camera.start(); QCOMPARE(camera.state(), QCamera::ActiveState); QCOMPARE(stateChangedSignal.last().first().value<QCamera::State>(), QCamera::ActiveState); @@ -386,10 +381,6 @@ void tst_QCameraBackend::testCaptureToBuffer() camera.load(); -#ifdef Q_WS_MAEMO_6 - QVERIFY(imageCapture.isCaptureDestinationSupported(QCameraImageCapture::CaptureToBuffer)); -#endif - if (!imageCapture.isCaptureDestinationSupported(QCameraImageCapture::CaptureToBuffer)) QSKIP("Buffer capture not supported"); @@ -454,11 +445,6 @@ void tst_QCameraBackend::testCaptureToBuffer() imageAvailableSignal.clear(); savedSignal.clear(); - //Capture to yuv buffer -#ifdef Q_WS_MAEMO_6 - QVERIFY(imageCapture.supportedBufferFormats().contains(QVideoFrame::Format_UYVY)); -#endif - if (imageCapture.supportedBufferFormats().contains(QVideoFrame::Format_UYVY)) { imageCapture.setBufferFormat(QVideoFrame::Format_UYVY); QCOMPARE(imageCapture.bufferFormat(), QVideoFrame::Format_UYVY); @@ -493,9 +479,6 @@ void tst_QCameraBackend::testCaptureToBuffer() QTRY_VERIFY(imageCapture.isReadyForCapture()); //Try to capture to both buffer and file -#ifdef Q_WS_MAEMO_6 - QVERIFY(imageCapture.isCaptureDestinationSupported(QCameraImageCapture::CaptureToBuffer | QCameraImageCapture::CaptureToFile)); -#endif if (imageCapture.isCaptureDestinationSupported(QCameraImageCapture::CaptureToBuffer | QCameraImageCapture::CaptureToFile)) { imageCapture.setCaptureDestination(QCameraImageCapture::CaptureToBuffer | QCameraImageCapture::CaptureToFile); @@ -524,9 +507,7 @@ void tst_QCameraBackend::testCaptureToBuffer() void tst_QCameraBackend::testCameraCaptureMetadata() { -#ifndef Q_WS_MAEMO_6 QSKIP("Capture metadata is supported only on harmattan"); -#endif QCamera camera; QCameraImageCapture imageCapture(&camera); @@ -547,9 +528,7 @@ void tst_QCameraBackend::testCameraCaptureMetadata() void tst_QCameraBackend::testExposureCompensation() { -#if !defined(Q_WS_MAEMO_6) QSKIP("Capture exposure parameters are supported only on mobile platforms"); -#endif QCamera camera; QCameraExposure *exposure = camera.exposure(); @@ -594,16 +573,11 @@ void tst_QCameraBackend::testExposureCompensation() void tst_QCameraBackend::testExposureMode() { -#if !defined(Q_WS_MAEMO_6) QSKIP("Capture exposure parameters are supported only on mobile platforms"); -#endif QCamera camera; QCameraExposure *exposure = camera.exposure(); -#ifdef Q_WS_MAEMO_6 - QEXPECT_FAIL("", "Camerabin reports Manual exposure instead of Auto", Continue); -#endif QCOMPARE(exposure->exposureMode(), QCameraExposure::ExposureAuto); // Night @@ -616,11 +590,6 @@ void tst_QCameraBackend::testExposureMode() camera.unload(); QTRY_COMPARE(camera.status(), QCamera::UnloadedStatus); -#ifdef Q_WS_MAEMO_6 - //resource policy doesn't work correctly when resource is released and immediately requested again. - QTest::qWait(250); -#endif - // Auto exposure->setExposureMode(QCameraExposure::ExposureAuto); QCOMPARE(exposure->exposureMode(), QCameraExposure::ExposureAuto); diff --git a/tests/auto/integration/qmediaplayerbackend/BLACKLIST b/tests/auto/integration/qmediaplayerbackend/BLACKLIST index 837032759..e826fc079 100644 --- a/tests/auto/integration/qmediaplayerbackend/BLACKLIST +++ b/tests/auto/integration/qmediaplayerbackend/BLACKLIST @@ -17,12 +17,8 @@ windows 64bit developer-build windows 64bit developer-build [playPauseStop] -redhatenterpriselinuxworkstation-6.6 -rhel-7.1 -ubuntu-14.04 64bit -ubuntu-16.04 64bit +linux windows 64bit developer-build -rhel-7.2 [processEOS] windows 64bit developer-build diff --git a/tests/auto/integration/qsoundeffect/BLACKLIST b/tests/auto/integration/qsoundeffect/BLACKLIST index 8edfcd8e9..467169fcf 100644 --- a/tests/auto/integration/qsoundeffect/BLACKLIST +++ b/tests/auto/integration/qsoundeffect/BLACKLIST @@ -1,3 +1,6 @@ +[testSetSourceWhileLoading] +linux + #QTBUG-55735 [testSetSourceWhilePlaying] linux diff --git a/tests/auto/integration/qsoundeffect/qsoundeffect.pro b/tests/auto/integration/qsoundeffect/qsoundeffect.pro index 7a0f63e4b..8ec2e458a 100644 --- a/tests/auto/integration/qsoundeffect/qsoundeffect.pro +++ b/tests/auto/integration/qsoundeffect/qsoundeffect.pro @@ -8,12 +8,9 @@ CONFIG += testcase SOURCES += tst_qsoundeffect.cpp unix:!mac { - !contains(QT_CONFIG, pulseaudio) { + !qtConfig(pulseaudio) { DEFINES += QT_MULTIMEDIA_QMEDIAPLAYER } } 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/qgraphicsvideoitem/tst_qgraphicsvideoitem.cpp b/tests/auto/unit/qgraphicsvideoitem/tst_qgraphicsvideoitem.cpp index fb689fbd3..f4759bbf7 100644 --- a/tests/auto/unit/qgraphicsvideoitem/tst_qgraphicsvideoitem.cpp +++ b/tests/auto/unit/qgraphicsvideoitem/tst_qgraphicsvideoitem.cpp @@ -28,7 +28,7 @@ //TESTED_COMPONENT=src/multimedia -#include <qtmultimediadefs.h> +#include <qtmultimediaglobal.h> #include "qgraphicsvideoitem.h" #include <QtTest/QtTest> #include "qmediaobject.h" 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 diff --git a/tests/auto/unit/qpaintervideosurface/tst_qpaintervideosurface.cpp b/tests/auto/unit/qpaintervideosurface/tst_qpaintervideosurface.cpp index ae1f7a5bc..4b2136a5c 100644 --- a/tests/auto/unit/qpaintervideosurface/tst_qpaintervideosurface.cpp +++ b/tests/auto/unit/qpaintervideosurface/tst_qpaintervideosurface.cpp @@ -34,7 +34,7 @@ #include <QtWidgets/qapplication.h> #include <qvideosurfaceformat.h> -#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1) +#if QT_CONFIG(opengl) #include <QtOpenGL/qgl.h> #include <QtOpenGL/qglframebufferobject.h> #include <QtGui/qopenglfunctions.h> @@ -57,7 +57,7 @@ private slots: void present(); void presentOpaqueFrame(); -#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1) +#if QT_CONFIG(opengl) void shaderType(); @@ -78,7 +78,7 @@ private slots: Q_DECLARE_METATYPE(const uchar *) -#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1) +#if QT_CONFIG(opengl) Q_DECLARE_METATYPE(QPainterVideoSurface::ShaderType); class QtTestGLVideoBuffer : public QAbstractVideoBuffer @@ -551,7 +551,7 @@ void tst_QPainterVideoSurface::presentOpaqueFrame() QCOMPARE(surface.error(), QAbstractVideoSurface::IncorrectFormatError); } -#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1) +#if QT_CONFIG(opengl) void tst_QPainterVideoSurface::shaderType() { diff --git a/tests/auto/unit/qvideowidget/tst_qvideowidget.cpp b/tests/auto/unit/qvideowidget/tst_qvideowidget.cpp index a1d16e60b..3baa72281 100644 --- a/tests/auto/unit/qvideowidget/tst_qvideowidget.cpp +++ b/tests/auto/unit/qvideowidget/tst_qvideowidget.cpp @@ -28,7 +28,7 @@ //TESTED_COMPONENT=src/multimedia -#include <qtmultimediadefs.h> +#include <qtmultimediaglobal.h> #include <QtTest/QtTest> #include "qvideowidget.h" |