8#include <private/qwindowsaudioutils_p.h>
10#include <QtCore/qdebug.h>
16 , m_sourceResolver(
new SourceResolver)
18 connect(m_sourceResolver, &SourceResolver::mediaSourceReady,
this, &MFAudioDecoderControl::handleMediaSourceReady);
19 connect(m_sourceResolver, &SourceResolver::error,
this, &MFAudioDecoderControl::handleMediaSourceError);
25 m_sourceResolver->Release();
30 if (!m_device && m_source == fileName)
39 if (!m_source.isEmpty()) {
40 m_sourceResolver->load(m_source, 0);
41 m_loadingSource =
true;
47 if (m_device == device && m_source.isEmpty())
57 if (m_device->isOpen() && m_device->isReadable()) {
58 m_sourceResolver->load(QUrl(), m_device);
59 m_loadingSource =
true;
66 m_loadingSource =
false;
67 if (m_deferredStart) {
68 m_deferredStart =
false;
69 startReadingSource(m_sourceResolver->mediaSource());
75 m_loadingSource =
false;
76 m_deferredStart =
false;
77 if (hr == MF_E_UNSUPPORTED_BYTESTREAM_TYPE) {
78 error(QAudioDecoder::FormatError, tr(
"Unsupported media type"));
79 }
else if (hr == ERROR_FILE_NOT_FOUND) {
80 error(QAudioDecoder::ResourceError, tr(
"Media not found"));
82 error(QAudioDecoder::ResourceError, tr(
"Unable to load specified URL")
83 + QString::fromStdString(std::system_category().message(hr)));
91 m_decoderSourceReader = std::make_unique<MFDecoderSourceReader>();
92 if (!m_decoderSourceReader) {
93 error(QAudioDecoder::ResourceError, tr(
"Could not instantiate MFDecoderSourceReader"));
97 auto mediaType = m_decoderSourceReader->setSource(source, m_outputFormat.sampleFormat());
98 QAudioFormat mediaFormat = QWindowsAudioUtils::mediaTypeToFormat(mediaType.Get());
100 error(QAudioDecoder::FormatError, tr(
"Invalid media format"));
101 m_decoderSourceReader.reset();
105 ComPtr<IMFPresentationDescriptor> pd;
106 if (SUCCEEDED(source->CreatePresentationDescriptor(pd.GetAddressOf()))) {
108 pd->GetUINT64(MF_PD_DURATION, &duration);
110 m_duration = qint64(duration);
111 durationChanged(m_duration);
114 if (!m_resampler.setup(mediaFormat, m_outputFormat.isValid() ? m_outputFormat : mediaFormat)) {
115 qWarning() <<
"Failed to set up resampler";
119 connect(m_decoderSourceReader.get(), &MFDecoderSourceReader::finished,
this, &MFAudioDecoderControl::handleSourceFinished);
120 connect(m_decoderSourceReader.get(), &MFDecoderSourceReader::newSample,
this, &MFAudioDecoderControl::handleNewSample);
124 m_decoderSourceReader->readNextSample();
132 if (m_loadingSource) {
133 m_deferredStart =
true;
135 IMFMediaSource *source = m_sourceResolver->mediaSource();
138 error(QAudioDecoder::ResourceError, tr(
"Unable to read from specified device"));
139 else if (m_source.isValid())
140 error(QAudioDecoder::ResourceError, tr(
"Unable to load specified URL"));
142 error(QAudioDecoder::ResourceError, tr(
"No media source specified"));
145 startReadingSource(source);
152 m_deferredStart =
false;
156 disconnect(m_decoderSourceReader.get());
157 m_decoderSourceReader->clearSource();
158 m_decoderSourceReader.reset();
162 m_audioBuffer.swap(buffer);
163 bufferAvailableChanged(
false);
165 setIsDecoding(
false);
167 if (m_position != -1) {
169 positionChanged(m_position);
171 if (m_duration != -1) {
173 durationChanged(m_duration);
181 qint64 sampleStartTimeUs = m_resampler.outputFormat().durationForBytes(m_resampler.totalOutputBytes());
182 QByteArray out = m_resampler.resample(sample);
185 error(QAudioDecoder::Error::ResourceError, tr(
"Failed processing a sample"));
188 m_audioBuffer = QAudioBuffer(out, m_resampler.outputFormat(), sampleStartTimeUs);
190 bufferAvailableChanged(
true);
203 if (m_outputFormat == format)
205 m_outputFormat = format;
206 formatChanged(m_outputFormat);
214 buffer.swap(m_audioBuffer);
215 m_position = buffer.startTime() / 1000;
216 positionChanged(m_position);
217 bufferAvailableChanged(
false);
218 m_decoderSourceReader->readNextSample();
226#include "moc_mfaudiodecodercontrol_p.cpp"
void setAudioFormat(const QAudioFormat &format) override
bool bufferAvailable() const override
void setSourceDevice(QIODevice *device) override
QAudioBuffer read() override
void setSource(const QUrl &fileName) override
~MFAudioDecoderControl() override
The QAudioDecoder class implements decoding audio.