diff options
Diffstat (limited to 'src/multimedia/platform')
16 files changed, 231 insertions, 277 deletions
diff --git a/src/multimedia/platform/android/common/qandroidaudiooutput_p.h b/src/multimedia/platform/android/common/qandroidaudiooutput_p.h new file mode 100644 index 000000000..65e40a300 --- /dev/null +++ b/src/multimedia/platform/android/common/qandroidaudiooutput_p.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2021 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 QANDROIDAUDIOOUTPUT_H +#define QANDROIDAUDIOOUTPUT_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 <private/qplatformaudiooutput_p.h> + +QT_BEGIN_NAMESPACE + +class Q_MULTIMEDIA_EXPORT QAndroidAudioOutput : public QPlatformAudioOutput +{ +public: + QAndroidAudioOutput(QAudioOutput *qq) : QPlatformAudioOutput(qq) {} + + virtual QList<QAudio::Role> supportedAudioRoles() const { + return QList<QAudio::Role>() + << QAudio::VoiceCommunicationRole + << QAudio::MusicRole + << QAudio::VideoRole + << QAudio::SonificationRole + << QAudio::AlarmRole + << QAudio::NotificationRole + << QAudio::RingtoneRole + << QAudio::AccessibilityRole + << QAudio::GameRole; + } +}; + +QT_END_NAMESPACE + + +#endif // QANDROIDAUDIOOUTPUT_H diff --git a/src/multimedia/platform/android/mediaplayer/qandroidmediaplayercontrol.cpp b/src/multimedia/platform/android/mediaplayer/qandroidmediaplayercontrol.cpp index 4794dd3e0..85b4e3df4 100644 --- a/src/multimedia/platform/android/mediaplayer/qandroidmediaplayercontrol.cpp +++ b/src/multimedia/platform/android/mediaplayer/qandroidmediaplayercontrol.cpp @@ -42,6 +42,8 @@ #include "qandroidvideooutput_p.h" #include "qandroidmetadata_p.h" #include "qandroidmediaplayervideorenderercontrol_p.h" +#include "qandroidaudiooutput_p.h" +#include "qaudiooutput.h" QT_BEGIN_NAMESPACE @@ -184,12 +186,7 @@ void QAndroidMediaPlayerControl::setPosition(qint64 position) Q_EMIT positionChanged(seekPosition); } -int QAndroidMediaPlayerControl::volume() const -{ - return (mPendingVolume == -1) ? mMediaPlayer->volume() : mPendingVolume; -} - -void QAndroidMediaPlayerControl::setVolume(int volume) +void QAndroidMediaPlayerControl::setVolume(float volume) { if ((mState & (AndroidMediaPlayer::Idle | AndroidMediaPlayer::Initialized @@ -198,26 +195,12 @@ void QAndroidMediaPlayerControl::setVolume(int volume) | AndroidMediaPlayer::Started | AndroidMediaPlayer::Paused | AndroidMediaPlayer::PlaybackCompleted)) == 0) { - if (mPendingVolume != volume) { - mPendingVolume = volume; - Q_EMIT volumeChanged(volume); - } - return; - } - - mMediaPlayer->setVolume(volume); - - if (mPendingVolume != -1) { - mPendingVolume = -1; + mPendingVolume = volume; return; } - Q_EMIT volumeChanged(volume); -} - -bool QAndroidMediaPlayerControl::isMuted() const -{ - return (mPendingMute == -1) ? mMediaPlayer->isMuted() : (mPendingMute == 1); + mMediaPlayer->setVolume(qRound(volume*100.)); + mPendingVolume = -1; } void QAndroidMediaPlayerControl::setMuted(bool muted) @@ -229,21 +212,12 @@ void QAndroidMediaPlayerControl::setMuted(bool muted) | AndroidMediaPlayer::Started | AndroidMediaPlayer::Paused | AndroidMediaPlayer::PlaybackCompleted)) == 0) { - if (mPendingMute != muted) { - mPendingMute = muted; - Q_EMIT mutedChanged(muted); - } + mPendingMute = muted; return; } mMediaPlayer->setMuted(muted); - - if (mPendingMute != -1) { - mPendingMute = -1; - return; - } - - Q_EMIT mutedChanged(muted); + mPendingMute = -1; } void QAndroidMediaPlayerControl::setAudioRole(QAudio::Role role) @@ -251,20 +225,6 @@ void QAndroidMediaPlayerControl::setAudioRole(QAudio::Role role) mMediaPlayer->setAudioRole(role); } -QList<QAudio::Role> QAndroidMediaPlayerControl::supportedAudioRoles() const -{ - return QList<QAudio::Role>() - << QAudio::VoiceCommunicationRole - << QAudio::MusicRole - << QAudio::VideoRole - << QAudio::SonificationRole - << QAudio::AlarmRole - << QAudio::NotificationRole - << QAudio::RingtoneRole - << QAudio::AccessibilityRole - << QAudio::GameRole; -} - QMediaMetaData QAndroidMediaPlayerControl::metaData() const { return QAndroidMetaData::extractMetadata(mMediaContent); @@ -429,6 +389,21 @@ void QAndroidMediaPlayerControl::setVideoSink(QVideoSink *sink) mVideoRendererControl->setSurface(sink); } +void QAndroidMediaPlayerControl::setAudioOutput(QPlatformAudioOutput *output) +{ + if (m_audioOutput == output) + return; + if (m_audioOutput) + m_audioOutput->q->disconnect(this); + m_audioOutput = static_cast<QAndroidAudioOutput *>(output); + if (m_audioOutput) { + // #### Implement device changes: connect(m_audioOutput->q, &QAudioOutput::deviceChanged, this, XXXX); + connect(m_audioOutput->q, &QAudioOutput::volumeChanged, this, &QAndroidMediaPlayerControl::setVolume); + connect(m_audioOutput->q, &QAudioOutput::mutedChanged, this, &QAndroidMediaPlayerControl::setMuted); + connect(m_audioOutput->q, &QAudioOutput::audioRoleChanged, this, &QAndroidMediaPlayerControl::setAudioRole); + } +} + void QAndroidMediaPlayerControl::play() { StateChangeNotifier notifier(this); @@ -772,7 +747,7 @@ void QAndroidMediaPlayerControl::flushPendingStates() if (mPendingPosition != -1) setPosition(mPendingPosition); - if (mPendingVolume != -1) + if (mPendingVolume >= 0) setVolume(mPendingVolume); if (mPendingMute != -1) setMuted((mPendingMute == 1)); diff --git a/src/multimedia/platform/android/mediaplayer/qandroidmediaplayercontrol_p.h b/src/multimedia/platform/android/mediaplayer/qandroidmediaplayercontrol_p.h index d1db4fd58..3bbc20260 100644 --- a/src/multimedia/platform/android/mediaplayer/qandroidmediaplayercontrol_p.h +++ b/src/multimedia/platform/android/mediaplayer/qandroidmediaplayercontrol_p.h @@ -61,6 +61,7 @@ QT_BEGIN_NAMESPACE class AndroidMediaPlayer; class QAndroidVideoOutput; class QAndroidMediaPlayerVideoRendererControl; +class QAndroidAudioOutput; class QAndroidMediaPlayerControl : public QObject, public QPlatformMediaPlayer { @@ -72,8 +73,6 @@ public: QMediaPlayer::PlaybackState state() const override; qint64 duration() const override; qint64 position() const override; - int volume() const override; - bool isMuted() const override; float bufferProgress() const override; bool isAudioAvailable() const override; bool isVideoAvailable() const override; @@ -85,22 +84,22 @@ public: const QIODevice *mediaStream() const override; void setMedia(const QUrl &mediaContent, QIODevice *stream) override; - void setAudioRole(QAudio::Role role) override; - QList<QAudio::Role> supportedAudioRoles() const override; - QMediaMetaData metaData() const override; void setVideoOutput(QAndroidVideoOutput *videoOutput); void setVideoSink(QVideoSink *surface) override; + void setAudioOutput(QPlatformAudioOutput *output) override; + void setPosition(qint64 position) override; void play() override; void pause() override; void stop() override; - void setVolume(int volume) override; - void setMuted(bool muted) override; private Q_SLOTS: + void setVolume(float volume); + void setMuted(bool muted); + void setAudioRole(QAudio::Role role); void onVideoOutputReady(bool ready); void onError(qint32 what, qint32 extra); void onInfo(qint32 what, qint32 extra); @@ -111,6 +110,7 @@ private Q_SLOTS: private: AndroidMediaPlayer *mMediaPlayer; QAndroidMediaPlayerVideoRendererControl *mVideoRendererControl = nullptr; + QAndroidAudioOutput *m_audioOutput = nullptr; QMediaPlayer::PlaybackState mCurrentState; QUrl mMediaContent; QIODevice *mMediaStream; @@ -127,7 +127,7 @@ private: int mPendingState; qint64 mPendingPosition; bool mPendingSetMedia; - int mPendingVolume; + float mPendingVolume; int mPendingMute; bool mReloadingMedia; int mActiveStateChangeNotifiers; diff --git a/src/multimedia/platform/android/qandroidintegration.cpp b/src/multimedia/platform/android/qandroidintegration.cpp index d7fe2b3bc..167caea43 100644 --- a/src/multimedia/platform/android/qandroidintegration.cpp +++ b/src/multimedia/platform/android/qandroidintegration.cpp @@ -52,6 +52,7 @@ #include "private/androidmediarecorder_p.h" #include "private/qandroidformatsinfo_p.h" #include "private/qandroidmediaplayercontrol_p.h" +#include "private/qandroidaudiooutput_p.h" QT_BEGIN_NAMESPACE @@ -108,6 +109,11 @@ QPlatformCameraImageCapture *QAndroidIntegration::createImageCapture(QCameraImag return new QAndroidCameraImageCaptureControl(imageCapture); } +QPlatformAudioOutput *QAndroidIntegration::createAudioOutput(QAudioOutput *q) +{ + return new QAndroidAudioOutput(q); +} + Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void * /*reserved*/) { static bool initialized = false; diff --git a/src/multimedia/platform/android/qandroidintegration_p.h b/src/multimedia/platform/android/qandroidintegration_p.h index bab5e6529..b1ab26cfe 100644 --- a/src/multimedia/platform/android/qandroidintegration_p.h +++ b/src/multimedia/platform/android/qandroidintegration_p.h @@ -72,6 +72,8 @@ public: QPlatformMediaEncoder *createEncoder(QMediaEncoder *encoder) override; QPlatformCameraImageCapture *createImageCapture(QCameraImageCapture *imageCapture) override; + QPlatformAudioOutput *createAudioOutput(QAudioOutput *q) override; + QAndroidMediaDevices *m_devices = nullptr; QPlatformMediaFormatInfo *m_formatInfo = nullptr; }; diff --git a/src/multimedia/platform/darwin/mediaplayer/avfmediaplayer.mm b/src/multimedia/platform/darwin/mediaplayer/avfmediaplayer.mm index cfd310cd3..f60c61261 100644 --- a/src/multimedia/platform/darwin/mediaplayer/avfmediaplayer.mm +++ b/src/multimedia/platform/darwin/mediaplayer/avfmediaplayer.mm @@ -43,6 +43,9 @@ #include <private/avfvideosink_p.h> #include "avfmetadata_p.h" +#include "qaudiooutput.h" +#include "qplatformaudiooutput_p.h" + #include <qpointer.h> #include <QFileInfo> @@ -268,8 +271,9 @@ static void *AVFMediaPlayerObserverCurrentItemDurationObservationContext = &AVFM //Set the initial volume on new player object if (self.session) { - [m_player setVolume:m_session->volume() / 100.0f]; - [m_player setMuted:m_session->isMuted()]; + auto *audioOutput = m_session->m_audioOutput; + m_player.volume = (audioOutput ? audioOutput->volume : 1.); + m_player.muted = (audioOutput ? audioOutput->muted : true); } //Assign the output layer to the new player @@ -471,9 +475,7 @@ AVFMediaPlayer::AVFMediaPlayer(QMediaPlayer *player) , m_state(QMediaPlayer::StoppedState) , m_mediaStatus(QMediaPlayer::NoMedia) , m_mediaStream(nullptr) - , m_muted(false) , m_tryingAsync(false) - , m_volume(100) , m_rate(1.0) , m_requestedPosition(-1) , m_duration(0) @@ -651,16 +653,6 @@ float AVFMediaPlayer::bufferProgress() const return m_bufferProgress/100.; } -int AVFMediaPlayer::volume() const -{ - return m_volume; -} - -bool AVFMediaPlayer::isMuted() const -{ - return m_muted; -} - void AVFMediaPlayer::setAudioAvailable(bool available) { if (m_audioAvailable == available) @@ -727,25 +719,22 @@ qreal AVFMediaPlayer::playbackRate() const return m_rate; } -bool AVFMediaPlayer::setAudioOutput(const QAudioDevice &info) +void AVFMediaPlayer::setAudioOutput(QPlatformAudioOutput *output) { - m_audioOutput = info; - -#ifdef Q_OS_MACOS - AVPlayer *player = [static_cast<AVFMediaPlayerObserver*>(m_observer) player]; - if (info.isNull()) { - player.audioOutputDeviceUniqueID = nil; - } else { - NSString *str = QString::fromUtf8(info.id()).toNSString(); - player.audioOutputDeviceUniqueID = str; + if (m_audioOutput == output) + return; + if (m_audioOutput) + m_audioOutput->q->disconnect(this); + m_audioOutput = output; + if (m_audioOutput) { + connect(m_audioOutput->q, &QAudioOutput::deviceChanged, this, &AVFMediaPlayer::audioOutputChanged); + connect(m_audioOutput->q, &QAudioOutput::volumeChanged, this, &AVFMediaPlayer::setVolume); + connect(m_audioOutput->q, &QAudioOutput::mutedChanged, this, &AVFMediaPlayer::setMuted); + //connect(m_audioOutput->q, &QAudioOutput::audioRoleChanged, this, &AVFMediaPlayer::setAudioRole); } -#endif - return true; -} - -QAudioDevice AVFMediaPlayer::audioOutput() const -{ - return m_audioOutput; + audioOutputChanged(); + setMuted(m_audioOutput ? m_audioOutput->muted : true); + setVolume(m_audioOutput ? m_audioOutput->volume : 1.); } QMediaMetaData AVFMediaPlayer::metaData() const @@ -895,22 +884,15 @@ void AVFMediaPlayer::stop() m_playbackTimer.stop(); } -void AVFMediaPlayer::setVolume(int volume) +void AVFMediaPlayer::setVolume(float volume) { #ifdef QT_DEBUG_AVF qDebug() << Q_FUNC_INFO << volume; #endif - if (m_volume == volume) - return; - - m_volume = volume; - AVPlayer *player = [static_cast<AVFMediaPlayerObserver*>(m_observer) player]; if (player) - [player setVolume:volume / 100.0f]; - - Q_EMIT volumeChanged(m_volume); + player.volume = volume; } void AVFMediaPlayer::setMuted(bool muted) @@ -919,16 +901,24 @@ void AVFMediaPlayer::setMuted(bool muted) qDebug() << Q_FUNC_INFO << muted; #endif - if (m_muted == muted) - return; - - m_muted = muted; - AVPlayer *player = [static_cast<AVFMediaPlayerObserver*>(m_observer) player]; if (player) - [player setMuted:muted]; + player.muted = muted; +} - Q_EMIT mutedChanged(muted); +void AVFMediaPlayer::audioOutputChanged() +{ +#ifdef Q_OS_MACOS + AVPlayer *player = [static_cast<AVFMediaPlayerObserver*>(m_observer) player]; + if (!m_audioOutput || m_audioOutput->device.id().isEmpty()) { + player.audioOutputDeviceUniqueID = nil; + if (!m_audioOutput) + player.muted = true; + } else { + NSString *str = QString::fromUtf8(m_audioOutput->device.id()).toNSString(); + player.audioOutputDeviceUniqueID = str; + } +#endif } void AVFMediaPlayer::processEOS() diff --git a/src/multimedia/platform/darwin/mediaplayer/avfmediaplayer_p.h b/src/multimedia/platform/darwin/mediaplayer/avfmediaplayer_p.h index 367b3d81e..4bd082c1c 100644 --- a/src/multimedia/platform/darwin/mediaplayer/avfmediaplayer_p.h +++ b/src/multimedia/platform/darwin/mediaplayer/avfmediaplayer_p.h @@ -94,9 +94,6 @@ public: float bufferProgress() const override; - int volume() const override; - bool isMuted() const override; - bool isAudioAvailable() const override; bool isVideoAvailable() const override; @@ -105,9 +102,8 @@ public: qreal playbackRate() const override; - bool setAudioOutput(const QAudioDevice &) override; - QAudioDevice audioOutput() const override; - QAudioDevice m_audioOutput; + void setAudioOutput(QPlatformAudioOutput *output) override; + QPlatformAudioOutput *m_audioOutput = nullptr; QMediaMetaData metaData() const override; @@ -121,8 +117,9 @@ public Q_SLOTS: void pause() override; void stop() override; - void setVolume(int volume) override; - void setMuted(bool muted) override; + void setVolume(float volume); + void setMuted(bool muted); + void audioOutputChanged(); void processEOS(); void processLoadStateChange(QMediaPlayer::PlaybackState newState); @@ -163,9 +160,7 @@ private: QUrl m_resources; QMediaMetaData m_metaData; - bool m_muted; bool m_tryingAsync; - int m_volume; qreal m_rate; qint64 m_requestedPosition; diff --git a/src/multimedia/platform/gstreamer/common/qgstreameraudiooutput.cpp b/src/multimedia/platform/gstreamer/common/qgstreameraudiooutput.cpp index da0ffce72..a7a531e7f 100644 --- a/src/multimedia/platform/gstreamer/common/qgstreameraudiooutput.cpp +++ b/src/multimedia/platform/gstreamer/common/qgstreameraudiooutput.cpp @@ -96,8 +96,7 @@ bool QGstreamerAudioOutput::setAudioOutput(const QAudioDevice &info) qCDebug(qLcMediaAudioOutput) << "setAudioOutput" << info.description() << info.isNull(); m_audioOutput = info; - auto state = gstPipeline.state(); - if (state != GST_STATE_PLAYING) + if (gstPipeline.isNull() || gstPipeline.state() != GST_STATE_PLAYING) return changeAudioOutput(); auto pad = audioVolume.staticPad("src"); diff --git a/src/multimedia/platform/gstreamer/common/qgstreamermediaplayer.cpp b/src/multimedia/platform/gstreamer/common/qgstreamermediaplayer.cpp index 08ca8f23b..f1aa64a5a 100644 --- a/src/multimedia/platform/gstreamer/common/qgstreamermediaplayer.cpp +++ b/src/multimedia/platform/gstreamer/common/qgstreamermediaplayer.cpp @@ -70,11 +70,6 @@ QGstreamerMediaPlayer::QGstreamerMediaPlayer(QMediaPlayer *parent) QPlatformMediaPlayer(parent), playerPipeline("playerPipeline") { - gstAudioOutput = new QGstreamerAudioOutput(nullptr); - gstAudioOutput->setPipeline(playerPipeline); - connect(gstAudioOutput, &QGstreamerAudioOutput::mutedChanged, this, &QGstreamerMediaPlayer::mutedChangedHandler); - connect(gstAudioOutput, &QGstreamerAudioOutput::volumeChanged, this, &QGstreamerMediaPlayer::volumeChangedHandler); - gstVideoOutput = new QGstreamerVideoOutput(this); gstVideoOutput->setPipeline(playerPipeline); @@ -101,7 +96,6 @@ QGstreamerMediaPlayer::~QGstreamerMediaPlayer() playerPipeline.removeMessageFilter(this); playerPipeline.setStateSync(GST_STATE_NULL); topology.free(); - delete gstAudioOutput; } qint64 QGstreamerMediaPlayer::position() const @@ -122,16 +116,6 @@ float QGstreamerMediaPlayer::bufferProgress() const return m_bufferProgress/100.; } -int QGstreamerMediaPlayer::volume() const -{ - return qRound(gstAudioOutput->volume*100.); -} - -bool QGstreamerMediaPlayer::isMuted() const -{ - return gstAudioOutput->muted; -} - bool QGstreamerMediaPlayer::isSeekable() const { return true; @@ -232,25 +216,6 @@ void QGstreamerMediaPlayer::stopOrEOS(bool eos) mediaStatusChanged(eos ? QMediaPlayer::EndOfMedia : QMediaPlayer::LoadedMedia); } -void QGstreamerMediaPlayer::setVolume(int vol) -{ - float v = vol/100.; - if (v == gstAudioOutput->volume) - return; - gstAudioOutput->volume = v; - gstAudioOutput->setVolume(vol/100.); - volumeChanged(vol); -} - -void QGstreamerMediaPlayer::setMuted(bool muted) -{ - if (muted == gstAudioOutput->muted) - return; - gstAudioOutput->muted = muted; - gstAudioOutput->setMuted(muted); - mutedChanged(muted); -} - bool QGstreamerMediaPlayer::processBusMessage(const QGstreamerMessage &message) { if (message.isNull()) @@ -434,7 +399,8 @@ void QGstreamerMediaPlayer::decoderPadAdded(const QGstElement &src, const QGstPa output = gstVideoOutput->gstElement(); } else if (type.startsWith("audio/x-raw")) { streamType = AudioStream; - output = gstAudioOutput->gstElement(); + if (gstAudioOutput) + output = gstAudioOutput->gstElement(); } else if (type.startsWith("text/")) { streamType = SubtitleStream; } else { @@ -611,14 +577,12 @@ void QGstreamerMediaPlayer::setMedia(const QUrl &content, QIODevice *stream) positionChanged(0); } -bool QGstreamerMediaPlayer::setAudioOutput(const QAudioDevice &info) +void QGstreamerMediaPlayer::setAudioOutput(QPlatformAudioOutput *output) { - return gstAudioOutput->setAudioOutput(info); -} - -QAudioDevice QGstreamerMediaPlayer::audioOutput() const -{ - return gstAudioOutput->audioOutput(); + if (gstAudioOutput == output) + return; + gstAudioOutput = static_cast<QGstreamerAudioOutput *>(output); + // ### Connect it if we're already running! } QMediaMetaData QGstreamerMediaPlayer::metaData() const diff --git a/src/multimedia/platform/gstreamer/common/qgstreamermediaplayer_p.h b/src/multimedia/platform/gstreamer/common/qgstreamermediaplayer_p.h index 23062e4d0..2d939a0f8 100644 --- a/src/multimedia/platform/gstreamer/common/qgstreamermediaplayer_p.h +++ b/src/multimedia/platform/gstreamer/common/qgstreamermediaplayer_p.h @@ -84,9 +84,6 @@ public: float bufferProgress() const override; - int volume() const override; - bool isMuted() const override; - bool isAudioAvailable() const override; bool isVideoAvailable() const override; @@ -102,8 +99,7 @@ public: bool streamPlaybackSupported() const override { return true; } - bool setAudioOutput(const QAudioDevice &) override; - QAudioDevice audioOutput() const override; + void setAudioOutput(QPlatformAudioOutput *output) override; QMediaMetaData metaData() const override; @@ -120,13 +116,8 @@ public: void pause() override; void stop() override; - void setVolume(int volume) override; - void setMuted(bool muted) override; - bool processBusMessage(const QGstreamerMessage& message) override; public Q_SLOTS: - void volumeChangedHandler(int volume) { volumeChanged(volume); } - void mutedChangedHandler(bool mute) { mutedChanged(mute); } void updatePosition() { positionChanged(position()); } private: diff --git a/src/multimedia/platform/qplatformaudiooutput_p.h b/src/multimedia/platform/qplatformaudiooutput_p.h index 594d59ed0..9979a6d5e 100644 --- a/src/multimedia/platform/qplatformaudiooutput_p.h +++ b/src/multimedia/platform/qplatformaudiooutput_p.h @@ -66,11 +66,14 @@ public: virtual void setAudioDevice(const QAudioDevice &/*device*/) {} virtual void setMuted(bool /*muted*/) {} virtual void setVolume(float /*volume*/) {} + virtual void setAudioRole(QAudio::Role /*role*/) {} + virtual QList<QAudio::Role> supportedAudioRoles() const { return {}; } QAudioOutput *q = nullptr; QAudioDevice device; float volume = 1.; bool muted = false; + QAudio::Role role = QAudio::UnknownRole; }; QT_END_NAMESPACE diff --git a/src/multimedia/platform/qplatformmediaplayer_p.h b/src/multimedia/platform/qplatformmediaplayer_p.h index d32e6ee6d..542c87b39 100644 --- a/src/multimedia/platform/qplatformmediaplayer_p.h +++ b/src/multimedia/platform/qplatformmediaplayer_p.h @@ -61,6 +61,7 @@ QT_BEGIN_NAMESPACE class QMediaStreamsControl; +class QPlatformAudioOutput; class Q_MULTIMEDIA_EXPORT QPlatformMediaPlayer { @@ -74,12 +75,6 @@ public: virtual qint64 position() const = 0; virtual void setPosition(qint64 position) = 0; - virtual int volume() const = 0; - virtual void setVolume(int volume) = 0; - - virtual bool isMuted() const = 0; - virtual void setMuted(bool mute) = 0; - virtual float bufferProgress() const = 0; virtual bool isAudioAvailable() const = 0; @@ -100,13 +95,9 @@ public: virtual void pause() = 0; virtual void stop() = 0; - virtual void setAudioRole(QAudio::Role /*role*/) {} - virtual QList<QAudio::Role> supportedAudioRoles() const { return {}; } - virtual bool streamPlaybackSupported() const { return false; } - virtual bool setAudioOutput(const QAudioDevice &) { return false; } - virtual QAudioDevice audioOutput() const { return QAudioDevice(); } + virtual void setAudioOutput(QPlatformAudioOutput *) {} virtual QMediaMetaData metaData() const { return {}; } @@ -124,8 +115,6 @@ public: void positionChanged(qint64 position) { player->positionChanged(position); } void audioAvailableChanged(bool audioAvailable) { player->hasAudioChanged(audioAvailable); } void videoAvailableChanged(bool videoAvailable) { player->hasVideoChanged(videoAvailable); } - void volumeChanged(int volume) { player->volumeChanged(volume); } - void mutedChanged(bool mute) { player->mutedChanged(mute); } void seekableChanged(bool seekable) { player->seekableChanged(seekable); } void playbackRateChanged(qreal rate) { player->playbackRateChanged(rate); } void bufferProgressChanged(float progress) { player->bufferProgressChanged(progress); } diff --git a/src/multimedia/platform/windows/player/mfplayercontrol.cpp b/src/multimedia/platform/windows/player/mfplayercontrol.cpp index 117cd402c..e6ac343b3 100644 --- a/src/multimedia/platform/windows/player/mfplayercontrol.cpp +++ b/src/multimedia/platform/windows/player/mfplayercontrol.cpp @@ -126,14 +126,9 @@ QMediaMetaData MFPlayerControl::metaData() const return m_session->metaData(); } -bool MFPlayerControl::setAudioOutput(const QAudioDevice &info) +void MFPlayerControl::setAudioOutput(QPlatformAudioOutput *output) { - return m_session->setAudioOutput(info); -} - -QAudioDevice MFPlayerControl::audioOutput() const -{ - return m_session->audioOutput(); + m_session->setAudioOutput(output); } void MFPlayerControl::setVideoSink(QVideoSink *sink) @@ -254,26 +249,6 @@ void MFPlayerControl::setPosition(qint64 position) m_session->setPosition(position); } -int MFPlayerControl::volume() const -{ - return m_session->volume(); -} - -void MFPlayerControl::setVolume(int volume) -{ - m_session->setVolume(volume); -} - -bool MFPlayerControl::isMuted() const -{ - return m_session->isMuted(); -} - -void MFPlayerControl::setMuted(bool muted) -{ - m_session->setMuted(muted); -} - float MFPlayerControl::bufferProgress() const { return m_session->bufferProgress() / 100.; diff --git a/src/multimedia/platform/windows/player/mfplayercontrol_p.h b/src/multimedia/platform/windows/player/mfplayercontrol_p.h index 8433ae58a..995181626 100644 --- a/src/multimedia/platform/windows/player/mfplayercontrol_p.h +++ b/src/multimedia/platform/windows/player/mfplayercontrol_p.h @@ -75,12 +75,6 @@ public: qint64 position() const override; void setPosition(qint64 position) override; - int volume() const override; - void setVolume(int volume) override; - - bool isMuted() const override; - void setMuted(bool muted) override; - float bufferProgress() const override; bool isAudioAvailable() const override; @@ -105,8 +99,7 @@ public: QMediaMetaData metaData() const override; - bool setAudioOutput(const QAudioDevice &) override; - QAudioDevice audioOutput() const override; + void setAudioOutput(QPlatformAudioOutput *output) override; void setVideoSink(QVideoSink *sink) override; diff --git a/src/multimedia/platform/windows/player/mfplayersession.cpp b/src/multimedia/platform/windows/player/mfplayersession.cpp index b2afca6bf..1fa05c33a 100644 --- a/src/multimedia/platform/windows/player/mfplayersession.cpp +++ b/src/multimedia/platform/windows/player/mfplayersession.cpp @@ -47,6 +47,9 @@ #include <QtCore/qfile.h> #include <QtCore/qbuffer.h> +#include "qplatformaudiooutput_p.h" +#include "qaudiooutput.h" + #include "mfplayercontrol_p.h" #include "mfevrvideowindowcontrol_p.h" #include "mfvideorenderercontrol_p.h" @@ -83,8 +86,6 @@ MFPlayerSession::MFPlayerSession(MFPlayerControl *playerControl) , m_mediaTypes(0) , m_pendingRate(1) , m_status(QMediaPlayer::NoMedia) - , m_volume(100) - , m_muted(false) , m_audioSampleGrabber(0) , m_audioSampleGrabberNode(0) , m_videoProbeMFT(0) @@ -397,34 +398,36 @@ IMFTopologyNode* MFPlayerSession::addOutputNode(MediaType mediaType, IMFTopology IMFActivate *activate = NULL; if (mediaType == Audio) { - HRESULT hr = MFCreateAudioRendererActivate(&activate); - if (FAILED(hr)) { - qWarning() << "Failed to create audio renderer activate"; - node->Release(); - return NULL; - } + if (m_audioOutput) { + HRESULT hr = MFCreateAudioRendererActivate(&activate); + if (FAILED(hr)) { + qWarning() << "Failed to create audio renderer activate"; + node->Release(); + return NULL; + } - if (!m_audioOutput.id().isEmpty()) { - QString s = QString::fromUtf8(m_audioOutput.id()); - hr = activate->SetString(MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ID, (LPCWSTR)s.utf16()); - } else { - //This is the default one that has been inserted in updateEndpoints(), - //so give the activate a hint that we want to use the device for multimedia playback - //then the media foundation will choose an appropriate one. - - //from MSDN: - //The ERole enumeration defines constants that indicate the role that the system has assigned to an audio endpoint device. - //eMultimedia: Music, movies, narration, and live music recording. - hr = activate->SetUINT32(MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ROLE, eMultimedia); - } + auto id = m_audioOutput->device.id(); + if (!id.isEmpty()) { + QString s = QString::fromUtf8(id); + hr = activate->SetString(MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ID, (LPCWSTR)s.utf16()); + } else { + //This is the default one that has been inserted in updateEndpoints(), + //so give the activate a hint that we want to use the device for multimedia playback + //then the media foundation will choose an appropriate one. + + //from MSDN: + //The ERole enumeration defines constants that indicate the role that the system has assigned to an audio endpoint device. + //eMultimedia: Music, movies, narration, and live music recording. + hr = activate->SetUINT32(MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ROLE, eMultimedia); + } - if (FAILED(hr)) { - qWarning() << "Failed to set attribute for audio device" << m_audioOutput.description(); - activate->Release(); - node->Release(); - return NULL; + if (FAILED(hr)) { + qWarning() << "Failed to set attribute for audio device" << m_audioOutput->device.description(); + activate->Release(); + node->Release(); + return NULL; + } } - } else if (mediaType == Video) { activate = m_videoRendererControl->createActivate(); } else { @@ -1350,12 +1353,7 @@ void MFPlayerSession::scrub(bool enableScrub) } } -int MFPlayerSession::volume() const -{ - return m_volume; -} - -void MFPlayerSession::setVolume(int volume) +void MFPlayerSession::setVolume(float volume) { if (m_volume == volume) return; @@ -1363,13 +1361,6 @@ void MFPlayerSession::setVolume(int volume) if (!m_muted) setVolumeInternal(volume); - - emit volumeChanged(m_volume); -} - -bool MFPlayerSession::isMuted() const -{ - return m_muted; } void MFPlayerSession::setMuted(bool muted) @@ -1379,11 +1370,9 @@ void MFPlayerSession::setMuted(bool muted) m_muted = muted; setVolumeInternal(muted ? 0 : m_volume); - - emit mutedChanged(m_muted); } -void MFPlayerSession::setVolumeInternal(int volume) +void MFPlayerSession::setVolumeInternal(float volume) { if (m_volumeControl) { quint32 channelCount = 0; @@ -1391,9 +1380,8 @@ void MFPlayerSession::setVolumeInternal(int volume) || channelCount == 0) return; - float scaled = volume * 0.01f; for (quint32 i = 0; i < channelCount; ++i) - m_volumeControl->SetChannelVolume(i, scaled); + m_volumeControl->SetChannelVolume(i, volume); } } @@ -1811,15 +1799,23 @@ void MFPlayerSession::clear() } } -bool MFPlayerSession::setAudioOutput(const QAudioDevice &device) +void MFPlayerSession::setAudioOutput(QPlatformAudioOutput *device) { // ### This doesn't yet update the output routing during playback // ie. it currently only works before the first play(). if (m_audioOutput == device) - return true; + return; + + if (m_audioOutput) + m_audioOutput->q->disconnect(this); m_audioOutput = device; - return true; + if (m_audioOutput) { + // #### Implement device changes: connect(m_audioOutput->q, &QAudioOutput::deviceChanged, this, XXXX); + connect(m_audioOutput->q, &QAudioOutput::volumeChanged, this, &MFPlayerSession::setVolume); + connect(m_audioOutput->q, &QAudioOutput::mutedChanged, this, &MFPlayerSession::setMuted); +// connect(m_audioOutput->q, &QAudioOutput::audioRoleChanged, this, &MFPlayerSession::setAudioRole); + } } void MFPlayerSession::setVideoSink(QVideoSink *sink) diff --git a/src/multimedia/platform/windows/player/mfplayersession_p.h b/src/multimedia/platform/windows/player/mfplayersession_p.h index 9f035e4c2..10b424a37 100644 --- a/src/multimedia/platform/windows/player/mfplayersession_p.h +++ b/src/multimedia/platform/windows/player/mfplayersession_p.h @@ -112,10 +112,6 @@ public: void setPosition(qint64 position); qreal playbackRate() const; void setPlaybackRate(qreal rate); - int volume() const; - void setVolume(int volume); - bool isMuted() const; - void setMuted(bool muted); float bufferProgress(); QMediaTimeRange availablePlaybackRanges(); @@ -124,8 +120,7 @@ public: void close(); void clearPlayer() { m_playerControl = nullptr; } - bool setAudioOutput(const QAudioDevice &device); - QAudioDevice audioOutput() const { return m_audioOutput; } + void setAudioOutput(QPlatformAudioOutput *device); QMediaMetaData metaData() const { return m_metaData; } @@ -138,12 +133,14 @@ public: void seekableUpdate(bool seekable) { if (m_playerControl) m_playerControl->handleSeekableUpdate(seekable); } void error(QMediaPlayer::Error error, QString errorString, bool isFatal) { if (m_playerControl) m_playerControl->handleError(error, errorString, isFatal); } void playbackRateChanged(qreal rate) { if (m_playerControl) m_playerControl->playbackRateChanged(rate); } - void volumeChanged(int volume) { if (m_playerControl) m_playerControl->volumeChanged(volume); } - void mutedChanged(bool muted) { if (m_playerControl) m_playerControl->mutedChanged(muted); } void bufferProgressChanged(float percentFilled) { if (m_playerControl) m_playerControl->bufferProgressChanged(percentFilled); } void metaDataChanged() { if (m_playerControl) m_playerControl->metaDataChanged(); } void positionChanged(qint64 position) { if (m_playerControl) m_playerControl->positionChanged(position); } +public Q_SLOTS: + void setVolume(float volume); + void setMuted(bool muted); + Q_SIGNALS: void sessionEvent(IMFMediaEvent *sessionEvent); @@ -224,13 +221,13 @@ private: QMediaPlayer::MediaStatus m_status; bool m_canScrub; - int m_volume; - bool m_muted; + float m_volume = 1.; + bool m_muted = false; - QAudioDevice m_audioOutput; + QPlatformAudioOutput *m_audioOutput = nullptr; QMediaMetaData m_metaData; - void setVolumeInternal(int volume); + void setVolumeInternal(float volume); void createSession(); void setupPlaybackTopology(IMFMediaSource *source, IMFPresentationDescriptor *sourcePD); |