diff options
Diffstat (limited to 'src')
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(); |