summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2021-05-11 15:49:03 +0200
committerLars Knoll <lars.knoll@qt.io>2021-05-17 10:34:08 +0000
commit718d25264419afd72c1d6ae7d4c335da286b216d (patch)
tree4de50ba2667641e4468365ee0f192520a63e6ab7
parent65d06e5445519e7b8094460e6d1d7983fa8cbaee (diff)
Cleanup the audio decoder architecture
QPlatformAudioDecoder should not be a QObject, instead just have a pointer back to the front-end class. The backend is now also properly owned by the frontend. Get rid of QAudioDecoderPrivate, we don't need it anymore. Fix the audiodecoderbackend autotest and the audiodecoder example. Change-Id: Id9a3368788b5398f37b77be819e8f12947ba045f Reviewed-by: André de la Rocha <andre.rocha@qt.io> Reviewed-by: Lars Knoll <lars.knoll@qt.io>
-rw-r--r--examples/multimedia/audiodecoder/audiodecoder.cpp2
-rw-r--r--src/multimedia/audio/qaudiodecoder.cpp157
-rw-r--r--src/multimedia/audio/qaudiodecoder.h6
-rw-r--r--src/multimedia/platform/gstreamer/audio/qgstreameraudiodecoder.cpp17
-rw-r--r--src/multimedia/platform/gstreamer/audio/qgstreameraudiodecoder_p.h2
-rw-r--r--src/multimedia/platform/gstreamer/qgstreamerintegration.cpp10
-rw-r--r--src/multimedia/platform/gstreamer/qgstreamerintegration_p.h2
-rw-r--r--src/multimedia/platform/qplatformaudiodecoder.cpp67
-rw-r--r--src/multimedia/platform/qplatformaudiodecoder_p.h16
-rw-r--r--src/multimedia/platform/qplatformmediaintegration.cpp15
-rw-r--r--src/multimedia/platform/qplatformmediaintegration_p.h3
-rw-r--r--src/multimedia/platform/windows/decoder/mfaudiodecodercontrol.cpp2
-rw-r--r--src/multimedia/platform/windows/decoder/mfaudiodecodercontrol_p.h2
-rw-r--r--src/multimedia/platform/windows/qwindowsintegration.cpp4
-rw-r--r--src/multimedia/platform/windows/qwindowsintegration_p.h2
-rw-r--r--tests/auto/integration/qaudiodecoderbackend/tst_qaudiodecoderbackend.cpp17
-rw-r--r--tests/auto/unit/mockbackend/qmockaudiodecoder.h2
-rw-r--r--tests/auto/unit/mockbackend/qmockintegration.cpp4
-rw-r--r--tests/auto/unit/mockbackend/qmockintegration_p.h2
19 files changed, 157 insertions, 175 deletions
diff --git a/examples/multimedia/audiodecoder/audiodecoder.cpp b/examples/multimedia/audiodecoder/audiodecoder.cpp
index 7c46be800..401b41bfd 100644
--- a/examples/multimedia/audiodecoder/audiodecoder.cpp
+++ b/examples/multimedia/audiodecoder/audiodecoder.cpp
@@ -99,7 +99,7 @@ AudioDecoder::~AudioDecoder()
void AudioDecoder::setSource(const QString &fileName)
{
- m_decoder.setSource(fileName);
+ m_decoder.setSource(QUrl::fromLocalFile(fileName));
}
void AudioDecoder::start()
diff --git a/src/multimedia/audio/qaudiodecoder.cpp b/src/multimedia/audio/qaudiodecoder.cpp
index 6de7ab285..9c2c3bc36 100644
--- a/src/multimedia/audio/qaudiodecoder.cpp
+++ b/src/multimedia/audio/qaudiodecoder.cpp
@@ -71,91 +71,27 @@ QT_BEGIN_NAMESPACE
\sa QAudioBuffer
*/
-#define Q_DECLARE_NON_CONST_PUBLIC(Class) \
- inline Class* q_func() { return static_cast<Class *>(q_ptr); } \
- friend class Class;
-
-class QAudioDecoderPrivate : public QObjectPrivate
-{
- Q_DECLARE_NON_CONST_PUBLIC(QAudioDecoder)
-
-public:
- QPlatformAudioDecoder *control = nullptr;
- QAudioDecoder::State state = QAudioDecoder::StoppedState;
- QAudioDecoder::Error error = QAudioDecoder::NoError;
- QString errorString;
-
- void _q_stateChanged(QAudioDecoder::State state);
- void _q_error(int error, const QString &errorString);
-};
-
-#undef Q_DECLARE_NON_CONST_PUBLIC
-
-void QAudioDecoderPrivate::_q_stateChanged(QAudioDecoder::State ps)
-{
- Q_Q(QAudioDecoder);
-
- if (ps != state) {
- state = ps;
-
- emit q->stateChanged(ps);
- }
-}
-
-void QAudioDecoderPrivate::_q_error(int error, const QString &errorString)
-{
- Q_Q(QAudioDecoder);
-
- this->error = QAudioDecoder::Error(error);
- this->errorString = errorString;
-
- emit q->error(this->error);
-}
-
/*!
Construct an QAudioDecoder instance with \a parent.
*/
QAudioDecoder::QAudioDecoder(QObject *parent)
- : QObject(*new QAudioDecoderPrivate, parent)
+ : QObject(parent)
{
- Q_D(QAudioDecoder);
-
- d->control = QPlatformMediaIntegration::instance()->createAudioDecoder();
- if (d->control != nullptr) {
- connect(d->control, SIGNAL(stateChanged(QAudioDecoder::State)), SLOT(_q_stateChanged(QAudioDecoder::State)));
- connect(d->control, SIGNAL(error(int,QString)), SLOT(_q_error(int,QString)));
-
- connect(d->control, SIGNAL(formatChanged(QAudioFormat)), SIGNAL(formatChanged(QAudioFormat)));
- connect(d->control, SIGNAL(sourceChanged()), SIGNAL(sourceChanged()));
- connect(d->control, SIGNAL(bufferReady()), this, SIGNAL(bufferReady()));
- connect(d->control ,SIGNAL(bufferAvailableChanged(bool)), this, SIGNAL(bufferAvailableChanged(bool)));
- connect(d->control ,SIGNAL(finished()), this, SIGNAL(finished()));
- connect(d->control ,SIGNAL(positionChanged(qint64)), this, SIGNAL(positionChanged(qint64)));
- connect(d->control ,SIGNAL(durationChanged(qint64)), this, SIGNAL(durationChanged(qint64)));
- } else {
- d->error = NotSupportedError;
- d->errorString = tr("The QAudioDecoder object does not have a valid service");
- }
+ decoder = QPlatformMediaIntegration::instance()->createAudioDecoder(this);
}
/*!
Destroys the audio decoder object.
*/
-QAudioDecoder::~QAudioDecoder()
-{
- Q_D(QAudioDecoder);
-
- if (d->control)
- delete d->control;
-}
+QAudioDecoder::~QAudioDecoder() = default;
/*!
Returns true is audio decoding is supported on this platform.
*/
bool QAudioDecoder::isAvailable() const
{
- return d_func()->control != nullptr;
+ return decoder != nullptr;
}
/*!
@@ -163,7 +99,7 @@ bool QAudioDecoder::isAvailable() const
*/
QAudioDecoder::State QAudioDecoder::state() const
{
- return d_func()->state;
+ return decoder ? decoder->state() : QAudioDecoder::StoppedState;
}
/*!
@@ -171,7 +107,9 @@ QAudioDecoder::State QAudioDecoder::state() const
*/
QAudioDecoder::Error QAudioDecoder::error() const
{
- return d_func()->error;
+ if (!decoder)
+ return NotSupportedError;
+ return decoder->error();
}
/*!
@@ -180,7 +118,9 @@ QAudioDecoder::Error QAudioDecoder::error() const
*/
QString QAudioDecoder::errorString() const
{
- return d_func()->errorString;
+ if (!decoder)
+ return tr("QAudioDecoder not supported.");
+ return decoder->errorString();
}
/*!
@@ -197,20 +137,13 @@ QString QAudioDecoder::errorString() const
*/
void QAudioDecoder::start()
{
- Q_D(QAudioDecoder);
-
- if (d->control == nullptr) {
- QMetaObject::invokeMethod(this, "_q_error", Qt::QueuedConnection,
- Q_ARG(int, QAudioDecoder::NotSupportedError),
- Q_ARG(QString, tr("The QAudioDecoder object does not have a valid service")));
+ if (decoder == nullptr)
return;
- }
// Reset error conditions
- d->error = NoError;
- d->errorString.clear();
+ decoder->clearError();
- d->control->start();
+ decoder->start();
}
/*!
@@ -218,10 +151,8 @@ void QAudioDecoder::start()
*/
void QAudioDecoder::stop()
{
- Q_D(QAudioDecoder);
-
- if (d->control != nullptr)
- d->control->stop();
+ if (decoder != nullptr)
+ decoder->stop();
}
/*!
@@ -231,9 +162,8 @@ void QAudioDecoder::stop()
*/
QUrl QAudioDecoder::source() const
{
- Q_D(const QAudioDecoder);
- if (d->control)
- return d->control->source();
+ if (decoder)
+ return decoder->source();
return QString();
}
@@ -248,10 +178,11 @@ QUrl QAudioDecoder::source() const
*/
void QAudioDecoder::setSource(const QUrl &fileName)
{
- Q_D(QAudioDecoder);
+ if (!decoder)
+ return;
- if (d->control != nullptr)
- d_func()->control->setSource(fileName);
+ decoder->clearError();
+ decoder->setSource(fileName);
}
/*!
@@ -260,9 +191,8 @@ void QAudioDecoder::setSource(const QUrl &fileName)
*/
QIODevice *QAudioDecoder::sourceDevice() const
{
- Q_D(const QAudioDecoder);
- if (d->control)
- return d->control->sourceDevice();
+ if (decoder)
+ return decoder->sourceDevice();
return nullptr;
}
@@ -277,10 +207,8 @@ QIODevice *QAudioDecoder::sourceDevice() const
*/
void QAudioDecoder::setSourceDevice(QIODevice *device)
{
- Q_D(QAudioDecoder);
-
- if (d->control != nullptr)
- d_func()->control->setSourceDevice(device);
+ if (decoder != nullptr)
+ decoder->setSourceDevice(device);
}
/*!
@@ -292,9 +220,8 @@ void QAudioDecoder::setSourceDevice(QIODevice *device)
*/
QAudioFormat QAudioDecoder::audioFormat() const
{
- Q_D(const QAudioDecoder);
- if (d->control)
- return d->control->audioFormat();
+ if (decoder)
+ return decoder->audioFormat();
return QAudioFormat();
}
@@ -316,13 +243,11 @@ QAudioFormat QAudioDecoder::audioFormat() const
*/
void QAudioDecoder::setAudioFormat(const QAudioFormat &format)
{
- Q_D(QAudioDecoder);
-
if (state() != QAudioDecoder::StoppedState)
return;
- if (d->control != nullptr)
- d_func()->control->setAudioFormat(format);
+ if (decoder != nullptr)
+ decoder->setAudioFormat(format);
}
/*!
@@ -332,9 +257,8 @@ void QAudioDecoder::setAudioFormat(const QAudioFormat &format)
*/
bool QAudioDecoder::bufferAvailable() const
{
- Q_D(const QAudioDecoder);
- if (d->control)
- return d->control->bufferAvailable();
+ if (decoder)
+ return decoder->bufferAvailable();
return false;
}
@@ -345,9 +269,8 @@ bool QAudioDecoder::bufferAvailable() const
qint64 QAudioDecoder::position() const
{
- Q_D(const QAudioDecoder);
- if (d->control)
- return d->control->position();
+ if (decoder)
+ return decoder->position();
return -1;
}
@@ -358,9 +281,8 @@ qint64 QAudioDecoder::position() const
qint64 QAudioDecoder::duration() const
{
- Q_D(const QAudioDecoder);
- if (d->control)
- return d->control->duration();
+ if (decoder)
+ return decoder->duration();
return -1;
}
@@ -376,11 +298,8 @@ qint64 QAudioDecoder::duration() const
QAudioBuffer QAudioDecoder::read() const
{
- Q_D(const QAudioDecoder);
-
- if (d->control) {
- return d->control->read();
- }
+ if (decoder)
+ return decoder->read();
return QAudioBuffer();
}
diff --git a/src/multimedia/audio/qaudiodecoder.h b/src/multimedia/audio/qaudiodecoder.h
index b3f7c6bdc..9b7c360d5 100644
--- a/src/multimedia/audio/qaudiodecoder.h
+++ b/src/multimedia/audio/qaudiodecoder.h
@@ -47,7 +47,7 @@
QT_BEGIN_NAMESPACE
-class QAudioDecoderPrivate;
+class QPlatformAudioDecoder;
class Q_MULTIMEDIA_EXPORT QAudioDecoder : public QObject
{
Q_OBJECT
@@ -120,9 +120,7 @@ Q_SIGNALS:
private:
Q_DISABLE_COPY(QAudioDecoder)
- Q_DECLARE_PRIVATE(QAudioDecoder)
- Q_PRIVATE_SLOT(d_func(), void _q_stateChanged(QAudioDecoder::State))
- Q_PRIVATE_SLOT(d_func(), void _q_error(int, const QString &))
+ QPlatformAudioDecoder *decoder;
};
QT_END_NAMESPACE
diff --git a/src/multimedia/platform/gstreamer/audio/qgstreameraudiodecoder.cpp b/src/multimedia/platform/gstreamer/audio/qgstreameraudiodecoder.cpp
index 0f5a0ee0a..817e168bf 100644
--- a/src/multimedia/platform/gstreamer/audio/qgstreameraudiodecoder.cpp
+++ b/src/multimedia/platform/gstreamer/audio/qgstreameraudiodecoder.cpp
@@ -73,7 +73,7 @@ typedef enum {
-QGstreamerAudioDecoder::QGstreamerAudioDecoder(QObject *parent)
+QGstreamerAudioDecoder::QGstreamerAudioDecoder(QAudioDecoder *parent)
: QPlatformAudioDecoder(parent),
m_playbin(GST_PIPELINE_CAST(QGstElement("playbin", "playbin").element()))
{
@@ -352,6 +352,7 @@ void QGstreamerAudioDecoder::start()
m_pendingState = QAudioDecoder::DecodingState;
if (m_playbin.setState(GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) {
qWarning() << "GStreamer; Unable to start decoding process";
+ m_playbin.dumpGraph("failed");
m_pendingState = m_state = QAudioDecoder::StoppedState;
emit stateChanged(m_state);
@@ -475,19 +476,19 @@ void QGstreamerAudioDecoder::processInvalidMedia(QAudioDecoder::Error errorCode,
GstFlowReturn QGstreamerAudioDecoder::new_sample(GstAppSink *, gpointer user_data)
{
// "Note that the preroll buffer will also be returned as the first buffer when calling gst_app_sink_pull_buffer()."
- QGstreamerAudioDecoder *control = reinterpret_cast<QGstreamerAudioDecoder*>(user_data);
+ QGstreamerAudioDecoder *decoder = reinterpret_cast<QGstreamerAudioDecoder*>(user_data);
int buffersAvailable;
{
- QMutexLocker locker(&control->m_buffersMutex);
- buffersAvailable = control->m_buffersAvailable;
- control->m_buffersAvailable++;
- Q_ASSERT(control->m_buffersAvailable <= MAX_BUFFERS_IN_QUEUE);
+ QMutexLocker locker(&decoder->m_buffersMutex);
+ buffersAvailable = decoder->m_buffersAvailable;
+ decoder->m_buffersAvailable++;
+ Q_ASSERT(decoder->m_buffersAvailable <= MAX_BUFFERS_IN_QUEUE);
}
if (!buffersAvailable)
- QMetaObject::invokeMethod(control, "bufferAvailableChanged", Qt::QueuedConnection, Q_ARG(bool, true));
- QMetaObject::invokeMethod(control, "bufferReady", Qt::QueuedConnection);
+ decoder->bufferAvailableChanged(true);
+ decoder->bufferReady();
return GST_FLOW_OK;
}
diff --git a/src/multimedia/platform/gstreamer/audio/qgstreameraudiodecoder_p.h b/src/multimedia/platform/gstreamer/audio/qgstreameraudiodecoder_p.h
index 22d024801..be2343916 100644
--- a/src/multimedia/platform/gstreamer/audio/qgstreameraudiodecoder_p.h
+++ b/src/multimedia/platform/gstreamer/audio/qgstreameraudiodecoder_p.h
@@ -78,7 +78,7 @@ class QGstreamerAudioDecoder
Q_OBJECT
public:
- QGstreamerAudioDecoder(QObject *parent);
+ QGstreamerAudioDecoder(QAudioDecoder *parent);
virtual ~QGstreamerAudioDecoder();
// QAudioDecoder interface
diff --git a/src/multimedia/platform/gstreamer/qgstreamerintegration.cpp b/src/multimedia/platform/gstreamer/qgstreamerintegration.cpp
index fec548162..ba1baa641 100644
--- a/src/multimedia/platform/gstreamer/qgstreamerintegration.cpp
+++ b/src/multimedia/platform/gstreamer/qgstreamerintegration.cpp
@@ -54,6 +54,8 @@ QT_BEGIN_NAMESPACE
QGstreamerIntegration::QGstreamerIntegration()
{
gst_init(nullptr, nullptr);
+ m_devices = new QGstreamerMediaDevices();
+ m_formatsInfo = new QGstreamerFormatInfo();
}
QGstreamerIntegration::~QGstreamerIntegration()
@@ -64,21 +66,17 @@ QGstreamerIntegration::~QGstreamerIntegration()
QPlatformMediaDevices *QGstreamerIntegration::devices()
{
- if (!m_devices)
- m_devices = new QGstreamerMediaDevices();
return m_devices;
}
QPlatformMediaFormatInfo *QGstreamerIntegration::formatInfo()
{
- if (!m_formatsInfo)
- m_formatsInfo = new QGstreamerFormatInfo();
return m_formatsInfo;
}
-QPlatformAudioDecoder *QGstreamerIntegration::createAudioDecoder()
+QPlatformAudioDecoder *QGstreamerIntegration::createAudioDecoder(QAudioDecoder *decoder)
{
- return new QGstreamerAudioDecoder(nullptr);
+ return new QGstreamerAudioDecoder(decoder);
}
QPlatformMediaCaptureSession *QGstreamerIntegration::createCaptureSession(QMediaRecorder::CaptureMode mode)
diff --git a/src/multimedia/platform/gstreamer/qgstreamerintegration_p.h b/src/multimedia/platform/gstreamer/qgstreamerintegration_p.h
index 7781b538e..6606cc356 100644
--- a/src/multimedia/platform/gstreamer/qgstreamerintegration_p.h
+++ b/src/multimedia/platform/gstreamer/qgstreamerintegration_p.h
@@ -69,7 +69,7 @@ public:
QPlatformMediaDevices *devices() override;
QPlatformMediaFormatInfo *formatInfo() override;
- QPlatformAudioDecoder *createAudioDecoder() override;
+ QPlatformAudioDecoder *createAudioDecoder(QAudioDecoder *decoder) override;
QPlatformMediaCaptureSession *createCaptureSession(QMediaRecorder::CaptureMode mode) override;
QPlatformMediaPlayer *createPlayer(QMediaPlayer *player) override;
QPlatformCamera *createCamera(QCamera *) override;
diff --git a/src/multimedia/platform/qplatformaudiodecoder.cpp b/src/multimedia/platform/qplatformaudiodecoder.cpp
index 2b29fd1ac..b7da0a304 100644
--- a/src/multimedia/platform/qplatformaudiodecoder.cpp
+++ b/src/multimedia/platform/qplatformaudiodecoder.cpp
@@ -38,6 +38,7 @@
****************************************************************************/
#include "qplatformaudiodecoder_p.h"
+#include "qthread.h"
QT_BEGIN_NAMESPACE
@@ -59,8 +60,9 @@ QT_BEGIN_NAMESPACE
/*!
Constructs a new audio decoder control with the given \a parent.
*/
-QPlatformAudioDecoder::QPlatformAudioDecoder(QObject *parent)
- : QObject(parent)
+QPlatformAudioDecoder::QPlatformAudioDecoder(QAudioDecoder *parent)
+ : QObject(parent),
+ q(parent)
{
}
@@ -70,6 +72,14 @@ QPlatformAudioDecoder::QPlatformAudioDecoder(QObject *parent)
Returns the state of a player control.
*/
+void QPlatformAudioDecoder::stateChanged(QAudioDecoder::State newState)
+{
+ if (m_state == newState)
+ return;
+ m_state = newState;
+ emit q->stateChanged(newState);
+}
+
/*!
\fn QPlatformAudioDecoder::stateChanged(QAudioDecoder::State newState)
@@ -134,24 +144,41 @@ QPlatformAudioDecoder::QPlatformAudioDecoder(QObject *parent)
Signals that an \a error has occurred. The \a errorString provides a more detailed explanation.
*/
+void QPlatformAudioDecoder::error(int error, const QString &errorString)
+{
+ if (error == m_error && errorString == m_errorString)
+ return;
+ m_error = QAudioDecoder::Error(error);
+ m_errorString = errorString;
+
+ emit q->error(m_error);
+}
+
/*!
\fn QPlatformAudioDecoder::bufferAvailableChanged(bool available)
Signals that the bufferAvailable property has changed to \a available.
*/
+void QPlatformAudioDecoder::bufferAvailableChanged(bool available)
+{
+ if (QThread::currentThread() != q->thread())
+ QMetaObject::invokeMethod(q, "bufferAvailableChanged", Qt::QueuedConnection, Q_ARG(bool, available));
+ else
+ emit q->bufferAvailableChanged(available);
+}
/*!
\fn QPlatformAudioDecoder::bufferReady()
Signals that a new buffer is ready for reading.
*/
-
-/*!
- \fn QPlatformAudioDecoder::bufferAvailable() const
-
- Returns true if a buffer is available to be read,
- and false otherwise.
-*/
+void QPlatformAudioDecoder::bufferReady()
+{
+ if (QThread::currentThread() != q->thread())
+ QMetaObject::invokeMethod(q, "bufferReady", Qt::QueuedConnection);
+ else
+ emit q->bufferReady();
+}
/*!
\fn QPlatformAudioDecoder::sourceChanged()
@@ -160,6 +187,10 @@ QPlatformAudioDecoder::QPlatformAudioDecoder(QObject *parent)
\sa source(), sourceDevice()
*/
+void QPlatformAudioDecoder::sourceChanged()
+{
+ emit q->sourceChanged();
+}
/*!
\fn QPlatformAudioDecoder::formatChanged(const QAudioFormat &format)
@@ -168,6 +199,10 @@ QPlatformAudioDecoder::QPlatformAudioDecoder(QObject *parent)
\sa audioFormat(), setAudioFormat()
*/
+void QPlatformAudioDecoder::formatChanged(const QAudioFormat &format)
+{
+ emit q->formatChanged(format);
+}
/*!
\fn void QPlatformAudioDecoder::finished()
@@ -177,6 +212,10 @@ QPlatformAudioDecoder::QPlatformAudioDecoder(QObject *parent)
\sa start(), stop(), error()
*/
+void QPlatformAudioDecoder::finished()
+{
+ emit q->finished();
+}
/*!
\fn void QPlatformAudioDecoder::positionChanged(qint64 position)
@@ -185,6 +224,10 @@ QPlatformAudioDecoder::QPlatformAudioDecoder(QObject *parent)
\sa durationChanged()
*/
+void QPlatformAudioDecoder::positionChanged(qint64 position)
+{
+ q->positionChanged(position);
+}
/*!
\fn void QPlatformAudioDecoder::durationChanged(qint64 duration)
@@ -193,6 +236,10 @@ QPlatformAudioDecoder::QPlatformAudioDecoder(QObject *parent)
\sa positionChanged()
*/
+void QPlatformAudioDecoder::durationChanged(qint64 duration)
+{
+ q->durationChanged(duration);
+}
/*!
\fn QPlatformAudioDecoder::audioFormat() const
@@ -237,5 +284,3 @@ QPlatformAudioDecoder::QPlatformAudioDecoder(QObject *parent)
*/
QT_END_NAMESPACE
-
-#include "moc_qplatformaudiodecoder_p.cpp"
diff --git a/src/multimedia/platform/qplatformaudiodecoder_p.h b/src/multimedia/platform/qplatformaudiodecoder_p.h
index 09e3a02b4..91877e647 100644
--- a/src/multimedia/platform/qplatformaudiodecoder_p.h
+++ b/src/multimedia/platform/qplatformaudiodecoder_p.h
@@ -56,6 +56,7 @@
#include <QtCore/qpair.h>
#include <QtMultimedia/qaudiobuffer.h>
+#include <QtMultimedia/qaudiodecoder.h>
QT_BEGIN_NAMESPACE
@@ -65,7 +66,7 @@ class Q_MULTIMEDIA_EXPORT QPlatformAudioDecoder : public QObject
Q_OBJECT
public:
- virtual QAudioDecoder::State state() const = 0;
+ virtual QAudioDecoder::State state() const { return m_state; }
virtual QUrl source() const = 0;
virtual void setSource(const QUrl &fileName) = 0;
@@ -85,12 +86,12 @@ public:
virtual qint64 position() const = 0;
virtual qint64 duration() const = 0;
-Q_SIGNALS:
void stateChanged(QAudioDecoder::State newState);
void formatChanged(const QAudioFormat &format);
void sourceChanged();
void error(int error, const QString &errorString);
+ void clearError() { error(QAudioDecoder::NoError, QString()); }
void bufferReady();
void bufferAvailableChanged(bool available);
@@ -99,8 +100,17 @@ Q_SIGNALS:
void positionChanged(qint64 position);
void durationChanged(qint64 duration);
+ QAudioDecoder::Error error() const { return m_error; }
+ QString errorString() const { return m_errorString; }
+
protected:
- explicit QPlatformAudioDecoder(QObject *parent = nullptr);
+ explicit QPlatformAudioDecoder(QAudioDecoder *parent);
+private:
+ QAudioDecoder *q = nullptr;
+
+ QAudioDecoder::State m_state = QAudioDecoder::StoppedState;
+ QAudioDecoder::Error m_error = QAudioDecoder::NoError;
+ QString m_errorString;
};
QT_END_NAMESPACE
diff --git a/src/multimedia/platform/qplatformmediaintegration.cpp b/src/multimedia/platform/qplatformmediaintegration.cpp
index dd9843f2d..dbfb5eca7 100644
--- a/src/multimedia/platform/qplatformmediaintegration.cpp
+++ b/src/multimedia/platform/qplatformmediaintegration.cpp
@@ -39,6 +39,8 @@
#include <qtmultimediaglobal_p.h>
#include "qplatformmediaintegration_p.h"
+#include <qatomic.h>
+#include <qmutex.h>
#if QT_CONFIG(gstreamer)
#include <private/qgstreamerintegration_p.h>
@@ -66,22 +68,27 @@ namespace {
struct Holder {
~Holder()
{
+ QMutexLocker locker(&mutex);
delete nativeInstance;
nativeInstance = nullptr;
instance = nullptr;
}
+ QBasicMutex mutex;
QPlatformMediaIntegration *instance = nullptr;
- QPlatformMediaIntegration *nativeInstance = nullptr;
+ QAtomicPointer<QPlatformMediaIntegration> nativeInstance = nullptr;
} holder;
}
QPlatformMediaIntegration *QPlatformMediaIntegration::instance()
{
- if (!holder.nativeInstance)
- holder.nativeInstance = new PlatformIntegration;
+ if (!holder.nativeInstance.loadRelaxed()) {
+ QMutexLocker locker(&holder.mutex);
+ if (!holder.nativeInstance.loadAcquire())
+ holder.nativeInstance.storeRelease(new PlatformIntegration);
+ }
if (!holder.instance)
- holder.instance = holder.nativeInstance;
+ holder.instance = holder.nativeInstance.loadRelaxed();
return holder.instance;
}
diff --git a/src/multimedia/platform/qplatformmediaintegration_p.h b/src/multimedia/platform/qplatformmediaintegration_p.h
index 0a089f9dc..1bd943b8d 100644
--- a/src/multimedia/platform/qplatformmediaintegration_p.h
+++ b/src/multimedia/platform/qplatformmediaintegration_p.h
@@ -56,6 +56,7 @@
QT_BEGIN_NAMESPACE
class QMediaPlayer;
+class QAudioDecoder;
class QCamera;
class QMediaEncoder;
class QCameraImageCapture;
@@ -84,7 +85,7 @@ public:
virtual QPlatformMediaDevices *devices() = 0;
virtual QPlatformMediaFormatInfo *formatInfo() = 0;
- virtual QPlatformAudioDecoder *createAudioDecoder() { return nullptr; }
+ virtual QPlatformAudioDecoder *createAudioDecoder(QAudioDecoder *) { return nullptr; }
// ### get rid of the mode once refactoring is done
virtual QPlatformMediaCaptureSession *createCaptureSession(QMediaRecorder::CaptureMode /*mode*/ = QMediaRecorder::AudioAndVideo) { return nullptr; }
virtual QPlatformMediaPlayer *createPlayer(QMediaPlayer *) { return nullptr; }
diff --git a/src/multimedia/platform/windows/decoder/mfaudiodecodercontrol.cpp b/src/multimedia/platform/windows/decoder/mfaudiodecodercontrol.cpp
index 5a07d7e08..953281f31 100644
--- a/src/multimedia/platform/windows/decoder/mfaudiodecodercontrol.cpp
+++ b/src/multimedia/platform/windows/decoder/mfaudiodecodercontrol.cpp
@@ -40,7 +40,7 @@
#include "Wmcodecdsp.h"
#include "mfaudiodecodercontrol_p.h"
-MFAudioDecoderControl::MFAudioDecoderControl(QObject *parent)
+MFAudioDecoderControl::MFAudioDecoderControl(QAudioDecoder *parent)
: QPlatformAudioDecoder(parent)
, m_decoderSourceReader(new MFDecoderSourceReader)
, m_sourceResolver(new SourceResolver)
diff --git a/src/multimedia/platform/windows/decoder/mfaudiodecodercontrol_p.h b/src/multimedia/platform/windows/decoder/mfaudiodecodercontrol_p.h
index 563b9efb6..56edb95c0 100644
--- a/src/multimedia/platform/windows/decoder/mfaudiodecodercontrol_p.h
+++ b/src/multimedia/platform/windows/decoder/mfaudiodecodercontrol_p.h
@@ -61,7 +61,7 @@ class MFAudioDecoderControl : public QPlatformAudioDecoder
{
Q_OBJECT
public:
- MFAudioDecoderControl(QObject *parent = 0);
+ MFAudioDecoderControl(QAudioDecoder *parent);
~MFAudioDecoderControl();
QAudioDecoder::State state() const;
diff --git a/src/multimedia/platform/windows/qwindowsintegration.cpp b/src/multimedia/platform/windows/qwindowsintegration.cpp
index a399d3be8..9180fa4d2 100644
--- a/src/multimedia/platform/windows/qwindowsintegration.cpp
+++ b/src/multimedia/platform/windows/qwindowsintegration.cpp
@@ -93,9 +93,9 @@ QPlatformMediaCaptureSession *QWindowsIntegration::createCaptureSession(QMediaRe
return new QWindowsMediaCaptureService();
}
-QPlatformAudioDecoder *QWindowsIntegration::createAudioDecoder()
+QPlatformAudioDecoder *QWindowsIntegration::createAudioDecoder(QAudioDecoder *decoder)
{
- return new MFAudioDecoderControl;
+ return new MFAudioDecoderControl(decoder);
}
QPlatformMediaPlayer *QWindowsIntegration::createPlayer(QMediaPlayer *parent)
diff --git a/src/multimedia/platform/windows/qwindowsintegration_p.h b/src/multimedia/platform/windows/qwindowsintegration_p.h
index 98b159206..c0fb6d4a6 100644
--- a/src/multimedia/platform/windows/qwindowsintegration_p.h
+++ b/src/multimedia/platform/windows/qwindowsintegration_p.h
@@ -72,7 +72,7 @@ public:
QPlatformMediaCaptureSession *createCaptureSession(QMediaRecorder::CaptureMode) override;
- QPlatformAudioDecoder *createAudioDecoder() override;
+ QPlatformAudioDecoder *createAudioDecoder(QAudioDecoder *decoder) override;
QPlatformMediaPlayer *createPlayer(QMediaPlayer *parent) override;
QPlatformCamera *createCamera(QCamera *camera) override;
QPlatformMediaEncoder *createEncoder(QMediaEncoder *encoder) override;
diff --git a/tests/auto/integration/qaudiodecoderbackend/tst_qaudiodecoderbackend.cpp b/tests/auto/integration/qaudiodecoderbackend/tst_qaudiodecoderbackend.cpp
index a59bd1701..b3ccb0a10 100644
--- a/tests/auto/integration/qaudiodecoderbackend/tst_qaudiodecoderbackend.cpp
+++ b/tests/auto/integration/qaudiodecoderbackend/tst_qaudiodecoderbackend.cpp
@@ -107,10 +107,11 @@ void tst_QAudioDecoderBackend::fileTest()
// Test local file
QFileInfo fileInfo(QFINDTESTDATA(TEST_FILE_NAME));
- d.setSource(fileInfo.absoluteFilePath());
+ QUrl url = QUrl::fromLocalFile(fileInfo.absoluteFilePath());
+ d.setSource(url);
QVERIFY(d.state() == QAudioDecoder::StoppedState);
QVERIFY(!d.bufferAvailable());
- QCOMPARE(d.source(), fileInfo.absoluteFilePath());
+ QCOMPARE(d.source(), url);
QSignalSpy readySpy(&d, SIGNAL(bufferReady()));
QSignalSpy bufferChangedSpy(&d, SIGNAL(bufferAvailableChanged(bool)));
@@ -284,10 +285,11 @@ void tst_QAudioDecoderBackend::unsupportedFileTest()
// Test local file
QFileInfo fileInfo(QFINDTESTDATA(TEST_UNSUPPORTED_FILE_NAME));
- d.setSource(fileInfo.absoluteFilePath());
+ QUrl url = QUrl::fromLocalFile(fileInfo.absoluteFilePath());
+ d.setSource(url);
QVERIFY(d.state() == QAudioDecoder::StoppedState);
QVERIFY(!d.bufferAvailable());
- QCOMPARE(d.source(), fileInfo.absoluteFilePath());
+ QCOMPARE(d.source(), url);
QSignalSpy readySpy(&d, SIGNAL(bufferReady()));
QSignalSpy bufferChangedSpy(&d, SIGNAL(bufferAvailableChanged(bool)));
@@ -357,15 +359,16 @@ void tst_QAudioDecoderBackend::corruptedFileTest()
QVERIFY(d.state() == QAudioDecoder::StoppedState);
QVERIFY(d.bufferAvailable() == false);
- QCOMPARE(d.source(), QString(""));
+ QCOMPARE(d.source(), QUrl());
QVERIFY(d.audioFormat() == QAudioFormat());
// Test local file
QFileInfo fileInfo(QFINDTESTDATA(TEST_CORRUPTED_FILE_NAME));
- d.setSource(fileInfo.absoluteFilePath());
+ QUrl url = QUrl::fromLocalFile(fileInfo.absoluteFilePath());
+ d.setSource(url);
QVERIFY(d.state() == QAudioDecoder::StoppedState);
QVERIFY(!d.bufferAvailable());
- QCOMPARE(d.source(), fileInfo.absoluteFilePath());
+ QCOMPARE(d.source(), url);
QSignalSpy readySpy(&d, SIGNAL(bufferReady()));
QSignalSpy bufferChangedSpy(&d, SIGNAL(bufferAvailableChanged(bool)));
diff --git a/tests/auto/unit/mockbackend/qmockaudiodecoder.h b/tests/auto/unit/mockbackend/qmockaudiodecoder.h
index 1e1dca514..24cd98756 100644
--- a/tests/auto/unit/mockbackend/qmockaudiodecoder.h
+++ b/tests/auto/unit/mockbackend/qmockaudiodecoder.h
@@ -47,7 +47,7 @@ class QMockAudioDecoder : public QPlatformAudioDecoder
Q_OBJECT
public:
- QMockAudioDecoder(QObject *parent = 0)
+ QMockAudioDecoder(QAudioDecoder *parent = 0)
: QPlatformAudioDecoder(parent)
, mState(QAudioDecoder::StoppedState)
, mDevice(0)
diff --git a/tests/auto/unit/mockbackend/qmockintegration.cpp b/tests/auto/unit/mockbackend/qmockintegration.cpp
index 698ecfed9..a9135f175 100644
--- a/tests/auto/unit/mockbackend/qmockintegration.cpp
+++ b/tests/auto/unit/mockbackend/qmockintegration.cpp
@@ -66,12 +66,12 @@ QPlatformMediaDevices *QMockIntegration::devices()
return m_devices;
}
-QPlatformAudioDecoder *QMockIntegration::createAudioDecoder()
+QPlatformAudioDecoder *QMockIntegration::createAudioDecoder(QAudioDecoder *decoder)
{
if (m_flags & NoAudioDecoderInterface)
m_lastAudioDecoderControl = nullptr;
else
- m_lastAudioDecoderControl = new QMockAudioDecoder;
+ m_lastAudioDecoderControl = new QMockAudioDecoder(decoder);
return m_lastAudioDecoderControl;
}
diff --git a/tests/auto/unit/mockbackend/qmockintegration_p.h b/tests/auto/unit/mockbackend/qmockintegration_p.h
index 11ca8eccc..d0c14523d 100644
--- a/tests/auto/unit/mockbackend/qmockintegration_p.h
+++ b/tests/auto/unit/mockbackend/qmockintegration_p.h
@@ -71,7 +71,7 @@ public:
QPlatformMediaDevices *devices() override;
QPlatformMediaFormatInfo *formatInfo() override { return nullptr; }
- QPlatformAudioDecoder *createAudioDecoder() override;
+ QPlatformAudioDecoder *createAudioDecoder(QAudioDecoder *decoder) override;
QPlatformMediaPlayer *createPlayer(QMediaPlayer *) override;
QPlatformCamera *createCamera(QCamera *) override;
QPlatformMediaEncoder *createEncoder(QMediaEncoder *) override;