summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2021-06-14 15:42:59 +0200
committerLars Knoll <lars.knoll@qt.io>2021-06-17 23:13:28 +0200
commitaf1182b5e29afa0cd69f929d54da224019707214 (patch)
tree45c04b63af92bc43d7125494284a2347c9ae7dab /src
parent0bd8c0a36e8ccff03af7f6990298238455443ec4 (diff)
Fix the QAudioDecoder API
Adjust API after code review. Remove the audioFormat property. QAudioDecoder will now always decode to the native format used in the encoded file. QAudioBuffer will have the correct format set, and it's up to the app to handle this correctly. Remove state() and replace by isDecoding(). Change-Id: I6f2ac375d98b2d7c36aebaa729599f78699b1c7b Reviewed-by: André de la Rocha <andre.rocha@qt.io> Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io> Reviewed-by: Doris Verria <doris.verria@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/multimedia/audio/qaudiodecoder.cpp56
-rw-r--r--src/multimedia/audio/qaudiodecoder.h21
-rw-r--r--src/multimedia/platform/darwin/audio/avfaudiodecoder.mm51
-rw-r--r--src/multimedia/platform/darwin/audio/avfaudiodecoder_p.h10
-rw-r--r--src/multimedia/platform/gstreamer/audio/qgstreameraudiodecoder.cpp53
-rw-r--r--src/multimedia/platform/gstreamer/audio/qgstreameraudiodecoder_p.h11
-rw-r--r--src/multimedia/platform/gstreamer/common/qgstutils.cpp10
-rw-r--r--src/multimedia/platform/gstreamer/common/qgstutils_p.h1
-rw-r--r--src/multimedia/platform/qplatformaudiodecoder.cpp36
-rw-r--r--src/multimedia/platform/qplatformaudiodecoder_p.h16
-rw-r--r--src/multimedia/platform/windows/decoder/mfaudiodecodercontrol.cpp235
-rw-r--r--src/multimedia/platform/windows/decoder/mfaudiodecodercontrol_p.h10
-rw-r--r--src/multimedia/platform/windows/decoder/mfdecodersourcereader.cpp9
-rw-r--r--src/multimedia/platform/windows/decoder/mfdecodersourcereader_p.h2
14 files changed, 93 insertions, 428 deletions
diff --git a/src/multimedia/audio/qaudiodecoder.cpp b/src/multimedia/audio/qaudiodecoder.cpp
index 9c2c3bc36..8b8db59ba 100644
--- a/src/multimedia/audio/qaudiodecoder.cpp
+++ b/src/multimedia/audio/qaudiodecoder.cpp
@@ -89,17 +89,17 @@ QAudioDecoder::~QAudioDecoder() = default;
/*!
Returns true is audio decoding is supported on this platform.
*/
-bool QAudioDecoder::isAvailable() const
+bool QAudioDecoder::isSupported() const
{
return decoder != nullptr;
}
/*!
- Returns the current state of the audio decoder.
+ Returns true if the decoder is currently running and decoding audio data.
*/
-QAudioDecoder::State QAudioDecoder::state() const
+bool QAudioDecoder::isDecoding() const
{
- return decoder ? decoder->state() : QAudioDecoder::StoppedState;
+ return decoder && decoder->isDecoding();
}
/*!
@@ -151,8 +151,10 @@ void QAudioDecoder::start()
*/
void QAudioDecoder::stop()
{
- if (decoder != nullptr)
- decoder->stop();
+ if (!decoder)
+ return;
+
+ decoder->stop();
}
/*!
@@ -207,47 +209,9 @@ QIODevice *QAudioDecoder::sourceDevice() const
*/
void QAudioDecoder::setSourceDevice(QIODevice *device)
{
- if (decoder != nullptr)
- decoder->setSourceDevice(device);
-}
-
-/*!
- Returns the current audio format of the decoded stream.
-
- Any buffers returned should have this format.
-
- \sa setAudioFormat(), formatChanged()
-*/
-QAudioFormat QAudioDecoder::audioFormat() const
-{
- if (decoder)
- return decoder->audioFormat();
- return QAudioFormat();
-}
-
-/*!
- Set the desired audio format for decoded samples to \a format.
-
- This property can only be set while the decoder is stopped.
- Setting this property at other times will be ignored.
-
- If the decoder does not support this format, \l error() will
- be set to \c FormatError.
-
- If you do not specify a format, the format of the decoded
- audio itself will be used. Otherwise, some format conversion
- will be applied.
-
- If you wish to reset the decoded format to that of the original
- audio file, you can specify an invalid \a format.
-*/
-void QAudioDecoder::setAudioFormat(const QAudioFormat &format)
-{
- if (state() != QAudioDecoder::StoppedState)
+ if (!decoder)
return;
-
- if (decoder != nullptr)
- decoder->setAudioFormat(format);
+ decoder->setSourceDevice(device);
}
/*!
diff --git a/src/multimedia/audio/qaudiodecoder.h b/src/multimedia/audio/qaudiodecoder.h
index 9dd257cc9..465bb3974 100644
--- a/src/multimedia/audio/qaudiodecoder.h
+++ b/src/multimedia/audio/qaudiodecoder.h
@@ -52,18 +52,11 @@ class Q_MULTIMEDIA_EXPORT QAudioDecoder : public QObject
{
Q_OBJECT
Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
- Q_PROPERTY(State state READ state NOTIFY stateChanged)
+ Q_PROPERTY(bool isDecoding READ isDecoding NOTIFY isDecodingChanged)
Q_PROPERTY(QString error READ errorString)
Q_PROPERTY(bool bufferAvailable READ bufferAvailable NOTIFY bufferAvailableChanged)
public:
- enum State
- {
- StoppedState,
- DecodingState
- };
- Q_ENUM(State)
-
enum Error
{
NoError,
@@ -77,8 +70,8 @@ public:
explicit QAudioDecoder(QObject *parent = nullptr);
~QAudioDecoder();
- bool isAvailable() const;
- State state() const;
+ bool isSupported() const;
+ bool isDecoding() const;
QUrl source() const;
void setSource(const QUrl &fileName);
@@ -86,9 +79,6 @@ public:
QIODevice* sourceDevice() const;
void setSourceDevice(QIODevice *device);
- QAudioFormat audioFormat() const;
- void setAudioFormat(const QAudioFormat &format);
-
Error error() const;
QString errorString() const;
@@ -106,9 +96,7 @@ Q_SIGNALS:
void bufferAvailableChanged(bool);
void bufferReady();
void finished();
-
- void stateChanged(QAudioDecoder::State newState);
- void formatChanged(const QAudioFormat &format);
+ void isDecodingChanged(bool);
void error(QAudioDecoder::Error error);
@@ -124,7 +112,6 @@ private:
QT_END_NAMESPACE
-Q_MEDIA_ENUM_DEBUG(QAudioDecoder, State)
Q_MEDIA_ENUM_DEBUG(QAudioDecoder, Error)
#endif // QAUDIODECODER_H
diff --git a/src/multimedia/platform/darwin/audio/avfaudiodecoder.mm b/src/multimedia/platform/darwin/audio/avfaudiodecoder.mm
index 2ff872212..ecea99f74 100644
--- a/src/multimedia/platform/darwin/audio/avfaudiodecoder.mm
+++ b/src/multimedia/platform/darwin/audio/avfaudiodecoder.mm
@@ -90,7 +90,7 @@ QT_USE_NAMESPACE
return;
const AudioStreamBasicDescription* const asbd = CMAudioFormatDescriptionGetStreamBasicDescription(formatDescription);
QAudioFormat qtFormat = CoreAudioUtils::toQAudioFormat(*asbd);
- if (!qtFormat.isValid() || qtFormat != m_decoder->audioFormat())
+ if (!qtFormat.isValid())
return;
// Get the required size to allocate to audioBufferList
@@ -314,7 +314,7 @@ void AVFAudioDecoder::setSourceDevice(QIODevice *device)
void AVFAudioDecoder::start()
{
Q_ASSERT(!m_buffersAvailable);
- if (m_state != QAudioDecoder::StoppedState)
+ if (isDecoding())
return;
if (m_position != -1) {
@@ -348,16 +348,13 @@ void AVFAudioDecoder::start()
];
if (m_device && m_loadingSource) {
- m_state = QAudioDecoder::DecodingState;
- emit stateChanged(m_state);
+ setIsDecoding(true);
return;
}
}
void AVFAudioDecoder::stop()
{
- QAudioDecoder::State oldState = m_state;
- m_state = QAudioDecoder::StoppedState;
if (m_asset)
[m_asset cancelLoading];
if (m_reader)
@@ -375,21 +372,7 @@ void AVFAudioDecoder::stop()
m_duration = -1;
emit durationChanged(m_duration);
}
- if (m_state != oldState)
- emit stateChanged(m_state);
-}
-
-QAudioFormat AVFAudioDecoder::audioFormat() const
-{
- return m_format;
-}
-
-void AVFAudioDecoder::setAudioFormat(const QAudioFormat &format)
-{
- if (m_format != format) {
- m_format = format;
- emit formatChanged(m_format);
- }
+ setIsDecoding(false);
}
QAudioBuffer AVFAudioDecoder::read()
@@ -444,18 +427,10 @@ void AVFAudioDecoder::initAssetReader()
// Set format
QAudioFormat format;
- if (m_format.isValid()) {
- format = m_format;
- } else {
- format = qt_format_for_audio_track(track);
- if (!format.isValid())
- {
- processInvalidMedia(QAudioDecoder::FormatError, tr("Unsupported source format"));
- return;
- }
- // ### Change QAudioDecoder's format to resolved one?
- m_format = format;
- emit formatChanged(m_format);
+ format = qt_format_for_audio_track(track);
+ if (!format.isValid()) {
+ processInvalidMedia(QAudioDecoder::FormatError, tr("Unsupported source format"));
+ return;
}
// Set duration
@@ -498,10 +473,7 @@ void AVFAudioDecoder::startReading()
return;
}
- QAudioDecoder::State oldState = m_state;
- m_state = QAudioDecoder::DecodingState;
- if (oldState != m_state)
- emit stateChanged(m_state);
+ setIsDecoding(true);
// Since copyNextSampleBuffer is synchronous, submit it to an async dispatch queue
// to run in a separate thread. Call the handleNextSampleBuffer "callback" on another
@@ -515,11 +487,8 @@ void AVFAudioDecoder::startReading()
CFRelease(sampleBuffer);
});
}
- if (m_reader.status == AVAssetReaderStatusCompleted) {
- m_state = QAudioDecoder::StoppedState;
+ if (m_reader.status == AVAssetReaderStatusCompleted)
emit finished();
- emit stateChanged(m_state);
- }
});
}
diff --git a/src/multimedia/platform/darwin/audio/avfaudiodecoder_p.h b/src/multimedia/platform/darwin/audio/avfaudiodecoder_p.h
index 9f302cc39..5348b06fd 100644
--- a/src/multimedia/platform/darwin/audio/avfaudiodecoder_p.h
+++ b/src/multimedia/platform/darwin/audio/avfaudiodecoder_p.h
@@ -75,9 +75,6 @@ public:
AVFAudioDecoder(QAudioDecoder *parent);
virtual ~AVFAudioDecoder();
- // QAudioDecoder interface
- QAudioDecoder::State state() const override { return m_state; }
-
QUrl source() const override;
void setSource(const QUrl &fileName) override;
@@ -87,9 +84,6 @@ public:
void start() override;
void stop() override;
- QAudioFormat audioFormat() const override;
- void setAudioFormat(const QAudioFormat &format) override;
-
QAudioBuffer read() override;
bool bufferAvailable() const override;
@@ -108,12 +102,8 @@ private:
void processInvalidMedia(QAudioDecoder::Error errorCode, const QString& errorString);
void initAssetReader();
- QAudioDecoder::State m_state = QAudioDecoder::StoppedState;
- QAudioDecoder::State m_pendingState = QAudioDecoder::StoppedState;
-
QUrl m_source;
QIODevice *m_device = nullptr;
- QAudioFormat m_format;
int m_buffersAvailable = 0;
QList<QAudioBuffer> m_cachedBuffers;
diff --git a/src/multimedia/platform/gstreamer/audio/qgstreameraudiodecoder.cpp b/src/multimedia/platform/gstreamer/audio/qgstreameraudiodecoder.cpp
index 817e168bf..db23ac80f 100644
--- a/src/multimedia/platform/gstreamer/audio/qgstreameraudiodecoder.cpp
+++ b/src/multimedia/platform/gstreamer/audio/qgstreameraudiodecoder.cpp
@@ -163,21 +163,17 @@ bool QGstreamerAudioDecoder::processBusMessage(const QGstreamerMessage &message)
.arg(states[pending]) << "internal" << m_state;
#endif
- QAudioDecoder::State prevState = m_state;
-
+ bool isDecoding = false;
switch (newState) {
case GST_STATE_VOID_PENDING:
case GST_STATE_NULL:
- m_state = QAudioDecoder::StoppedState;
- break;
case GST_STATE_READY:
- m_state = QAudioDecoder::StoppedState;
break;
case GST_STATE_PLAYING:
- m_state = QAudioDecoder::DecodingState;
+ isDecoding = true;
break;
case GST_STATE_PAUSED:
- m_state = QAudioDecoder::DecodingState;
+ isDecoding = true;
//gstreamer doesn't give a reliable indication the duration
//information is ready, GST_MESSAGE_DURATION is not sent by most elements
@@ -187,15 +183,12 @@ bool QGstreamerAudioDecoder::processBusMessage(const QGstreamerMessage &message)
break;
}
- if (prevState != m_state)
- emit stateChanged(m_state);
+ setIsDecoding(isDecoding);
}
break;
case GST_MESSAGE_EOS:
- m_pendingState = m_state = QAudioDecoder::StoppedState;
- emit finished();
- emit stateChanged(m_state);
+ finished();
break;
case GST_MESSAGE_ERROR: {
@@ -338,24 +331,15 @@ void QGstreamerAudioDecoder::start()
// Set audio format
if (m_appSink) {
- if (mFormat.isValid()) {
- setAudioFlags(false);
- QGstMutableCaps caps = QGstUtils::capsForAudioFormat(mFormat);
- gst_app_sink_set_caps(m_appSink, caps.get());
- } else {
- // We want whatever the native audio format is
- setAudioFlags(true);
- gst_app_sink_set_caps(m_appSink, nullptr);
- }
+ // We want whatever the native audio format is
+ setAudioFlags(true);
+ gst_app_sink_set_caps(m_appSink, nullptr);
}
- 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);
+ return;
}
}
@@ -367,9 +351,6 @@ void QGstreamerAudioDecoder::stop()
m_playbin.setState(GST_STATE_NULL);
removeAppSink();
- QAudioDecoder::State oldState = m_state;
- m_pendingState = m_state = QAudioDecoder::StoppedState;
-
// GStreamer thread is stopped. Can safely access m_buffersAvailable
if (m_buffersAvailable != 0) {
m_buffersAvailable = 0;
@@ -386,21 +367,7 @@ void QGstreamerAudioDecoder::stop()
emit durationChanged(m_duration);
}
- if (oldState != m_state)
- emit stateChanged(m_state);
-}
-
-QAudioFormat QGstreamerAudioDecoder::audioFormat() const
-{
- return mFormat;
-}
-
-void QGstreamerAudioDecoder::setAudioFormat(const QAudioFormat &format)
-{
- if (mFormat != format) {
- mFormat = format;
- emit formatChanged(mFormat);
- }
+ setIsDecoding(false);
}
QAudioBuffer QGstreamerAudioDecoder::read()
diff --git a/src/multimedia/platform/gstreamer/audio/qgstreameraudiodecoder_p.h b/src/multimedia/platform/gstreamer/audio/qgstreameraudiodecoder_p.h
index be2343916..de9d59baf 100644
--- a/src/multimedia/platform/gstreamer/audio/qgstreameraudiodecoder_p.h
+++ b/src/multimedia/platform/gstreamer/audio/qgstreameraudiodecoder_p.h
@@ -81,9 +81,6 @@ public:
QGstreamerAudioDecoder(QAudioDecoder *parent);
virtual ~QGstreamerAudioDecoder();
- // QAudioDecoder interface
- QAudioDecoder::State state() const override { return m_state; }
-
QUrl source() const override;
void setSource(const QUrl &fileName) override;
@@ -93,9 +90,6 @@ public:
void start() override;
void stop() override;
- QAudioFormat audioFormat() const override;
- void setAudioFormat(const QAudioFormat &format) override;
-
QAudioBuffer read() override;
bool bufferAvailable() const override;
@@ -105,8 +99,6 @@ public:
// GStreamerBusMessageFilter interface
bool processBusMessage(const QGstreamerMessage &message) override;
- QAudioDecoder::State pendingState() const { return m_pendingState; }
-
#if QT_CONFIG(gstreamer_app)
QGstAppSrc *appsrc() const { return m_appSrc; }
static void configureAppSrcElement(GObject*, GObject*, GParamSpec*, QGstreamerAudioDecoder *_this);
@@ -125,8 +117,6 @@ private:
void processInvalidMedia(QAudioDecoder::Error errorCode, const QString& errorString);
static qint64 getPositionFromBuffer(GstBuffer* buffer);
- QAudioDecoder::State m_state = QAudioDecoder::StoppedState;
- QAudioDecoder::State m_pendingState = QAudioDecoder::StoppedState;
QGstPipeline m_playbin;
QGstBin m_outputBin;
QGstElement m_audioConvert;
@@ -135,7 +125,6 @@ private:
QUrl mSource;
QIODevice *mDevice = nullptr;
- QAudioFormat mFormat;
mutable QMutex m_buffersMutex;
int m_buffersAvailable = 0;
diff --git a/src/multimedia/platform/gstreamer/common/qgstutils.cpp b/src/multimedia/platform/gstreamer/common/qgstutils.cpp
index 7dd733f00..5d88f7e13 100644
--- a/src/multimedia/platform/gstreamer/common/qgstutils.cpp
+++ b/src/multimedia/platform/gstreamer/common/qgstutils.cpp
@@ -100,12 +100,16 @@ static QAudioFormat::SampleFormat gstSampleFormatToSampleFormat(const char *fmt)
*/
QAudioFormat QGstUtils::audioFormatForSample(GstSample *sample)
{
- GstCaps* caps = gst_sample_get_caps(sample);
- if (!caps)
+ QGstCaps caps = gst_sample_get_caps(sample);
+ if (caps.isNull())
return QAudioFormat();
+ return audioFormatForCaps(caps);
+}
+QAudioFormat QGstUtils::audioFormatForCaps(QGstCaps caps)
+{
QAudioFormat format;
- QGstStructure s = QGstCaps(caps).at(0);
+ QGstStructure s = caps.at(0);
if (s.name() != "audio/x-raw")
return format;
diff --git a/src/multimedia/platform/gstreamer/common/qgstutils_p.h b/src/multimedia/platform/gstreamer/common/qgstutils_p.h
index 651152950..0e6e76954 100644
--- a/src/multimedia/platform/gstreamer/common/qgstutils_p.h
+++ b/src/multimedia/platform/gstreamer/common/qgstutils_p.h
@@ -72,6 +72,7 @@ class QVideoFrameFormat;
namespace QGstUtils {
Q_MULTIMEDIA_EXPORT QAudioFormat audioFormatForSample(GstSample *sample);
+ QAudioFormat audioFormatForCaps(QGstCaps caps);
Q_MULTIMEDIA_EXPORT QGstMutableCaps capsForAudioFormat(const QAudioFormat &format);
Q_MULTIMEDIA_EXPORT QVideoFrameFormat formatForCaps(
diff --git a/src/multimedia/platform/qplatformaudiodecoder.cpp b/src/multimedia/platform/qplatformaudiodecoder.cpp
index b7da0a304..817e0656f 100644
--- a/src/multimedia/platform/qplatformaudiodecoder.cpp
+++ b/src/multimedia/platform/qplatformaudiodecoder.cpp
@@ -67,28 +67,6 @@ QPlatformAudioDecoder::QPlatformAudioDecoder(QAudioDecoder *parent)
}
/*!
- \fn QPlatformAudioDecoder::state() const
-
- 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)
-
- Signals that the state of a player control has changed to \a newState.
-
- \sa state()
-*/
-
-/*!
\fn QPlatformAudioDecoder::source() const
Returns the current media source filename, or a null QString if none (or a device)
@@ -150,6 +128,7 @@ void QPlatformAudioDecoder::error(int error, const QString &errorString)
return;
m_error = QAudioDecoder::Error(error);
m_errorString = errorString;
+ setIsDecoding(false);
emit q->error(m_error);
}
@@ -193,18 +172,6 @@ void QPlatformAudioDecoder::sourceChanged()
}
/*!
- \fn QPlatformAudioDecoder::formatChanged(const QAudioFormat &format)
-
- Signals that the current audio format of the decoder has changed to \a format.
-
- \sa audioFormat(), setAudioFormat()
-*/
-void QPlatformAudioDecoder::formatChanged(const QAudioFormat &format)
-{
- emit q->formatChanged(format);
-}
-
-/*!
\fn void QPlatformAudioDecoder::finished()
Signals that the decoding has finished successfully.
@@ -214,6 +181,7 @@ void QPlatformAudioDecoder::formatChanged(const QAudioFormat &format)
*/
void QPlatformAudioDecoder::finished()
{
+ setIsDecoding(false);
emit q->finished();
}
diff --git a/src/multimedia/platform/qplatformaudiodecoder_p.h b/src/multimedia/platform/qplatformaudiodecoder_p.h
index 91877e647..e097b79fa 100644
--- a/src/multimedia/platform/qplatformaudiodecoder_p.h
+++ b/src/multimedia/platform/qplatformaudiodecoder_p.h
@@ -66,8 +66,6 @@ class Q_MULTIMEDIA_EXPORT QPlatformAudioDecoder : public QObject
Q_OBJECT
public:
- virtual QAudioDecoder::State state() const { return m_state; }
-
virtual QUrl source() const = 0;
virtual void setSource(const QUrl &fileName) = 0;
@@ -77,17 +75,12 @@ public:
virtual void start() = 0;
virtual void stop() = 0;
- virtual QAudioFormat audioFormat() const = 0;
- virtual void setAudioFormat(const QAudioFormat &format) = 0;
-
virtual QAudioBuffer read() = 0;
virtual bool bufferAvailable() const = 0;
virtual qint64 position() const = 0;
virtual qint64 duration() const = 0;
- void stateChanged(QAudioDecoder::State newState);
- void formatChanged(const QAudioFormat &format);
void sourceChanged();
void error(int error, const QString &errorString);
@@ -95,7 +88,14 @@ public:
void bufferReady();
void bufferAvailableChanged(bool available);
+ void setIsDecoding(bool running = true) {
+ if (m_isDecoding == running)
+ return;
+ m_isDecoding = running;
+ emit q->isDecodingChanged(m_isDecoding);
+ }
void finished();
+ bool isDecoding() const { return m_isDecoding; }
void positionChanged(qint64 position);
void durationChanged(qint64 duration);
@@ -108,9 +108,9 @@ protected:
private:
QAudioDecoder *q = nullptr;
- QAudioDecoder::State m_state = QAudioDecoder::StoppedState;
QAudioDecoder::Error m_error = QAudioDecoder::NoError;
QString m_errorString;
+ bool m_isDecoding = false;
};
QT_END_NAMESPACE
diff --git a/src/multimedia/platform/windows/decoder/mfaudiodecodercontrol.cpp b/src/multimedia/platform/windows/decoder/mfaudiodecodercontrol.cpp
index 953281f31..7a460533d 100644
--- a/src/multimedia/platform/windows/decoder/mfaudiodecodercontrol.cpp
+++ b/src/multimedia/platform/windows/decoder/mfaudiodecodercontrol.cpp
@@ -44,8 +44,6 @@ MFAudioDecoderControl::MFAudioDecoderControl(QAudioDecoder *parent)
: QPlatformAudioDecoder(parent)
, m_decoderSourceReader(new MFDecoderSourceReader)
, m_sourceResolver(new SourceResolver)
- , m_resampler(0)
- , m_state(QAudioDecoder::StoppedState)
, m_device(0)
, m_mfInputStreamID(0)
, m_mfOutputStreamID(0)
@@ -56,21 +54,10 @@ MFAudioDecoderControl::MFAudioDecoderControl(QAudioDecoder *parent)
, m_mfOutputType(0)
, m_convertSample(0)
, m_sourceReady(false)
- , m_resamplerDirty(false)
{
- CoCreateInstance(CLSID_CResamplerMediaObject, NULL, CLSCTX_INPROC_SERVER, IID_IMFTransform, (LPVOID*)(&m_resampler));
- if (!m_resampler) {
- qCritical("MFAudioDecoderControl: Failed to create resampler(CLSID_CResamplerMediaObject)!");
- return;
- }
- m_resampler->AddInputStreams(1, &m_mfInputStreamID);
-
connect(m_sourceResolver, SIGNAL(mediaSourceReady()), this, SLOT(handleMediaSourceReady()));
connect(m_sourceResolver, SIGNAL(error(long)), this, SLOT(handleMediaSourceError(long)));
connect(m_decoderSourceReader, SIGNAL(finished()), this, SLOT(handleSourceFinished()));
-
- QAudioFormat defaultFormat;
- setAudioFormat(defaultFormat);
}
MFAudioDecoderControl::~MFAudioDecoderControl()
@@ -80,13 +67,6 @@ MFAudioDecoderControl::~MFAudioDecoderControl()
m_decoderSourceReader->shutdown();
m_decoderSourceReader->Release();
m_sourceResolver->Release();
- if (m_resampler)
- m_resampler->Release();
-}
-
-QAudioDecoder::State MFAudioDecoderControl::state() const
-{
- return m_state;
}
QUrl MFAudioDecoderControl::source() const
@@ -107,9 +87,9 @@ void MFAudioDecoderControl::onSourceCleared()
durationDirty = true;
}
if (positionDirty)
- emit positionChanged(m_position);
+ positionChanged(m_position);
if (durationDirty)
- emit durationChanged(m_duration);
+ durationChanged(m_duration);
}
void MFAudioDecoderControl::setSource(const QUrl &fileName)
@@ -118,7 +98,7 @@ void MFAudioDecoderControl::setSource(const QUrl &fileName)
return;
m_sourceReady = false;
m_sourceResolver->cancel();
- m_decoderSourceReader->setSource(0, m_audioFormat);
+ m_decoderSourceReader->setSource(nullptr);
m_device = 0;
m_source = fileName;
if (!m_source.isEmpty()) {
@@ -128,7 +108,7 @@ void MFAudioDecoderControl::setSource(const QUrl &fileName)
} else {
onSourceCleared();
}
- emit sourceChanged();
+ sourceChanged();
}
QIODevice* MFAudioDecoderControl::sourceDevice() const
@@ -142,7 +122,7 @@ void MFAudioDecoderControl::setSourceDevice(QIODevice *device)
return;
m_sourceReady = false;
m_sourceResolver->cancel();
- m_decoderSourceReader->setSource(0, m_audioFormat);
+ m_decoderSourceReader->setSource(nullptr);
m_source.clear();
m_device = device;
if (m_device) {
@@ -152,48 +132,17 @@ void MFAudioDecoderControl::setSourceDevice(QIODevice *device)
} else {
onSourceCleared();
}
- emit sourceChanged();
-}
-
-void MFAudioDecoderControl::updateResamplerOutputType()
-{
- m_resamplerDirty = false;
- if (m_audioFormat == m_sourceOutputFormat)
- return;
- HRESULT hr = m_resampler->SetOutputType(m_mfOutputStreamID, m_mfOutputType, 0);
- if (SUCCEEDED(hr)) {
- MFT_OUTPUT_STREAM_INFO streamInfo;
- m_resampler->GetOutputStreamInfo(m_mfOutputStreamID, &streamInfo);
- if ((streamInfo.dwFlags & (MFT_OUTPUT_STREAM_PROVIDES_SAMPLES | MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES)) == 0) {
- //if resampler does not allocate output sample memory, we do it here
- if (m_convertSample) {
- m_convertSample->Release();
- m_convertSample = 0;
- }
- if (SUCCEEDED(MFCreateSample(&m_convertSample))) {
- IMFMediaBuffer *mbuf = 0;;
- if (SUCCEEDED(MFCreateMemoryBuffer(streamInfo.cbSize, &mbuf))) {
- m_convertSample->AddBuffer(mbuf);
- mbuf->Release();
- }
- }
- }
- } else {
- qWarning() << "MFAudioDecoderControl: failed to SetOutputType of resampler" << hr;
- }
+ sourceChanged();
}
void MFAudioDecoderControl::handleMediaSourceReady()
{
m_loadingSource = false;
m_sourceReady = true;
- IMFMediaType *mediaType = m_decoderSourceReader->setSource(m_sourceResolver->mediaSource(), m_audioFormat);
+ IMFMediaType *mediaType = m_decoderSourceReader->setSource(m_sourceResolver->mediaSource());
m_sourceOutputFormat = QAudioFormat();
if (mediaType) {
- m_sourceOutputFormat = m_audioFormat;
- QAudioFormat af = m_audioFormat;
-
UINT32 val = 0;
if (SUCCEEDED(mediaType->GetUINT32(MF_MT_AUDIO_NUM_CHANNELS, &val))) {
m_sourceOutputFormat.setChannelCount(int(val));
@@ -210,30 +159,15 @@ void MFAudioDecoderControl::handleMediaSourceReady()
m_sourceOutputFormat.setSampleFormat(QAudioFormat::Float);
} else if (bitsPerSample == 8) {
m_sourceOutputFormat.setSampleFormat(QAudioFormat::UInt8);
- } else {
+ } else if (bitsPerSample == 16) {
m_sourceOutputFormat.setSampleFormat(QAudioFormat::Int16);
+ } else if (bitsPerSample == 32){
+ m_sourceOutputFormat.setSampleFormat(QAudioFormat::Int32);
}
}
-
- if (m_audioFormat.channelCount() <= 0) {
- af.setChannelCount(m_sourceOutputFormat.channelCount());
- }
- if (m_audioFormat.sampleRate() <= 0) {
- af.setSampleRate(m_sourceOutputFormat.sampleRate());
- }
- setAudioFormat(af);
}
if (m_sourceResolver->mediaSource()) {
- if (mediaType && m_resampler) {
- HRESULT hr = S_OK;
- hr = m_resampler->SetInputType(m_mfInputStreamID, mediaType, 0);
- if (SUCCEEDED(hr)) {
- updateResamplerOutputType();
- } else {
- qWarning() << "MFAudioDecoderControl: failed to SetInputType of resampler" << hr;
- }
- }
IMFPresentationDescriptor *pd;
if (SUCCEEDED(m_sourceResolver->mediaSource()->CreatePresentationDescriptor(&pd))) {
UINT64 duration = 0;
@@ -242,15 +176,14 @@ void MFAudioDecoderControl::handleMediaSourceReady()
duration /= 10000;
if (m_duration != qint64(duration)) {
m_duration = qint64(duration);
- emit durationChanged(m_duration);
+ durationChanged(m_duration);
}
}
- if (m_state == QAudioDecoder::DecodingState) {
+ if (isDecoding()) {
activatePipeline();
}
- } else if (m_state != QAudioDecoder::StoppedState) {
- m_state = QAudioDecoder::StoppedState;
- emit stateChanged(m_state);
+ } else if (isDecoding()) {
+ setIsDecoding(false);
}
}
@@ -258,58 +191,49 @@ void MFAudioDecoderControl::handleMediaSourceError(long hr)
{
Q_UNUSED(hr);
m_loadingSource = false;
- m_decoderSourceReader->setSource(0, m_audioFormat);
- if (m_state != QAudioDecoder::StoppedState) {
- m_state = QAudioDecoder::StoppedState;
- emit stateChanged(m_state);
- }
+ m_decoderSourceReader->setSource(nullptr);
+ setIsDecoding(false);
}
void MFAudioDecoderControl::activatePipeline()
{
Q_ASSERT(!m_bufferReady);
- m_state = QAudioDecoder::DecodingState;
+ setIsDecoding(true);
connect(m_decoderSourceReader, SIGNAL(sampleAdded()), this, SLOT(handleSampleAdded()));
- if (m_resamplerDirty) {
- updateResamplerOutputType();
- }
m_decoderSourceReader->reset();
m_decoderSourceReader->readNextSample();
if (m_position != 0) {
m_position = 0;
- emit positionChanged(0);
+ positionChanged(0);
}
}
void MFAudioDecoderControl::start()
{
- if (m_state != QAudioDecoder::StoppedState)
+ if (isDecoding())
return;
if (m_loadingSource) {
//deferred starting
- m_state = QAudioDecoder::DecodingState;
- emit stateChanged(m_state);
+ setIsDecoding(true);
return;
}
if (!m_decoderSourceReader->mediaSource())
return;
activatePipeline();
- emit stateChanged(m_state);
}
void MFAudioDecoderControl::stop()
{
- if (m_state == QAudioDecoder::StoppedState)
+ if (!isDecoding())
return;
- m_state = QAudioDecoder::StoppedState;
disconnect(m_decoderSourceReader, SIGNAL(sampleAdded()), this, SLOT(handleSampleAdded()));
if (m_bufferReady) {
m_bufferReady = false;
emit bufferAvailableChanged(m_bufferReady);
}
- emit stateChanged(m_state);
+ setIsDecoding(false);
}
void MFAudioDecoderControl::handleSampleAdded()
@@ -317,64 +241,29 @@ void MFAudioDecoderControl::handleSampleAdded()
QList<IMFSample*> samples = m_decoderSourceReader->takeSamples();
Q_ASSERT(samples.count() > 0);
Q_ASSERT(!m_bufferReady);
- Q_ASSERT(m_resampler);
LONGLONG sampleStartTime = 0;
IMFSample *firstSample = samples.first();
firstSample->GetSampleTime(&sampleStartTime);
QByteArray abuf;
- if (m_sourceOutputFormat == m_audioFormat) {
- //no need for resampling
- for (IMFSample *s : qAsConst(samples)) {
- IMFMediaBuffer *buffer;
- s->ConvertToContiguousBuffer(&buffer);
- DWORD bufLen = 0;
- BYTE *buf = 0;
- if (SUCCEEDED(buffer->Lock(&buf, NULL, &bufLen))) {
- abuf.push_back(QByteArray(reinterpret_cast<char*>(buf), bufLen));
- buffer->Unlock();
- }
- buffer->Release();
- LONGLONG sampleTime = 0, sampleDuration = 0;
- s->GetSampleTime(&sampleTime);
- s->GetSampleDuration(&sampleDuration);
- m_position = qint64(sampleTime + sampleDuration) / 10000;
- s->Release();
- }
- } else {
- for (IMFSample *s : qAsConst(samples)) {
- HRESULT hr = m_resampler->ProcessInput(m_mfInputStreamID, s, 0);
- if (SUCCEEDED(hr)) {
- MFT_OUTPUT_DATA_BUFFER outputDataBuffer;
- outputDataBuffer.dwStreamID = m_mfOutputStreamID;
- while (true) {
- outputDataBuffer.pEvents = 0;
- outputDataBuffer.dwStatus = 0;
- outputDataBuffer.pSample = m_convertSample;
- DWORD status = 0;
- if (SUCCEEDED(m_resampler->ProcessOutput(0, 1, &outputDataBuffer, &status))) {
- IMFMediaBuffer *buffer;
- outputDataBuffer.pSample->ConvertToContiguousBuffer(&buffer);
- DWORD bufLen = 0;
- BYTE *buf = 0;
- if (SUCCEEDED(buffer->Lock(&buf, NULL, &bufLen))) {
- abuf.push_back(QByteArray(reinterpret_cast<char*>(buf), bufLen));
- buffer->Unlock();
- }
- buffer->Release();
- } else {
- break;
- }
- }
- }
- LONGLONG sampleTime = 0, sampleDuration = 0;
- s->GetSampleTime(&sampleTime);
- s->GetSampleDuration(&sampleDuration);
- m_position = qint64(sampleTime + sampleDuration) / 10000;
- s->Release();
+ for (IMFSample *s : qAsConst(samples)) {
+ IMFMediaBuffer *buffer;
+ s->ConvertToContiguousBuffer(&buffer);
+ DWORD bufLen = 0;
+ BYTE *buf = 0;
+ if (SUCCEEDED(buffer->Lock(&buf, NULL, &bufLen))) {
+ abuf.push_back(QByteArray(reinterpret_cast<char*>(buf), bufLen));
+ buffer->Unlock();
}
+ buffer->Release();
+ LONGLONG sampleTime = 0, sampleDuration = 0;
+ s->GetSampleTime(&sampleTime);
+ s->GetSampleDuration(&sampleDuration);
+ m_position = qint64(sampleTime + sampleDuration) / 10000;
+ s->Release();
}
+
// WMF uses 100-nanosecond units, QAudioDecoder uses milliseconds, QAudioBuffer uses microseconds...
- m_cachedAudioBuffer = QAudioBuffer(abuf, m_audioFormat, qint64(sampleStartTime / 10));
+ m_cachedAudioBuffer = QAudioBuffer(abuf, m_sourceOutputFormat, qint64(sampleStartTime / 10));
m_bufferReady = true;
emit positionChanged(m_position);
emit bufferAvailableChanged(m_bufferReady);
@@ -387,54 +276,6 @@ void MFAudioDecoderControl::handleSourceFinished()
emit finished();
}
-QAudioFormat MFAudioDecoderControl::audioFormat() const
-{
- return m_audioFormat;
-}
-
-void MFAudioDecoderControl::setAudioFormat(const QAudioFormat &format)
-{
- if (m_audioFormat == format || !m_resampler)
- return;
- m_audioFormat = format;
-
- if (m_audioFormat.isValid()) {
- IMFMediaType *mediaType = 0;
- MFCreateMediaType(&mediaType);
- mediaType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio);
- if (format.sampleFormat() == QAudioFormat::Float) {
- mediaType->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_Float);
- } else {
- mediaType->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_PCM);
- }
-
- mediaType->SetUINT32(MF_MT_AUDIO_NUM_CHANNELS, UINT32(m_audioFormat.channelCount()));
- mediaType->SetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, UINT32(m_audioFormat.sampleRate()));
- UINT32 alignmentBlock = UINT32(m_audioFormat.bytesPerFrame());
- mediaType->SetUINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, alignmentBlock);
- UINT32 avgBytesPerSec = UINT32(m_audioFormat.sampleRate() * m_audioFormat.bytesPerFrame());
- mediaType->SetUINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, avgBytesPerSec);
- mediaType->SetUINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, UINT32(m_audioFormat.bytesPerSample()*8));
- mediaType->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);
-
- if (m_mfOutputType)
- m_mfOutputType->Release();
- m_mfOutputType = mediaType;
- } else {
- if (m_mfOutputType)
- m_mfOutputType->Release();
- m_mfOutputType = NULL;
- }
-
- if (m_sourceReady && m_state == QAudioDecoder::StoppedState) {
- updateResamplerOutputType();
- } else {
- m_resamplerDirty = true;
- }
-
- emit formatChanged(m_audioFormat);
-}
-
QAudioBuffer MFAudioDecoderControl::read()
{
if (!m_bufferReady)
diff --git a/src/multimedia/platform/windows/decoder/mfaudiodecodercontrol_p.h b/src/multimedia/platform/windows/decoder/mfaudiodecodercontrol_p.h
index 56edb95c0..8cd769e67 100644
--- a/src/multimedia/platform/windows/decoder/mfaudiodecodercontrol_p.h
+++ b/src/multimedia/platform/windows/decoder/mfaudiodecodercontrol_p.h
@@ -64,8 +64,6 @@ public:
MFAudioDecoderControl(QAudioDecoder *parent);
~MFAudioDecoderControl();
- QAudioDecoder::State state() const;
-
QUrl source() const;
void setSource(const QUrl &fileName);
@@ -75,9 +73,6 @@ public:
void start();
void stop();
- QAudioFormat audioFormat() const;
- void setAudioFormat(const QAudioFormat &format);
-
QAudioBuffer read();
bool bufferAvailable() const;
@@ -91,17 +86,13 @@ private Q_SLOTS:
void handleSourceFinished();
private:
- void updateResamplerOutputType();
void activatePipeline();
void onSourceCleared();
MFDecoderSourceReader *m_decoderSourceReader;
SourceResolver *m_sourceResolver;
- IMFTransform *m_resampler;
- QAudioDecoder::State m_state;
QUrl m_source;
QIODevice *m_device;
- QAudioFormat m_audioFormat;
DWORD m_mfInputStreamID;
DWORD m_mfOutputStreamID;
bool m_bufferReady;
@@ -113,7 +104,6 @@ private:
IMFSample *m_convertSample;
QAudioFormat m_sourceOutputFormat;
bool m_sourceReady;
- bool m_resamplerDirty;
};
#endif//MFAUDIODECODERCONTROL_H
diff --git a/src/multimedia/platform/windows/decoder/mfdecodersourcereader.cpp b/src/multimedia/platform/windows/decoder/mfdecodersourcereader.cpp
index 381c60dc5..d10839a63 100644
--- a/src/multimedia/platform/windows/decoder/mfdecodersourcereader.cpp
+++ b/src/multimedia/platform/windows/decoder/mfdecodersourcereader.cpp
@@ -64,7 +64,7 @@ IMFMediaSource* MFDecoderSourceReader::mediaSource()
return m_source;
}
-IMFMediaType* MFDecoderSourceReader::setSource(IMFMediaSource *source, const QAudioFormat &audioFormat)
+IMFMediaType* MFDecoderSourceReader::setSource(IMFMediaSource *source)
{
IMFMediaType *mediaType = NULL;
if (m_source == source)
@@ -90,12 +90,7 @@ IMFMediaType* MFDecoderSourceReader::setSource(IMFMediaSource *source, const QAu
IMFMediaType *pPartialType = NULL;
MFCreateMediaType(&pPartialType);
pPartialType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio);
-
- if (audioFormat.sampleFormat() == QAudioFormat::Float) {
- pPartialType->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_Float);
- } else {
- pPartialType->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_PCM);
- }
+ pPartialType->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_PCM);
m_sourceReader->SetCurrentMediaType(DWORD(MF_SOURCE_READER_FIRST_AUDIO_STREAM), NULL, pPartialType);
pPartialType->Release();
diff --git a/src/multimedia/platform/windows/decoder/mfdecodersourcereader_p.h b/src/multimedia/platform/windows/decoder/mfdecodersourcereader_p.h
index 7d63f5368..6730dbf7f 100644
--- a/src/multimedia/platform/windows/decoder/mfdecodersourcereader_p.h
+++ b/src/multimedia/platform/windows/decoder/mfdecodersourcereader_p.h
@@ -69,7 +69,7 @@ public:
void shutdown();
IMFMediaSource* mediaSource();
- IMFMediaType* setSource(IMFMediaSource *source, const QAudioFormat &audioFormat);
+ IMFMediaType* setSource(IMFMediaSource *source);
void reset();
void readNextSample();