From 4a3e9ba74250e50bc1944fc6a1acb2efd2700166 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Tue, 9 Feb 2021 15:20:50 +0100 Subject: Fix compilation on Windows Change-Id: I470d5ac39ca66bfe613e82370cd5ea6f6cffa171 Reviewed-by: Doris Verria Reviewed-by: Lars Knoll --- src/multimedia/CMakeLists.txt | 1 + src/multimedia/audio/qwavedecoder.h | 2 +- .../windows/audio/qwindowsaudiodeviceinfo.cpp | 339 ++++++++------------- .../windows/audio/qwindowsaudiodeviceinfo_p.h | 15 - .../platform/windows/audio/qwindowsaudioinput.cpp | 7 +- .../platform/windows/audio/qwindowsaudiooutput.cpp | 34 +-- .../platform/windows/audio/qwindowsaudioutils.cpp | 9 +- .../windows/decoder/mfaudiodecodercontrol.cpp | 39 +-- .../windows/decoder/mfdecodersourcereader.cpp | 2 +- .../platform/windows/player/mfplayersession.cpp | 13 +- .../platform/windows/qwindowsdevicemanager.cpp | 3 +- .../platform/windows/qwindowsformatinfo.cpp | 79 +++++ .../platform/windows/qwindowsformatinfo_p.h | 69 +++++ .../platform/windows/qwindowsintegration.cpp | 12 +- .../platform/windows/qwindowsintegration_p.h | 3 + 15 files changed, 318 insertions(+), 309 deletions(-) create mode 100644 src/multimedia/platform/windows/qwindowsformatinfo.cpp create mode 100644 src/multimedia/platform/windows/qwindowsformatinfo_p.h diff --git a/src/multimedia/CMakeLists.txt b/src/multimedia/CMakeLists.txt index ba5333f58..35a5002b2 100644 --- a/src/multimedia/CMakeLists.txt +++ b/src/multimedia/CMakeLists.txt @@ -160,6 +160,7 @@ qt_internal_extend_target(Multimedia CONDITION WIN32 platform/windows/player/mfvideorenderercontrol.cpp platform/windows/player/mfvideorenderercontrol_p.h platform/windows/player/samplegrabber.cpp platform/windows/player/samplegrabber_p.h platform/windows/qwindowsdevicemanager.cpp platform/windows/qwindowsdevicemanager_p.h + platform/windows/qwindowsformatinfo.cpp platform/windows/qwindowsformatinfo_p.h platform/windows/qwindowsintegration.cpp platform/windows/qwindowsintegration_p.h platform/windows/sourceresolver.cpp platform/windows/sourceresolver_p.h INCLUDE_DIRECTORIES diff --git a/src/multimedia/audio/qwavedecoder.h b/src/multimedia/audio/qwavedecoder.h index 8b8ef9266..5854bf528 100644 --- a/src/multimedia/audio/qwavedecoder.h +++ b/src/multimedia/audio/qwavedecoder.h @@ -48,7 +48,7 @@ QT_BEGIN_NAMESPACE -class Q_AUTOTEST_EXPORT QWaveDecoder : public QIODevice +class Q_MULTIMEDIA_EXPORT QWaveDecoder : public QIODevice { Q_OBJECT diff --git a/src/multimedia/platform/windows/audio/qwindowsaudiodeviceinfo.cpp b/src/multimedia/platform/windows/audio/qwindowsaudiodeviceinfo.cpp index 71be6e21a..ba6b06ed0 100644 --- a/src/multimedia/platform/windows/audio/qwindowsaudiodeviceinfo.cpp +++ b/src/multimedia/platform/windows/audio/qwindowsaudiodeviceinfo.cpp @@ -59,75 +59,145 @@ QWindowsAudioDeviceInfo::QWindowsAudioDeviceInfo(QByteArray dev, int waveID, const QString &description, QAudio::Mode mode) : QAudioDeviceInfoPrivate(dev, mode), - m_description(description), devId(waveID) { - updateLists(); -} - -QWindowsAudioDeviceInfo::~QWindowsAudioDeviceInfo() -{ - close(); -} + this->description = description; + preferredFormat.setSampleRate(44100); + preferredFormat.setChannelCount(2); + preferredFormat.setSampleFormat(QAudioFormat::Int16); -bool QWindowsAudioDeviceInfo::isFormatSupported(const QAudioFormat& format) const -{ - return testSettings(format); -} + DWORD fmt = 0; -QAudioFormat QWindowsAudioDeviceInfo::preferredFormat() const -{ - QAudioFormat nearest; - if (mode == QAudio::AudioOutput) { - nearest.setSampleRate(44100); - nearest.setChannelCount(2); - nearest.setByteOrder(QAudioFormat::LittleEndian); - nearest.setSampleType(QAudioFormat::SignedInt); - nearest.setSampleSize(16); - nearest.setCodec(QLatin1String("audio/x-raw")); + if(mode == QAudio::AudioOutput) { + WAVEOUTCAPS woc; + if (waveOutGetDevCaps(devId, &woc, sizeof(WAVEOUTCAPS)) == MMSYSERR_NOERROR) + fmt = woc.dwFormats; } else { - nearest.setSampleRate(11025); - nearest.setChannelCount(1); - nearest.setByteOrder(QAudioFormat::LittleEndian); - nearest.setSampleType(QAudioFormat::SignedInt); - nearest.setSampleSize(8); - nearest.setCodec(QLatin1String("audio/x-raw")); + WAVEINCAPS woc; + if (waveInGetDevCaps(devId, &woc, sizeof(WAVEINCAPS)) == MMSYSERR_NOERROR) + fmt = woc.dwFormats; } - return nearest; -} -QList QWindowsAudioDeviceInfo::supportedSampleRates() const -{ - return sampleRatez; -} - -QList QWindowsAudioDeviceInfo::supportedChannelCounts() const -{ - return channelz; -} - -QList QWindowsAudioDeviceInfo::supportedSampleSizes() const -{ - return sizez; -} + if (!fmt) + return; -QList QWindowsAudioDeviceInfo::supportedByteOrders() const -{ - return QList() << QAudioFormat::LittleEndian; -} + // Check sample size + if ((fmt & WAVE_FORMAT_1M08) + || (fmt & WAVE_FORMAT_1S08) + || (fmt & WAVE_FORMAT_2M08) + || (fmt & WAVE_FORMAT_2S08) + || (fmt & WAVE_FORMAT_4M08) + || (fmt & WAVE_FORMAT_4S08) + || (fmt & WAVE_FORMAT_48M08) + || (fmt & WAVE_FORMAT_48S08) + || (fmt & WAVE_FORMAT_96M08) + || (fmt & WAVE_FORMAT_96S08)) { + supportedSampleFormats.append(QAudioFormat::UInt8); + } + if ((fmt & WAVE_FORMAT_1M16) + || (fmt & WAVE_FORMAT_1S16) + || (fmt & WAVE_FORMAT_2M16) + || (fmt & WAVE_FORMAT_2S16) + || (fmt & WAVE_FORMAT_4M16) + || (fmt & WAVE_FORMAT_4S16) + || (fmt & WAVE_FORMAT_48M16) + || (fmt & WAVE_FORMAT_48S16) + || (fmt & WAVE_FORMAT_96M16) + || (fmt & WAVE_FORMAT_96S16)) { + supportedSampleFormats.append(QAudioFormat::Int16); + } -QList QWindowsAudioDeviceInfo::supportedSampleTypes() const -{ - return typez; -} + supportedSampleRates = { INT_MAX, 0 }; + // Check sample rate + if ((fmt & WAVE_FORMAT_1M08) + || (fmt & WAVE_FORMAT_1S08) + || (fmt & WAVE_FORMAT_1M16) + || (fmt & WAVE_FORMAT_1S16)) { + supportedSampleRates.minimum = qMin(supportedSampleRates.minimum, 11025); + supportedSampleRates.maximum = qMin(supportedSampleRates.maximum, 11025); + } + if ((fmt & WAVE_FORMAT_2M08) + || (fmt & WAVE_FORMAT_2S08) + || (fmt & WAVE_FORMAT_2M16) + || (fmt & WAVE_FORMAT_2S16)) { + supportedSampleRates.minimum = qMin(supportedSampleRates.minimum, 22050); + supportedSampleRates.maximum = qMin(supportedSampleRates.maximum, 22050); + } + if ((fmt & WAVE_FORMAT_4M08) + || (fmt & WAVE_FORMAT_4S08) + || (fmt & WAVE_FORMAT_4M16) + || (fmt & WAVE_FORMAT_4S16)) { + supportedSampleRates.minimum = qMin(supportedSampleRates.minimum, 44100); + supportedSampleRates.maximum = qMin(supportedSampleRates.maximum, 44100); + } + if ((fmt & WAVE_FORMAT_48M08) + || (fmt & WAVE_FORMAT_48S08) + || (fmt & WAVE_FORMAT_48M16) + || (fmt & WAVE_FORMAT_48S16)) { + supportedSampleRates.minimum = qMin(supportedSampleRates.minimum, 48000); + supportedSampleRates.maximum = qMin(supportedSampleRates.maximum, 48000); + } + if ((fmt & WAVE_FORMAT_96M08) + || (fmt & WAVE_FORMAT_96S08) + || (fmt & WAVE_FORMAT_96M16) + || (fmt & WAVE_FORMAT_96S16)) { + supportedSampleRates.minimum = qMin(supportedSampleRates.minimum, 96000); + supportedSampleRates.maximum = qMin(supportedSampleRates.maximum, 96000); + } + // Check channel count + if (fmt & WAVE_FORMAT_1M08 + || fmt & WAVE_FORMAT_1M16 + || fmt & WAVE_FORMAT_2M08 + || fmt & WAVE_FORMAT_2M16 + || fmt & WAVE_FORMAT_4M08 + || fmt & WAVE_FORMAT_4M16 + || fmt & WAVE_FORMAT_48M08 + || fmt & WAVE_FORMAT_48M16 + || fmt & WAVE_FORMAT_96M08 + || fmt & WAVE_FORMAT_96M16) { + supportedChannelCounts.minimum = 1; + supportedChannelCounts.maximum = 1; + } + if (fmt & WAVE_FORMAT_1S08 + || fmt & WAVE_FORMAT_1S16 + || fmt & WAVE_FORMAT_2S08 + || fmt & WAVE_FORMAT_2S16 + || fmt & WAVE_FORMAT_4S08 + || fmt & WAVE_FORMAT_4S16 + || fmt & WAVE_FORMAT_48S08 + || fmt & WAVE_FORMAT_48S16 + || fmt & WAVE_FORMAT_96S08 + || fmt & WAVE_FORMAT_96S16) { + supportedChannelCounts.minimum = qMin(supportedChannelCounts.minimum, 96000); + supportedChannelCounts.maximum = qMin(supportedChannelCounts.maximum, 96000); + } -bool QWindowsAudioDeviceInfo::open() -{ - return true; + // WAVEOUTCAPS and WAVEINCAPS contains information only for the previously tested parameters. + // WaveOut and WaveInt might actually support more formats, the only way to know is to try + // opening the device with it. + QAudioFormat testFormat; + testFormat.setChannelCount(supportedChannelCounts.maximum); + testFormat.setSampleRate(supportedSampleRates.maximum); + const QAudioFormat defaultTestFormat(testFormat); + + // Check if float samples are supported + testFormat.setSampleFormat(QAudioFormat::Float); + if (testSettings(testFormat)) + supportedSampleFormats.append(QAudioFormat::Float); + + // Check channel counts > 2 + testFormat = defaultTestFormat; + for (int i = 18; i > 2; --i) { // defines 18 different channels + testFormat.setChannelCount(i); + if (testSettings(testFormat)) { + supportedChannelCounts.maximum = i; + break; + } + } } -void QWindowsAudioDeviceInfo::close() +QWindowsAudioDeviceInfo::~QWindowsAudioDeviceInfo() { } @@ -148,161 +218,4 @@ bool QWindowsAudioDeviceInfo::testSettings(const QAudioFormat& format) const return false; } -void QWindowsAudioDeviceInfo::updateLists() -{ - if (!sizez.isEmpty()) - return; - - DWORD fmt = 0; - - if(mode == QAudio::AudioOutput) { - WAVEOUTCAPS woc; - if (waveOutGetDevCaps(devId, &woc, sizeof(WAVEOUTCAPS)) == MMSYSERR_NOERROR) - fmt = woc.dwFormats; - } else { - WAVEINCAPS woc; - if (waveInGetDevCaps(devId, &woc, sizeof(WAVEINCAPS)) == MMSYSERR_NOERROR) - fmt = woc.dwFormats; - } - - sizez.clear(); - sampleRatez.clear(); - channelz.clear(); - typez.clear(); - - if (fmt) { - // Check sample size - if ((fmt & WAVE_FORMAT_1M08) - || (fmt & WAVE_FORMAT_1S08) - || (fmt & WAVE_FORMAT_2M08) - || (fmt & WAVE_FORMAT_2S08) - || (fmt & WAVE_FORMAT_4M08) - || (fmt & WAVE_FORMAT_4S08) - || (fmt & WAVE_FORMAT_48M08) - || (fmt & WAVE_FORMAT_48S08) - || (fmt & WAVE_FORMAT_96M08) - || (fmt & WAVE_FORMAT_96S08)) { - sizez.append(8); - } - if ((fmt & WAVE_FORMAT_1M16) - || (fmt & WAVE_FORMAT_1S16) - || (fmt & WAVE_FORMAT_2M16) - || (fmt & WAVE_FORMAT_2S16) - || (fmt & WAVE_FORMAT_4M16) - || (fmt & WAVE_FORMAT_4S16) - || (fmt & WAVE_FORMAT_48M16) - || (fmt & WAVE_FORMAT_48S16) - || (fmt & WAVE_FORMAT_96M16) - || (fmt & WAVE_FORMAT_96S16)) { - sizez.append(16); - } - - // Check sample rate - if ((fmt & WAVE_FORMAT_1M08) - || (fmt & WAVE_FORMAT_1S08) - || (fmt & WAVE_FORMAT_1M16) - || (fmt & WAVE_FORMAT_1S16)) { - sampleRatez.append(11025); - } - if ((fmt & WAVE_FORMAT_2M08) - || (fmt & WAVE_FORMAT_2S08) - || (fmt & WAVE_FORMAT_2M16) - || (fmt & WAVE_FORMAT_2S16)) { - sampleRatez.append(22050); - } - if ((fmt & WAVE_FORMAT_4M08) - || (fmt & WAVE_FORMAT_4S08) - || (fmt & WAVE_FORMAT_4M16) - || (fmt & WAVE_FORMAT_4S16)) { - sampleRatez.append(44100); - } - if ((fmt & WAVE_FORMAT_48M08) - || (fmt & WAVE_FORMAT_48S08) - || (fmt & WAVE_FORMAT_48M16) - || (fmt & WAVE_FORMAT_48S16)) { - sampleRatez.append(48000); - } - if ((fmt & WAVE_FORMAT_96M08) - || (fmt & WAVE_FORMAT_96S08) - || (fmt & WAVE_FORMAT_96M16) - || (fmt & WAVE_FORMAT_96S16)) { - sampleRatez.append(96000); - } - - // Check channel count - if (fmt & WAVE_FORMAT_1M08 - || fmt & WAVE_FORMAT_1M16 - || fmt & WAVE_FORMAT_2M08 - || fmt & WAVE_FORMAT_2M16 - || fmt & WAVE_FORMAT_4M08 - || fmt & WAVE_FORMAT_4M16 - || fmt & WAVE_FORMAT_48M08 - || fmt & WAVE_FORMAT_48M16 - || fmt & WAVE_FORMAT_96M08 - || fmt & WAVE_FORMAT_96M16) { - channelz.append(1); - } - if (fmt & WAVE_FORMAT_1S08 - || fmt & WAVE_FORMAT_1S16 - || fmt & WAVE_FORMAT_2S08 - || fmt & WAVE_FORMAT_2S16 - || fmt & WAVE_FORMAT_4S08 - || fmt & WAVE_FORMAT_4S16 - || fmt & WAVE_FORMAT_48S08 - || fmt & WAVE_FORMAT_48S16 - || fmt & WAVE_FORMAT_96S08 - || fmt & WAVE_FORMAT_96S16) { - channelz.append(2); - } - - typez.append(QAudioFormat::SignedInt); - typez.append(QAudioFormat::UnSignedInt); - - // WAVEOUTCAPS and WAVEINCAPS contains information only for the previously tested parameters. - // WaveOut and WaveInt might actually support more formats, the only way to know is to try - // opening the device with it. - QAudioFormat testFormat; - testFormat.setCodec(QStringLiteral("audio/x-raw")); - testFormat.setByteOrder(QAudioFormat::LittleEndian); - testFormat.setSampleType(QAudioFormat::SignedInt); - testFormat.setChannelCount(channelz.first()); - testFormat.setSampleRate(sampleRatez.at(sampleRatez.size() / 2)); - testFormat.setSampleSize(sizez.last()); - const QAudioFormat defaultTestFormat(testFormat); - - // Check if float samples are supported - testFormat.setSampleType(QAudioFormat::Float); - testFormat.setSampleSize(32); - if (testSettings(testFormat)) - typez.append(QAudioFormat::Float); - - // Check channel counts > 2 - testFormat = defaultTestFormat; - for (int i = 3; i < 19; ++i) { // defines 18 different channels - testFormat.setChannelCount(i); - if (testSettings(testFormat)) - channelz.append(i); - } - - // Check more sample sizes - testFormat = defaultTestFormat; - const QList testSampleSizes = QList() << 24 << 32 << 48 << 64; - for (int s : testSampleSizes) { - testFormat.setSampleSize(s); - if (testSettings(testFormat)) - sizez.append(s); - } - - // Check more sample rates - testFormat = defaultTestFormat; - const QList testSampleRates = QList() << 8000 << 16000 << 32000 << 88200 << 192000; - for (int r : testSampleRates) { - testFormat.setSampleRate(r); - if (testSettings(testFormat)) - sampleRatez.append(r); - } - std::sort(sampleRatez.begin(), sampleRatez.end()); - } -} - QT_END_NAMESPACE diff --git a/src/multimedia/platform/windows/audio/qwindowsaudiodeviceinfo_p.h b/src/multimedia/platform/windows/audio/qwindowsaudiodeviceinfo_p.h index d259b928f..378188084 100644 --- a/src/multimedia/platform/windows/audio/qwindowsaudiodeviceinfo_p.h +++ b/src/multimedia/platform/windows/audio/qwindowsaudiodeviceinfo_p.h @@ -77,25 +77,10 @@ public: void close(); bool testSettings(const QAudioFormat& format) const; - void updateLists(); - QAudioFormat preferredFormat() const; - bool isFormatSupported(const QAudioFormat& format) const; - QString description() const { return m_description; } - QList supportedSampleRates() const; - QList supportedChannelCounts() const; - QList supportedSampleSizes() const; - QList supportedByteOrders() const; - QList supportedSampleTypes() const; int waveId() const { return devId; } private: - QAudio::Mode mode; - QString m_description; quint32 devId; - QList sampleRatez; - QList channelz; - QList sizez; - QList typez; }; diff --git a/src/multimedia/platform/windows/audio/qwindowsaudioinput.cpp b/src/multimedia/platform/windows/audio/qwindowsaudioinput.cpp index b154d441a..3f2423ad5 100644 --- a/src/multimedia/platform/windows/audio/qwindowsaudioinput.cpp +++ b/src/multimedia/platform/windows/audio/qwindowsaudioinput.cpp @@ -309,8 +309,8 @@ bool QWindowsAudioInput::open() buffer_size = (settings.sampleRate() * settings.channelCount() - * settings.sampleSize() - + 39) / 40; + * settings.bytesPerSample() + + 39) / 5; period_size = buffer_size / 5; } else { period_size = buffer_size / 5; @@ -625,8 +625,7 @@ qint64 QWindowsAudioInput::processedUSecs() const if (deviceState == QAudio::StoppedState) return 0; qint64 result = qint64(1000000) * totalTimeValue / - (settings.channelCount()*(settings.sampleSize()/8)) / - settings.sampleRate(); + settings.bytesPerFrame() / settings.sampleRate(); return result; } diff --git a/src/multimedia/platform/windows/audio/qwindowsaudiooutput.cpp b/src/multimedia/platform/windows/audio/qwindowsaudiooutput.cpp index 7a47d277a..b9f746e91 100644 --- a/src/multimedia/platform/windows/audio/qwindowsaudiooutput.cpp +++ b/src/multimedia/platform/windows/audio/qwindowsaudiooutput.cpp @@ -233,9 +233,8 @@ bool QWindowsAudioOutput::open() // Default buffer size, 200ms, default period size is 40ms buffer_size = (settings.sampleRate() - * settings.channelCount() - * settings.sampleSize() - + 39) / 40; + * settings.bytesPerFrame() + + 39) / 5; period_size = buffer_size / 5; } else { period_size = buffer_size / 5; @@ -304,7 +303,7 @@ bool QWindowsAudioOutput::open() void QWindowsAudioOutput::pauseAndSleep() { waveOutPause(hWaveOut); - int bitrate = settings.sampleRate() * settings.channelCount() * settings.sampleSize() / 8; + int bitrate = settings.sampleRate() * settings.bytesPerFrame(); // Time of written data. int delay = (buffer_size - bytesFree()) * 1000 / bitrate; Sleep(delay + 10); @@ -367,8 +366,7 @@ qint64 QWindowsAudioOutput::processedUSecs() const if (deviceState == QAudio::StoppedState) return 0; qint64 result = qint64(1000000) * totalTimeValue / - (settings.channelCount()*(settings.sampleSize()/8)) / - settings.sampleRate(); + settings.bytesPerFrame() / settings.sampleRate(); return result; } @@ -382,30 +380,6 @@ qint64 QWindowsAudioOutput::write( const char *data, qint64 len ) char* p = (char*)data; int l = (int)len; - QByteArray reverse; - if (settings.byteOrder() == QAudioFormat::BigEndian) { - - switch (settings.sampleSize()) { - case 8: - // No need to convert - break; - - case 16: - reverse.resize(l); - for (qint64 i = 0; i < (l >> 1); i++) - *((qint16*)reverse.data() + i) = qFromBigEndian(*((qint16*)data + i)); - p = reverse.data(); - break; - - case 32: - reverse.resize(l); - for (qint64 i = 0; i < (l >> 2); i++) - *((qint32*)reverse.data() + i) = qFromBigEndian(*((qint32*)data + i)); - p = reverse.data(); - break; - } - } - WAVEHDR* current; int remain; current = &waveBlocks[waveCurrentBlock]; diff --git a/src/multimedia/platform/windows/audio/qwindowsaudioutils.cpp b/src/multimedia/platform/windows/audio/qwindowsaudioutils.cpp index 05832fdcb..69e50a9a6 100644 --- a/src/multimedia/platform/windows/audio/qwindowsaudioutils.cpp +++ b/src/multimedia/platform/windows/audio/qwindowsaudioutils.cpp @@ -82,22 +82,19 @@ bool qt_convertFormat(const QAudioFormat &format, WAVEFORMATEXTENSIBLE *wfx) { if (!wfx || !format.isValid() - || format.codec() != QStringLiteral("audio/x-raw") || format.sampleRate() <= 0 - || format.channelCount() <= 0 - || format.sampleSize() <= 0 - || format.byteOrder() != QAudioFormat::LittleEndian) { + || format.channelCount() <= 0) { return false; } wfx->Format.nSamplesPerSec = format.sampleRate(); - wfx->Format.wBitsPerSample = wfx->Samples.wValidBitsPerSample = format.sampleSize(); + wfx->Format.wBitsPerSample = wfx->Samples.wValidBitsPerSample = format.bytesPerSample()*8; wfx->Format.nChannels = format.channelCount(); wfx->Format.nBlockAlign = (wfx->Format.wBitsPerSample / 8) * wfx->Format.nChannels; wfx->Format.nAvgBytesPerSec = wfx->Format.nBlockAlign * wfx->Format.nSamplesPerSec; wfx->Format.cbSize = 0; - if (format.sampleType() == QAudioFormat::Float) { + if (format.sampleFormat() == QAudioFormat::Float) { wfx->Format.wFormatTag = WAVE_FORMAT_IEEE_FLOAT; wfx->SubFormat = _KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; } else { diff --git a/src/multimedia/platform/windows/decoder/mfaudiodecodercontrol.cpp b/src/multimedia/platform/windows/decoder/mfaudiodecodercontrol.cpp index f41e05ed9..1e2d61027 100644 --- a/src/multimedia/platform/windows/decoder/mfaudiodecodercontrol.cpp +++ b/src/multimedia/platform/windows/decoder/mfaudiodecodercontrol.cpp @@ -70,7 +70,6 @@ MFAudioDecoderControl::MFAudioDecoderControl(QObject *parent) connect(m_decoderSourceReader, SIGNAL(finished()), this, SLOT(handleSourceFinished())); QAudioFormat defaultFormat; - defaultFormat.setCodec("audio/x-raw"); setAudioFormat(defaultFormat); } @@ -207,40 +206,26 @@ void MFAudioDecoderControl::handleMediaSourceReady() if (SUCCEEDED(mediaType->GetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, &val))) { m_sourceOutputFormat.setSampleRate(int(val)); } - if (SUCCEEDED(mediaType->GetUINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, &val))) { - m_sourceOutputFormat.setSampleSize(int(val)); - } + UINT32 bitsPerSample = 0; + mediaType->GetUINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, &bitsPerSample); GUID subType; if (SUCCEEDED(mediaType->GetGUID(MF_MT_SUBTYPE, &subType))) { if (subType == MFAudioFormat_Float) { - m_sourceOutputFormat.setSampleType(QAudioFormat::Float); - } else if (m_sourceOutputFormat.sampleSize() == 8) { - m_sourceOutputFormat.setSampleType(QAudioFormat::UnSignedInt); + m_sourceOutputFormat.setSampleFormat(QAudioFormat::Float); + } else if (bitsPerSample == 8) { + m_sourceOutputFormat.setSampleFormat(QAudioFormat::UInt8); } else { - m_sourceOutputFormat.setSampleType(QAudioFormat::SignedInt); + m_sourceOutputFormat.setSampleFormat(QAudioFormat::Int16); } } - if (m_sourceOutputFormat.sampleType() != QAudioFormat::Float) { - m_sourceOutputFormat.setByteOrder(QAudioFormat::LittleEndian); - } - if (m_audioFormat.sampleType() != QAudioFormat::Float - && m_audioFormat.sampleType() != QAudioFormat::SignedInt) { - af.setSampleType(m_sourceOutputFormat.sampleType()); - } - if (af.sampleType() == QAudioFormat::SignedInt) { - af.setByteOrder(QAudioFormat::LittleEndian); - } if (m_audioFormat.channelCount() <= 0) { af.setChannelCount(m_sourceOutputFormat.channelCount()); } if (m_audioFormat.sampleRate() <= 0) { af.setSampleRate(m_sourceOutputFormat.sampleRate()); } - if (m_audioFormat.sampleSize() <= 0) { - af.setSampleSize(m_sourceOutputFormat.sampleSize()); - } setAudioFormat(af); } @@ -416,17 +401,13 @@ void MFAudioDecoderControl::setAudioFormat(const QAudioFormat &format) { if (m_audioFormat == format || !m_resampler) return; - if (format.codec() != QLatin1String("audio/x-wav") && format.codec() != QLatin1String("audio/x-raw")) { - qWarning("MFAudioDecoderControl does not accept non-pcm audio format!"); - return; - } m_audioFormat = format; if (m_audioFormat.isValid()) { IMFMediaType *mediaType = 0; MFCreateMediaType(&mediaType); mediaType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio); - if (format.sampleType() == QAudioFormat::Float) { + if (format.sampleFormat() == QAudioFormat::Float) { mediaType->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_Float); } else { mediaType->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_PCM); @@ -434,11 +415,11 @@ void MFAudioDecoderControl::setAudioFormat(const QAudioFormat &format) 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.channelCount() * m_audioFormat.sampleSize() / 8); + UINT32 alignmentBlock = UINT32(m_audioFormat.bytesPerFrame()); mediaType->SetUINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, alignmentBlock); - UINT32 avgBytesPerSec = UINT32(m_audioFormat.sampleRate() * m_audioFormat.sampleSize() / 8 * m_audioFormat.channelCount()); + 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.sampleSize())); + mediaType->SetUINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, UINT32(m_audioFormat.bytesPerSample()*8)); mediaType->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE); if (m_mfOutputType) diff --git a/src/multimedia/platform/windows/decoder/mfdecodersourcereader.cpp b/src/multimedia/platform/windows/decoder/mfdecodersourcereader.cpp index b2b9cf60d..381c60dc5 100644 --- a/src/multimedia/platform/windows/decoder/mfdecodersourcereader.cpp +++ b/src/multimedia/platform/windows/decoder/mfdecodersourcereader.cpp @@ -91,7 +91,7 @@ IMFMediaType* MFDecoderSourceReader::setSource(IMFMediaSource *source, const QAu MFCreateMediaType(&pPartialType); pPartialType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio); - if (audioFormat.sampleType() == QAudioFormat::Float) { + if (audioFormat.sampleFormat() == QAudioFormat::Float) { pPartialType->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_Float); } else { pPartialType->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_PCM); diff --git a/src/multimedia/platform/windows/player/mfplayersession.cpp b/src/multimedia/platform/windows/player/mfplayersession.cpp index 0c3f10b9f..359748832 100644 --- a/src/multimedia/platform/windows/player/mfplayersession.cpp +++ b/src/multimedia/platform/windows/player/mfplayersession.cpp @@ -547,13 +547,12 @@ QAudioFormat MFPlayerSession::audioFormatForMFMediaType(IMFMediaType *mediaType) QAudioFormat format; format.setSampleRate(wfx->nSamplesPerSec); format.setChannelCount(wfx->nChannels); - format.setSampleSize(wfx->wBitsPerSample); - format.setCodec("audio/x-raw"); - format.setByteOrder(QAudioFormat::LittleEndian); - if (format.sampleSize() == 8) - format.setSampleType(QAudioFormat::UnSignedInt); - else - format.setSampleType(QAudioFormat::SignedInt); + if (wfx->wBitsPerSample == 8) + format.setSampleFormat(QAudioFormat::UInt8); + else if (wfx->wBitsPerSample == 16) + format.setSampleFormat(QAudioFormat::Int16); + else if (wfx->wBitsPerSample == 32) + format.setSampleFormat(QAudioFormat::Int32); CoTaskMemFree(wfx); return format; diff --git a/src/multimedia/platform/windows/qwindowsdevicemanager.cpp b/src/multimedia/platform/windows/qwindowsdevicemanager.cpp index eaee031ce..b93484a59 100644 --- a/src/multimedia/platform/windows/qwindowsdevicemanager.cpp +++ b/src/multimedia/platform/windows/qwindowsdevicemanager.cpp @@ -119,8 +119,7 @@ static QList availableDevices(QAudio::Mode mode) continue; QByteArray strId = QString::fromWCharArray(id.data()).toUtf8(); - QAudioDeviceInfo info(new QWindowsAudioDeviceInfo(strId, waveID, description, mode)); - devices.append(info); + devices.append((new QWindowsAudioDeviceInfo(strId, waveID, description, mode))->create()); } } diff --git a/src/multimedia/platform/windows/qwindowsformatinfo.cpp b/src/multimedia/platform/windows/qwindowsformatinfo.cpp new file mode 100644 index 000000000..e64c79a00 --- /dev/null +++ b/src/multimedia/platform/windows/qwindowsformatinfo.cpp @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2021 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwindowsformatinfo_p.h" + + +QT_BEGIN_NAMESPACE + +QWindowsFormatInfo::QWindowsFormatInfo() +{ + decoders = { + { QMediaFormat::MPEG4, + { QMediaFormat::AudioCodec::AAC, QMediaFormat::AudioCodec::MP3, QMediaFormat::AudioCodec::ALAC, QMediaFormat::AudioCodec::AC3, QMediaFormat::AudioCodec::EAC3, }, + { QMediaFormat::VideoCodec::H264, QMediaFormat::VideoCodec::H265, QMediaFormat::VideoCodec::MotionJPEG } }, + { QMediaFormat::QuickTime, + { QMediaFormat::AudioCodec::AAC, QMediaFormat::AudioCodec::MP3, QMediaFormat::AudioCodec::ALAC, QMediaFormat::AudioCodec::AC3, QMediaFormat::AudioCodec::EAC3, }, + { QMediaFormat::VideoCodec::H264, QMediaFormat::VideoCodec::H265, QMediaFormat::VideoCodec::MotionJPEG } }, + { QMediaFormat::AAC, + { QMediaFormat::AudioCodec::AAC }, + {} }, + { QMediaFormat::MP3, + { QMediaFormat::AudioCodec::MP3 }, + {} }, + { QMediaFormat::FLAC, + { QMediaFormat::AudioCodec::FLAC }, + {} }, + { QMediaFormat::Mpeg4Audio, + { QMediaFormat::AudioCodec::AAC }, + {} } + }; + + // ### no encoders yet + + // #### + imageFormats = { QImageEncoderSettings::JPEG, QImageEncoderSettings::PNG }; + +} + +QWindowsFormatInfo::~QWindowsFormatInfo() +{ +} + +QT_END_NAMESPACE diff --git a/src/multimedia/platform/windows/qwindowsformatinfo_p.h b/src/multimedia/platform/windows/qwindowsformatinfo_p.h new file mode 100644 index 000000000..5463136b1 --- /dev/null +++ b/src/multimedia/platform/windows/qwindowsformatinfo_p.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2021 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINDOWSFORMATSINFO_H +#define QWINDOWSFORMATSINFO_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QWindowsFormatInfo : public QMediaPlatformFormatInfo +{ +public: + QWindowsFormatInfo(); + ~QWindowsFormatInfo(); +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/multimedia/platform/windows/qwindowsintegration.cpp b/src/multimedia/platform/windows/qwindowsintegration.cpp index 2b610cde6..c4b9142ed 100644 --- a/src/multimedia/platform/windows/qwindowsintegration.cpp +++ b/src/multimedia/platform/windows/qwindowsintegration.cpp @@ -39,6 +39,7 @@ #include "qwindowsintegration_p.h" #include "qwindowsdevicemanager_p.h" +#include "qwindowsformatinfo_p.h" #include #include @@ -57,8 +58,10 @@ QWindowsIntegration::QWindowsIntegration() QWindowsIntegration::~QWindowsIntegration() { - g_refCount--; delete m_manager; + delete m_formatInfo; + + g_refCount--; if (g_refCount == 0) { // ### This currently crashes on exit // MFShutdown(); @@ -73,6 +76,13 @@ QMediaPlatformDeviceManager *QWindowsIntegration::deviceManager() return m_manager; } +QMediaPlatformFormatInfo *QWindowsIntegration::formatInfo() +{ + if (!m_formatInfo) + m_formatInfo = new QWindowsFormatInfo(); + return m_formatInfo; +} + QAudioDecoderControl *QWindowsIntegration::createAudioDecoder() { return new MFAudioDecoderControl; diff --git a/src/multimedia/platform/windows/qwindowsintegration_p.h b/src/multimedia/platform/windows/qwindowsintegration_p.h index 5997fdc3b..ee37c27ed 100644 --- a/src/multimedia/platform/windows/qwindowsintegration_p.h +++ b/src/multimedia/platform/windows/qwindowsintegration_p.h @@ -56,6 +56,7 @@ QT_BEGIN_NAMESPACE class QWindowsDeviceManager; +class QWindowsFormatInfo; class QWindowsIntegration : public QMediaPlatformIntegration { @@ -67,11 +68,13 @@ public: void releaseRefCount(); QMediaPlatformDeviceManager *deviceManager() override; + QMediaPlatformFormatInfo *formatInfo() override; QAudioDecoderControl *createAudioDecoder() override; QMediaPlatformPlayerInterface *createPlayerInterface() override; QWindowsDeviceManager *m_manager = nullptr; + QWindowsFormatInfo *m_formatInfo = nullptr; }; QT_END_NAMESPACE -- cgit v1.2.3