diff options
author | Lars Knoll <lars.knoll@qt.io> | 2021-01-27 19:31:13 +0100 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2021-02-09 14:33:28 +0000 |
commit | 89f4db5857ea0c30c52510785f505a9217750db5 (patch) | |
tree | 9f8ed97cddf1ae0c21a8a5d829e61ee8401a8fcd /src/multimedia/platform | |
parent | c401a0dc71dc49cd34f8a5dd2fd7320f451e98bf (diff) |
Cleanup QAudioFormat and friends
Reduce the amount of available formats, and always
use host endianness.
Return both sample rate and channel count as a range,
not a list of values.
Change-Id: I88389b49ace077764fb647f50834236448e55c0e
Reviewed-by: Doris Verria <doris.verria@qt.io>
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src/multimedia/platform')
26 files changed, 281 insertions, 794 deletions
diff --git a/src/multimedia/platform/alsa/qalsaaudiodeviceinfo.cpp b/src/multimedia/platform/alsa/qalsaaudiodeviceinfo.cpp index 92716220f..946d7c97a 100644 --- a/src/multimedia/platform/alsa/qalsaaudiodeviceinfo.cpp +++ b/src/multimedia/platform/alsa/qalsaaudiodeviceinfo.cpp @@ -54,209 +54,30 @@ QT_BEGIN_NAMESPACE -QAlsaAudioDeviceInfo::QAlsaAudioDeviceInfo(const QByteArray &dev, const QString &description, QAudio::Mode mode) +QAlsaAudioDeviceInfo::QAlsaAudioDeviceInfo(const QByteArray &dev, const QString &desc, QAudio::Mode mode) : QAudioDeviceInfoPrivate(dev, mode) - , m_description(description) { - handle = 0; - - this->mode = mode; + description = desc; checkSurround(); -} - -QAlsaAudioDeviceInfo::~QAlsaAudioDeviceInfo() -{ - close(); -} - -bool QAlsaAudioDeviceInfo::isFormatSupported(const QAudioFormat& format) const -{ - return testSettings(format); -} -QAudioFormat QAlsaAudioDeviceInfo::preferredFormat() const -{ - QAudioFormat nearest; - nearest.setSampleRate(44100); - nearest.setByteOrder(QAudioFormat::LittleEndian); - nearest.setSampleType(QAudioFormat::SignedInt); - nearest.setSampleSize(16); - nearest.setChannelCount(2); - if(mode == QAudio::AudioInput && !testSettings(nearest)) - nearest.setChannelCount(1); - return nearest; -} + supportedChannelCounts.minimum = 1; + supportedChannelCounts.maximum = 2; + if (surround71) + supportedChannelCounts.maximum = 8; + else if (surround40) + supportedChannelCounts.maximum = 4; + else if (surround51) + supportedChannelCounts.maximum = 6; -QList<int> QAlsaAudioDeviceInfo::supportedSampleRates() const -{ - updateLists(); - return sampleRatez; -} + supportedSampleRates.minimum = 8000; + supportedSampleRates.maximum = 48000; -QList<int> QAlsaAudioDeviceInfo::supportedChannelCounts() const -{ - updateLists(); - return channelz; + supportedSampleFormats << QAudioFormat::UInt8 << QAudioFormat::Int16 << QAudioFormat::Int32 << QAudioFormat::Float; } -QList<int> QAlsaAudioDeviceInfo::supportedSampleSizes() const -{ - updateLists(); - return sizez; -} - -QList<QAudioFormat::Endian> QAlsaAudioDeviceInfo::supportedByteOrders() const -{ - updateLists(); - return byteOrderz; -} - -QList<QAudioFormat::SampleType> QAlsaAudioDeviceInfo::supportedSampleTypes() const -{ - updateLists(); - return typez; -} - -QByteArray QAlsaAudioDeviceInfo::defaultDevice(QAudio::Mode) -{ - return "default"; -} - -bool QAlsaAudioDeviceInfo::open() const -{ - int err = 0; - - if(mode == QAudio::AudioOutput) { - err = snd_pcm_open(&handle, id.constData(), SND_PCM_STREAM_PLAYBACK,0); - } else { - err = snd_pcm_open(&handle, id.constData(), SND_PCM_STREAM_CAPTURE,0); - } - if(err < 0) { - handle = 0; - return false; - } - return true; -} - -void QAlsaAudioDeviceInfo::close() const -{ - if(handle) - snd_pcm_close(handle); - handle = 0; -} - -bool QAlsaAudioDeviceInfo::testSettings(const QAudioFormat& format) const -{ - // Set nearest to closest settings that do work. - // See if what is in settings will work (return value). - int err = -1; - snd_pcm_t* pcmHandle; - snd_pcm_hw_params_t *params; - - snd_pcm_stream_t stream = mode == QAudio::AudioOutput - ? SND_PCM_STREAM_PLAYBACK : SND_PCM_STREAM_CAPTURE; - - if (snd_pcm_open(&pcmHandle, id.constData(), stream, 0) < 0) - return false; - - snd_pcm_nonblock(pcmHandle, 0); - snd_pcm_hw_params_alloca(¶ms); - snd_pcm_hw_params_any(pcmHandle, params); - - // set the values! - snd_pcm_hw_params_set_channels(pcmHandle, params, format.channelCount()); - snd_pcm_hw_params_set_rate(pcmHandle, params, format.sampleRate(), 0); - - snd_pcm_format_t pcmFormat = SND_PCM_FORMAT_UNKNOWN; - switch (format.sampleSize()) { - case 8: - if (format.sampleType() == QAudioFormat::SignedInt) - pcmFormat = SND_PCM_FORMAT_S8; - else if (format.sampleType() == QAudioFormat::UnSignedInt) - pcmFormat = SND_PCM_FORMAT_U8; - break; - case 16: - if (format.sampleType() == QAudioFormat::SignedInt) { - pcmFormat = format.byteOrder() == QAudioFormat::LittleEndian - ? SND_PCM_FORMAT_S16_LE : SND_PCM_FORMAT_S16_BE; - } else if (format.sampleType() == QAudioFormat::UnSignedInt) { - pcmFormat = format.byteOrder() == QAudioFormat::LittleEndian - ? SND_PCM_FORMAT_U16_LE : SND_PCM_FORMAT_U16_BE; - } - break; - case 32: - if (format.sampleType() == QAudioFormat::SignedInt) { - pcmFormat = format.byteOrder() == QAudioFormat::LittleEndian - ? SND_PCM_FORMAT_S32_LE : SND_PCM_FORMAT_S32_BE; - } else if (format.sampleType() == QAudioFormat::UnSignedInt) { - pcmFormat = format.byteOrder() == QAudioFormat::LittleEndian - ? SND_PCM_FORMAT_U32_LE : SND_PCM_FORMAT_U32_BE; - } else if (format.sampleType() == QAudioFormat::Float) { - pcmFormat = format.byteOrder() == QAudioFormat::LittleEndian - ? SND_PCM_FORMAT_FLOAT_LE : SND_PCM_FORMAT_FLOAT_BE; - } - } - - if (pcmFormat != SND_PCM_FORMAT_UNKNOWN) - err = snd_pcm_hw_params_set_format(pcmHandle, params, pcmFormat); - - if (err >= 0 && format.channelCount() != -1) { - err = snd_pcm_hw_params_test_channels(pcmHandle, params, format.channelCount()); - if (err >= 0) - err = snd_pcm_hw_params_set_channels(pcmHandle, params, format.channelCount()); - } - - if (err >= 0 && format.sampleRate() != -1) { - err = snd_pcm_hw_params_test_rate(pcmHandle, params, format.sampleRate(), 0); - if (err >= 0) - err = snd_pcm_hw_params_set_rate(pcmHandle, params, format.sampleRate(), 0); - } - - if (err >= 0 && pcmFormat != SND_PCM_FORMAT_UNKNOWN) - err = snd_pcm_hw_params_set_format(pcmHandle, params, pcmFormat); - - if (err >= 0) - err = snd_pcm_hw_params(pcmHandle, params); - - snd_pcm_close(pcmHandle); - - return (err == 0); -} - -void QAlsaAudioDeviceInfo::updateLists() const +QAlsaAudioDeviceInfo::~QAlsaAudioDeviceInfo() { - // redo all lists based on current settings - sampleRatez.clear(); - channelz.clear(); - sizez.clear(); - byteOrderz.clear(); - typez.clear(); - - if(!handle) - open(); - - if(!handle) - return; - - for(int i=0; i<(int)MAX_SAMPLE_RATES; i++) { - //if(snd_pcm_hw_params_test_rate(handle, params, SAMPLE_RATES[i], dir) == 0) - sampleRatez.append(SAMPLE_RATES[i]); - } - channelz.append(1); - channelz.append(2); - if (surround40) channelz.append(4); - if (surround51) channelz.append(6); - if (surround71) channelz.append(8); - sizez.append(8); - sizez.append(16); - sizez.append(32); - byteOrderz.append(QAudioFormat::LittleEndian); - byteOrderz.append(QAudioFormat::BigEndian); - typez.append(QAudioFormat::SignedInt); - typez.append(QAudioFormat::UnSignedInt); - typez.append(QAudioFormat::Float); - close(); } void QAlsaAudioDeviceInfo::checkSurround() diff --git a/src/multimedia/platform/alsa/qalsaaudiodeviceinfo_p.h b/src/multimedia/platform/alsa/qalsaaudiodeviceinfo_p.h index 80b2f85d5..92dbccce0 100644 --- a/src/multimedia/platform/alsa/qalsaaudiodeviceinfo_p.h +++ b/src/multimedia/platform/alsa/qalsaaudiodeviceinfo_p.h @@ -66,45 +66,17 @@ QT_BEGIN_NAMESPACE -const unsigned int MAX_SAMPLE_RATES = 5; -const unsigned int SAMPLE_RATES[] = - { 8000, 11025, 22050, 44100, 48000 }; - class QAlsaAudioDeviceInfo : public QAudioDeviceInfoPrivate { public: QAlsaAudioDeviceInfo(const QByteArray &dev, const QString &description, QAudio::Mode mode); ~QAlsaAudioDeviceInfo(); - bool testSettings(const QAudioFormat& format) const; - void updateLists() const; - QAudioFormat preferredFormat() const override; - bool isFormatSupported(const QAudioFormat& format) const override; - QString description() const override { return m_description; } - QList<int> supportedSampleRates() const override; - QList<int> supportedChannelCounts() const override; - QList<int> supportedSampleSizes() const override; - QList<QAudioFormat::Endian> supportedByteOrders() const override; - QList<QAudioFormat::SampleType> supportedSampleTypes() const override; - static QByteArray defaultDevice(QAudio::Mode mode); - private: - bool open() const; - void close() const; - void checkSurround(); bool surround40; bool surround51; bool surround71; - - QString m_description; - QAudioFormat nearest; - mutable QList<int> sampleRatez; - mutable QList<int> channelz; - mutable QList<int> sizez; - mutable QList<QAudioFormat::Endian> byteOrderz; - mutable QList<QAudioFormat::SampleType> typez; - mutable snd_pcm_t* handle; }; QT_END_NAMESPACE diff --git a/src/multimedia/platform/alsa/qalsaaudioinput.cpp b/src/multimedia/platform/alsa/qalsaaudioinput.cpp index abfc7a0ac..2b4815188 100644 --- a/src/multimedia/platform/alsa/qalsaaudioinput.cpp +++ b/src/multimedia/platform/alsa/qalsaaudioinput.cpp @@ -171,60 +171,35 @@ int QAlsaAudioInput::xrun_recovery(int err) int QAlsaAudioInput::setFormat() { - snd_pcm_format_t format = SND_PCM_FORMAT_UNKNOWN; - - if(settings.sampleSize() == 8) { - format = SND_PCM_FORMAT_U8; - } else if(settings.sampleSize() == 16) { - if(settings.sampleType() == QAudioFormat::SignedInt) { - if(settings.byteOrder() == QAudioFormat::LittleEndian) - format = SND_PCM_FORMAT_S16_LE; - else - format = SND_PCM_FORMAT_S16_BE; - } else if(settings.sampleType() == QAudioFormat::UnSignedInt) { - if(settings.byteOrder() == QAudioFormat::LittleEndian) - format = SND_PCM_FORMAT_U16_LE; - else - format = SND_PCM_FORMAT_U16_BE; - } - } else if(settings.sampleSize() == 24) { - if(settings.sampleType() == QAudioFormat::SignedInt) { - if(settings.byteOrder() == QAudioFormat::LittleEndian) - format = SND_PCM_FORMAT_S24_LE; - else - format = SND_PCM_FORMAT_S24_BE; - } else if(settings.sampleType() == QAudioFormat::UnSignedInt) { - if(settings.byteOrder() == QAudioFormat::LittleEndian) - format = SND_PCM_FORMAT_U24_LE; - else - format = SND_PCM_FORMAT_U24_BE; - } - } else if(settings.sampleSize() == 32) { - if(settings.sampleType() == QAudioFormat::SignedInt) { - if(settings.byteOrder() == QAudioFormat::LittleEndian) - format = SND_PCM_FORMAT_S32_LE; - else - format = SND_PCM_FORMAT_S32_BE; - } else if(settings.sampleType() == QAudioFormat::UnSignedInt) { - if(settings.byteOrder() == QAudioFormat::LittleEndian) - format = SND_PCM_FORMAT_U32_LE; - else - format = SND_PCM_FORMAT_U32_BE; - } else if(settings.sampleType() == QAudioFormat::Float) { - if(settings.byteOrder() == QAudioFormat::LittleEndian) - format = SND_PCM_FORMAT_FLOAT_LE; - else - format = SND_PCM_FORMAT_FLOAT_BE; - } - } else if(settings.sampleSize() == 64) { - if(settings.byteOrder() == QAudioFormat::LittleEndian) - format = SND_PCM_FORMAT_FLOAT64_LE; + snd_pcm_format_t pcmformat = SND_PCM_FORMAT_UNKNOWN; + + switch (settings.sampleFormat()) { + case QAudioFormat::UInt8: + pcmformat = SND_PCM_FORMAT_U8; + break; + case QAudioFormat::Int16: + if constexpr (QSysInfo::ByteOrder == QSysInfo::BigEndian) + pcmformat = SND_PCM_FORMAT_S16_LE; + else + pcmformat = SND_PCM_FORMAT_S16_BE; + break; + case QAudioFormat::Int32: + if constexpr (QSysInfo::ByteOrder == QSysInfo::BigEndian) + pcmformat = SND_PCM_FORMAT_S32_LE; + else + pcmformat = SND_PCM_FORMAT_S32_BE; + break; + case QAudioFormat::Float: + if constexpr (QSysInfo::ByteOrder == QSysInfo::BigEndian) + pcmformat = SND_PCM_FORMAT_FLOAT_LE; else - format = SND_PCM_FORMAT_FLOAT64_BE; + pcmformat = SND_PCM_FORMAT_FLOAT_BE; + default: + break; } - return format != SND_PCM_FORMAT_UNKNOWN - ? snd_pcm_hw_params_set_format( handle, hwparams, format) + return pcmformat != SND_PCM_FORMAT_UNKNOWN + ? snd_pcm_hw_params_set_format( handle, hwparams, pcmformat) : -1; } @@ -679,7 +654,7 @@ int QAlsaAudioInput::notifyInterval() const qint64 QAlsaAudioInput::processedUSecs() const { qint64 result = qint64(1000000) * totalTimeValue / - (settings.channelCount()*(settings.sampleSize()/8)) / + settings.bytesPerFrame() / settings.sampleRate(); return result; diff --git a/src/multimedia/platform/alsa/qalsaaudiooutput.cpp b/src/multimedia/platform/alsa/qalsaaudiooutput.cpp index 327548bdf..0589c254c 100644 --- a/src/multimedia/platform/alsa/qalsaaudiooutput.cpp +++ b/src/multimedia/platform/alsa/qalsaaudiooutput.cpp @@ -166,55 +166,29 @@ int QAlsaAudioOutput::setFormat() { snd_pcm_format_t pcmformat = SND_PCM_FORMAT_UNKNOWN; - if(settings.sampleSize() == 8) { + switch (settings.sampleFormat()) { + case QAudioFormat::UInt8: pcmformat = SND_PCM_FORMAT_U8; - - } else if(settings.sampleSize() == 16) { - if(settings.sampleType() == QAudioFormat::SignedInt) { - if(settings.byteOrder() == QAudioFormat::LittleEndian) - pcmformat = SND_PCM_FORMAT_S16_LE; - else - pcmformat = SND_PCM_FORMAT_S16_BE; - } else if(settings.sampleType() == QAudioFormat::UnSignedInt) { - if(settings.byteOrder() == QAudioFormat::LittleEndian) - pcmformat = SND_PCM_FORMAT_U16_LE; - else - pcmformat = SND_PCM_FORMAT_U16_BE; - } - } else if(settings.sampleSize() == 24) { - if(settings.sampleType() == QAudioFormat::SignedInt) { - if(settings.byteOrder() == QAudioFormat::LittleEndian) - pcmformat = SND_PCM_FORMAT_S24_LE; - else - pcmformat = SND_PCM_FORMAT_S24_BE; - } else if(settings.sampleType() == QAudioFormat::UnSignedInt) { - if(settings.byteOrder() == QAudioFormat::LittleEndian) - pcmformat = SND_PCM_FORMAT_U24_LE; - else - pcmformat = SND_PCM_FORMAT_U24_BE; - } - } else if(settings.sampleSize() == 32) { - if(settings.sampleType() == QAudioFormat::SignedInt) { - if(settings.byteOrder() == QAudioFormat::LittleEndian) - pcmformat = SND_PCM_FORMAT_S32_LE; - else - pcmformat = SND_PCM_FORMAT_S32_BE; - } else if(settings.sampleType() == QAudioFormat::UnSignedInt) { - if(settings.byteOrder() == QAudioFormat::LittleEndian) - pcmformat = SND_PCM_FORMAT_U32_LE; - else - pcmformat = SND_PCM_FORMAT_U32_BE; - } else if(settings.sampleType() == QAudioFormat::Float) { - if(settings.byteOrder() == QAudioFormat::LittleEndian) - pcmformat = SND_PCM_FORMAT_FLOAT_LE; - else - pcmformat = SND_PCM_FORMAT_FLOAT_BE; - } - } else if(settings.sampleSize() == 64) { - if(settings.byteOrder() == QAudioFormat::LittleEndian) - pcmformat = SND_PCM_FORMAT_FLOAT64_LE; + break; + case QAudioFormat::Int16: + if constexpr (QSysInfo::ByteOrder == QSysInfo::BigEndian) + pcmformat = SND_PCM_FORMAT_S16_LE; + else + pcmformat = SND_PCM_FORMAT_S16_BE; + break; + case QAudioFormat::Int32: + if constexpr (QSysInfo::ByteOrder == QSysInfo::BigEndian) + pcmformat = SND_PCM_FORMAT_S32_LE; + else + pcmformat = SND_PCM_FORMAT_S32_BE; + break; + case QAudioFormat::Float: + if constexpr (QSysInfo::ByteOrder == QSysInfo::BigEndian) + pcmformat = SND_PCM_FORMAT_FLOAT_LE; else - pcmformat = SND_PCM_FORMAT_FLOAT64_BE; + pcmformat = SND_PCM_FORMAT_FLOAT_BE; + default: + break; } return pcmformat != SND_PCM_FORMAT_UNKNOWN diff --git a/src/multimedia/platform/alsa/qalsadevicemanager.cpp b/src/multimedia/platform/alsa/qalsadevicemanager.cpp index 20fbe6c53..24662980f 100644 --- a/src/multimedia/platform/alsa/qalsadevicemanager.cpp +++ b/src/multimedia/platform/alsa/qalsadevicemanager.cpp @@ -84,8 +84,7 @@ static QList<QAudioDeviceInfo> availableDevices(QAudio::Mode mode) if ((descr != NULL) && ((io == NULL) || (io == filter))) { auto *infop = new QAlsaAudioDeviceInfo(name, QString::fromUtf8(descr), mode); - QAudioDeviceInfo info(infop); - devices.append(info); + devices.append(infop->create()); if (strcmp(name, "default") == 0) infop->isDefault = true; } diff --git a/src/multimedia/platform/android/audio/qopenslesdeviceinfo.cpp b/src/multimedia/platform/android/audio/qopenslesdeviceinfo.cpp index 5c60ad6f9..dfc9ca0c0 100644 --- a/src/multimedia/platform/android/audio/qopenslesdeviceinfo.cpp +++ b/src/multimedia/platform/android/audio/qopenslesdeviceinfo.cpp @@ -47,59 +47,23 @@ QOpenSLESDeviceInfo::QOpenSLESDeviceInfo(const QByteArray &device, QAudio::Mode : QAudioDeviceInfoPrivate(device, mode), m_engine(QOpenSLESEngine::instance()) { -} - -bool QOpenSLESDeviceInfo::isFormatSupported(const QAudioFormat &format) const -{ - QOpenSLESDeviceInfo *that = const_cast<QOpenSLESDeviceInfo*>(this); - return that->supportedSampleRates().contains(format.sampleRate()) - && that->supportedChannelCounts().contains(format.channelCount()) - && that->supportedSampleSizes().contains(format.sampleSize()) - && that->supportedByteOrders().contains(format.byteOrder()) - && that->supportedSampleTypes().contains(format.sampleType()); -} - -QAudioFormat QOpenSLESDeviceInfo::preferredFormat() const -{ - QAudioFormat format; - format.setSampleSize(16); - format.setSampleType(QAudioFormat::SignedInt); - format.setSampleRate(QOpenSLESEngine::getOutputValue(QOpenSLESEngine::SampleRate, 48000)); - format.setChannelCount(mode == QAudio::AudioInput ? 1 : 2); - return format; -} - -QString QOpenSLESDeviceInfo::deviceName() const -{ - return id; -} - -QList<int> QOpenSLESDeviceInfo::supportedSampleRates() const -{ - return m_engine->supportedSampleRates(mode); -} - -QList<int> QOpenSLESDeviceInfo::supportedChannelCounts() const -{ - return m_engine->supportedChannelCounts(mode); -} + auto channels = m_engine->supportedChannelCounts(mode); + if (channels.size()) + supportedChannelCounts = { channels.first(), channels.last() }; -QList<int> QOpenSLESDeviceInfo::supportedSampleSizes() const -{ + auto sampleRates = m_engine->supportedSampleRates(mode); + if (sampleRates.size()) + supportedSampleRates = { sampleRates.first(), sampleRates.last() }; if (mode == QAudio::AudioInput) - return QList<int>() << 16; - else - return QList<int>() << 8 << 16; -} + supportedSampleFormats.append(QAudioFormat::UInt8); + supportedSampleFormats.append(QAudioFormat::Int16); -QList<QAudioFormat::Endian> QOpenSLESDeviceInfo::supportedByteOrders() const -{ - return QList<QAudioFormat::Endian>() << QAudioFormat::LittleEndian; -} - -QList<QAudioFormat::SampleType> QOpenSLESDeviceInfo::supportedSampleTypes() const -{ - return QList<QAudioFormat::SampleType>() << QAudioFormat::SignedInt; + preferredFormat.setChannelCount(2); + preferredFormat.setSampleRate(48000); + QAudioFormat::SampleFormat f = QAudioFormat::Int16; + if (!supportedSampleFormats.contains(f)) + f = supportedSampleFormats.value(0, QAudioFormat::Unknown); + preferredFormat.setSampleFormat(f); } QT_END_NAMESPACE diff --git a/src/multimedia/platform/android/audio/qopenslesdeviceinfo_p.h b/src/multimedia/platform/android/audio/qopenslesdeviceinfo_p.h index 5d5c36541..692915635 100644 --- a/src/multimedia/platform/android/audio/qopenslesdeviceinfo_p.h +++ b/src/multimedia/platform/android/audio/qopenslesdeviceinfo_p.h @@ -64,16 +64,6 @@ public: QOpenSLESDeviceInfo(const QByteArray &device, QAudio::Mode mode); ~QOpenSLESDeviceInfo() {} - QAudioFormat preferredFormat() const; - bool isFormatSupported(const QAudioFormat &format) const; - QString deviceName() const; - QString description() const { return deviceName(); } - QList<int> supportedSampleRates() const; - QList<int> supportedChannelCounts() const; - QList<int> supportedSampleSizes() const; - QList<QAudioFormat::Endian> supportedByteOrders() const; - QList<QAudioFormat::SampleType> supportedSampleTypes() const; - private: QOpenSLESEngine *m_engine; }; diff --git a/src/multimedia/platform/android/audio/qopenslesengine.cpp b/src/multimedia/platform/android/audio/qopenslesengine.cpp index 87ed1bf14..52a7db9e1 100644 --- a/src/multimedia/platform/android/audio/qopenslesengine.cpp +++ b/src/multimedia/platform/android/audio/qopenslesengine.cpp @@ -91,12 +91,12 @@ SLDataFormat_PCM QOpenSLESEngine::audioFormatToSLFormatPCM(const QAudioFormat &f format_pcm.formatType = SL_DATAFORMAT_PCM; format_pcm.numChannels = format.channelCount(); format_pcm.samplesPerSec = format.sampleRate() * 1000; - format_pcm.bitsPerSample = format.sampleSize(); - format_pcm.containerSize = format.sampleSize(); + format_pcm.bitsPerSample = format.bytesPerSample() * 8; + format_pcm.containerSize = format.bytesPerSample() * 8; format_pcm.channelMask = (format.channelCount() == 1 ? SL_SPEAKER_FRONT_CENTER : SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT); - format_pcm.endianness = (format.byteOrder() == QAudioFormat::LittleEndian ? + format_pcm.endianness = (QSysInfo::ByteOrder == QSysInfo::LittleEndian ? SL_BYTEORDER_LITTLEENDIAN : SL_BYTEORDER_BIGENDIAN); return format_pcm; @@ -108,14 +108,14 @@ QList<QAudioDeviceInfo> QOpenSLESEngine::availableDevices(QAudio::Mode mode) QList<QAudioDeviceInfo> devices; #ifdef ANDROID if (mode == QAudio::AudioInput) { - devices << QAudioDeviceInfo(new QOpenSLESDeviceInfo(QT_ANDROID_PRESET_MIC, mode)) - << QAudioDeviceInfo(new QOpenSLESDeviceInfo(QT_ANDROID_PRESET_CAMCORDER, mode)) - << QAudioDeviceInfo(new QOpenSLESDeviceInfo(QT_ANDROID_PRESET_VOICE_RECOGNITION, mode)) - << QAudioDeviceInfo(new QOpenSLESDeviceInfo(QT_ANDROID_PRESET_VOICE_COMMUNICATION, mode)); + devices << (new QOpenSLESDeviceInfo(QT_ANDROID_PRESET_MIC, mode))->create() + << (new QOpenSLESDeviceInfo(QT_ANDROID_PRESET_CAMCORDER, mode))->create() + << (new QOpenSLESDeviceInfo(QT_ANDROID_PRESET_VOICE_RECOGNITION, mode))->create() + << (new QOpenSLESDeviceInfo(QT_ANDROID_PRESET_VOICE_COMMUNICATION, mode))->create(); return devices; } #endif - devices << QAudioDeviceInfo(new QOpenSLESDeviceInfo("default", mode)); + devices << (new QOpenSLESDeviceInfo("default", mode))->create(); return devices; } @@ -223,11 +223,11 @@ int QOpenSLESEngine::getDefaultBufferSize(const QAudioFormat &format) const int audioFormat = [&format]() -> int { - if (format.sampleType() == QAudioFormat::Float && QtAndroidPrivate::androidSdkVersion() >= 21) + if (format.sampleFormat() == QAudioFormat::Float && QtAndroidPrivate::androidSdkVersion() >= 21) return 4; /* PCM_FLOAT */ - else if (format.sampleSize() == 8) + else if (format.sampleFormat() == QAudioFormat::UInt8) return 3; /* PCM_8BIT */ - else if (format.sampleSize() == 16) + else if (format.sampleFormat() == QAudioFormat::Int16) return 2; /* PCM_16BIT*/ else return 1; /* DEFAULT */ diff --git a/src/multimedia/platform/darwin/audio/qcoreaudiodeviceinfo.mm b/src/multimedia/platform/darwin/audio/qcoreaudiodeviceinfo.mm index 4b0e441f2..66bf49a5a 100644 --- a/src/multimedia/platform/darwin/audio/qcoreaudiodeviceinfo.mm +++ b/src/multimedia/platform/darwin/audio/qcoreaudiodeviceinfo.mm @@ -56,10 +56,15 @@ QCoreAudioDeviceInfo::QCoreAudioDeviceInfo(AudioDeviceID id, const QByteArray &d : QAudioDeviceInfoPrivate(device, mode), m_deviceId(id) { + preferredFormat = determinePreferredFormat(); + description = getDescription(); + supportedSampleRates = { 1, 96000 }; + supportedChannelCounts = { 1, 16 }; + supportedSampleFormats << QAudioFormat::UInt8 << QAudioFormat::Int16 << QAudioFormat::Int32 << QAudioFormat::Float; } -QAudioFormat QCoreAudioDeviceInfo::preferredFormat() const +QAudioFormat QCoreAudioDeviceInfo::determinePreferredFormat() const { QAudioFormat format; @@ -102,32 +107,19 @@ QAudioFormat QCoreAudioDeviceInfo::preferredFormat() const delete[] streams; } } -#else //iOS - format.setSampleSize(16); - format.setSampleRate(44100); - format.setByteOrder(QAudioFormat::LittleEndian); - format.setSampleType(QAudioFormat::SignedInt); - format.setChannelCount(mode == QAudio::AudioInput ? 1 : 2); + if (!format.isValid()) #endif + { + format.setSampleRate(44100); + format.setSampleFormat(QAudioFormat::Int16); + format.setChannelCount(mode == QAudio::AudioInput ? 1 : 2); + } return format; } -bool QCoreAudioDeviceInfo::isFormatSupported(const QAudioFormat &format) const -{ - QCoreAudioDeviceInfo *self = const_cast<QCoreAudioDeviceInfo*>(this); - - //Sample rates are more of a suggestion with CoreAudio so as long as we get a - //sane value then we can likely use it. - return format.isValid() - && format.sampleRate() > 0 - && self->supportedChannelCounts().contains(format.channelCount()) - && self->supportedSampleSizes().contains(format.sampleSize()); -} - - -QString QCoreAudioDeviceInfo::description() const +QString QCoreAudioDeviceInfo::getDescription() const { #ifdef Q_OS_MACOS CFStringRef name; @@ -151,72 +143,4 @@ QString QCoreAudioDeviceInfo::description() const #endif } -QList<int> QCoreAudioDeviceInfo::supportedSampleRates() const -{ - QSet<int> sampleRates; - -#if defined(Q_OS_OSX) - UInt32 propSize = 0; - AudioObjectPropertyScope scope = mode == QAudio::AudioInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput; - AudioObjectPropertyAddress availableNominalSampleRatesAddress = { kAudioDevicePropertyAvailableNominalSampleRates, - scope, - kAudioObjectPropertyElementMaster }; - - if (AudioObjectGetPropertyDataSize(m_deviceId, &availableNominalSampleRatesAddress, 0, NULL, &propSize) == noErr) { - const int pc = propSize / sizeof(AudioValueRange); - - if (pc > 0) { - AudioValueRange* vr = new AudioValueRange[pc]; - - if (AudioObjectGetPropertyData(m_deviceId, &availableNominalSampleRatesAddress, 0, NULL, &propSize, vr) == noErr) { - for (int i = 0; i < pc; ++i) { - sampleRates << vr[i].mMinimum << vr[i].mMaximum; - } - } - - delete[] vr; - } - } -#else //iOS - //iOS doesn't have a way to query available sample rates - //instead we provide reasonable targets - //It may be necessary have CoreAudioSessionManger test combinations - //with available hardware - sampleRates << 8000 << 11025 << 22050 << 44100 << 48000; -#endif - return sampleRates.values(); -} - - -QList<int> QCoreAudioDeviceInfo::supportedChannelCounts() const -{ - static QList<int> supportedChannels; - - if (supportedChannels.isEmpty()) { - // If the number of channels is not supported by an audio device, Core Audio will - // automatically convert the audio data. - for (int i = 1; i <= 16; ++i) - supportedChannels.append(i); - } - - return supportedChannels; -} - - -QList<int> QCoreAudioDeviceInfo::supportedSampleSizes() const -{ - return QList<int>() << 8 << 16 << 24 << 32 << 64; -} - - -QList<QAudioFormat::Endian> QCoreAudioDeviceInfo::supportedByteOrders() const -{ - return QList<QAudioFormat::Endian>() << QAudioFormat::LittleEndian << QAudioFormat::BigEndian; -} - -QList<QAudioFormat::SampleType> QCoreAudioDeviceInfo::supportedSampleTypes() const -{ - return QList<QAudioFormat::SampleType>() << QAudioFormat::SignedInt << QAudioFormat::UnSignedInt << QAudioFormat::Float; -} - QT_END_NAMESPACE diff --git a/src/multimedia/platform/darwin/audio/qcoreaudiodeviceinfo_p.h b/src/multimedia/platform/darwin/audio/qcoreaudiodeviceinfo_p.h index 5fe600909..80da914a1 100644 --- a/src/multimedia/platform/darwin/audio/qcoreaudiodeviceinfo_p.h +++ b/src/multimedia/platform/darwin/audio/qcoreaudiodeviceinfo_p.h @@ -65,17 +65,12 @@ public: QCoreAudioDeviceInfo(AudioDeviceID id, const QByteArray &device, QAudio::Mode mode); ~QCoreAudioDeviceInfo() {} - QAudioFormat preferredFormat() const; bool isFormatSupported(const QAudioFormat &format) const; - QString description() const; - QList<int> supportedSampleRates() const; - QList<int> supportedChannelCounts() const; - QList<int> supportedSampleSizes() const; - QList<QAudioFormat::Endian> supportedByteOrders() const; - QList<QAudioFormat::SampleType> supportedSampleTypes() const; AudioDeviceID deviceID() const { return m_deviceId; } private: + QAudioFormat determinePreferredFormat() const; + QString getDescription() const; #if defined(Q_OS_OSX) AudioDeviceID m_deviceId; #endif diff --git a/src/multimedia/platform/darwin/audio/qcoreaudiooutput.mm b/src/multimedia/platform/darwin/audio/qcoreaudiooutput.mm index d432aa55f..f79bce38c 100644 --- a/src/multimedia/platform/darwin/audio/qcoreaudiooutput.mm +++ b/src/multimedia/platform/darwin/audio/qcoreaudiooutput.mm @@ -67,7 +67,7 @@ QCoreAudioOutputBuffer::QCoreAudioOutputBuffer(int bufferSize, int maxPeriodSize , m_device(0) { m_buffer = new CoreAudioRingBuffer(bufferSize + (bufferSize % maxPeriodSize == 0 ? 0 : maxPeriodSize - (bufferSize % maxPeriodSize))); - m_bytesPerFrame = (audioFormat.sampleSize() / 8) * audioFormat.channelCount(); + m_bytesPerFrame = audioFormat.bytesPerFrame(); m_periodTime = m_maxPeriodSize / m_bytesPerFrame * 1000 / audioFormat.sampleRate(); m_fillTimer = new QTimer(this); diff --git a/src/multimedia/platform/darwin/audio/qcoreaudioutils.mm b/src/multimedia/platform/darwin/audio/qcoreaudioutils.mm index 065bff707..6b0721b60 100644 --- a/src/multimedia/platform/darwin/audio/qcoreaudioutils.mm +++ b/src/multimedia/platform/darwin/audio/qcoreaudioutils.mm @@ -71,17 +71,36 @@ double CoreAudioUtils::frequency() QAudioFormat CoreAudioUtils::toQAudioFormat(AudioStreamBasicDescription const& sf) { QAudioFormat audioFormat; + // all Darwin HW is little endian, we ignore those formats + if ((sf.mFormatFlags & kAudioFormatFlagIsBigEndian) != 0 && QSysInfo::ByteOrder != QSysInfo::LittleEndian) + return audioFormat; + + // filter out the formats we're interested in + QAudioFormat::SampleFormat format = QAudioFormat::Unknown; + switch (sf.mBitsPerChannel) { + case 8: + if ((sf.mFormatFlags & kAudioFormatFlagIsSignedInteger) == 0) + format = QAudioFormat::UInt8; + break; + case 16: + if ((sf.mFormatFlags & kAudioFormatFlagIsSignedInteger) != 0) + format = QAudioFormat::Int16; + break; + case 32: + if ((sf.mFormatFlags & kAudioFormatFlagIsSignedInteger) != 0) + format = QAudioFormat::Int32; + else if ((sf.mFormatFlags & kAudioFormatFlagIsFloat) != 0) + format = QAudioFormat::Float; + break; + default: + break; + } + + if (format == QAudioFormat::Unknown) + return audioFormat; audioFormat.setSampleRate(sf.mSampleRate); audioFormat.setChannelCount(sf.mChannelsPerFrame); - audioFormat.setSampleSize(sf.mBitsPerChannel); - audioFormat.setByteOrder((sf.mFormatFlags & kAudioFormatFlagIsBigEndian) != 0 ? QAudioFormat::BigEndian : QAudioFormat::LittleEndian); - QAudioFormat::SampleType type = QAudioFormat::UnSignedInt; - if ((sf.mFormatFlags & kAudioFormatFlagIsSignedInteger) != 0) - type = QAudioFormat::SignedInt; - else if ((sf.mFormatFlags & kAudioFormatFlagIsFloat) != 0) - type = QAudioFormat::Float; - audioFormat.setSampleType(type); return audioFormat; } @@ -94,21 +113,25 @@ AudioStreamBasicDescription CoreAudioUtils::toAudioStreamBasicDescription(QAudio sf.mSampleRate = audioFormat.sampleRate(); sf.mFramesPerPacket = 1; sf.mChannelsPerFrame = audioFormat.channelCount(); - sf.mBitsPerChannel = audioFormat.sampleSize(); - sf.mBytesPerFrame = sf.mChannelsPerFrame * (sf.mBitsPerChannel / 8); + sf.mBitsPerChannel = audioFormat.bytesPerSample() * 8; + sf.mBytesPerFrame = audioFormat.bytesPerFrame(); sf.mBytesPerPacket = sf.mFramesPerPacket * sf.mBytesPerFrame; sf.mFormatID = kAudioFormatLinearPCM; - switch (audioFormat.sampleType()) { - case QAudioFormat::SignedInt: sf.mFormatFlags |= kAudioFormatFlagIsSignedInteger; break; - case QAudioFormat::UnSignedInt: /* default */ break; - case QAudioFormat::Float: sf.mFormatFlags |= kAudioFormatFlagIsFloat; break; - case QAudioFormat::Unknown: default: break; + switch (audioFormat.sampleFormat()) { + case QAudioFormat::Int16: + case QAudioFormat::Int32: + sf.mFormatFlags |= kAudioFormatFlagIsSignedInteger; + break; + case QAudioFormat::Float: + sf.mFormatFlags |= kAudioFormatFlagIsFloat; + break; + case QAudioFormat::UInt8: + /* default */ + case QAudioFormat::Unknown: + break; } - if (audioFormat.byteOrder() == QAudioFormat::BigEndian) - sf.mFormatFlags |= kAudioFormatFlagIsBigEndian; - return sf; } diff --git a/src/multimedia/platform/darwin/qdarwindevicemanager.mm b/src/multimedia/platform/darwin/qdarwindevicemanager.mm index ca3babb6c..04802cb99 100644 --- a/src/multimedia/platform/darwin/qdarwindevicemanager.mm +++ b/src/multimedia/platform/darwin/qdarwindevicemanager.mm @@ -103,7 +103,7 @@ QList<QAudioDeviceInfo> availableAudioDevices(QAudio::Mode mode) QList<QAudioDeviceInfo> devices; AudioDeviceID defaultDevice = defaultAudioDevice(mode); - devices << QAudioDeviceInfo(new QCoreAudioDeviceInfo(defaultDevice, uniqueId(defaultDevice, mode), mode)); + devices << (new QCoreAudioDeviceInfo(defaultDevice, uniqueId(defaultDevice, mode), mode))->create(); UInt32 propSize = 0; AudioObjectPropertyAddress audioDevicesPropertyAddress = { kAudioHardwarePropertyDevices, @@ -131,7 +131,7 @@ QList<QAudioDeviceInfo> availableAudioDevices(QAudio::Mode mode) kAudioObjectPropertyElementMaster }; if (AudioObjectGetPropertyData(audioDevices[i], &audioDeviceStreamFormatPropertyAddress, 0, NULL, &size, &sf) == noErr) - devices << QAudioDeviceInfo(new QCoreAudioDeviceInfo(audioDevices[i], uniqueId(audioDevices[i], mode), mode)); + devices << (new QCoreAudioDeviceInfo(audioDevices[i], uniqueId(audioDevices[i], mode), mode))->create(); } } diff --git a/src/multimedia/platform/gstreamer/audio/qaudiodeviceinfo_gstreamer.cpp b/src/multimedia/platform/gstreamer/audio/qaudiodeviceinfo_gstreamer.cpp index 19e5aefdf..68279a25a 100644 --- a/src/multimedia/platform/gstreamer/audio/qaudiodeviceinfo_gstreamer.cpp +++ b/src/multimedia/platform/gstreamer/audio/qaudiodeviceinfo_gstreamer.cpp @@ -54,8 +54,30 @@ QGStreamerAudioDeviceInfo::QGStreamerAudioDeviceInfo(const QByteArray &device, Q if (gstDevice) { gst_object_ref(gstDevice); auto *n = gst_device_get_display_name(gstDevice); - m_description = QString::fromUtf8(n); + description = QString::fromUtf8(n); g_free(n); + + QGstCaps caps = gst_device_get_caps(gstDevice); + int size = caps.size(); + for (int i = 0; i < size; ++i) { + auto c = caps.at(i); + if (c.name() == "audio/x-raw") { + auto rate = c["rate"].toIntRange(); + if (rate) + supportedSampleRates = { rate->min, rate->max }; + auto channels = c["channels"].toIntRange(); + if (channels) + supportedChannelCounts = { channels->min, channels->max }; + supportedSampleFormats = c["format"].getSampleFormats(); + } + } + + preferredFormat.setChannelCount(qBound(supportedChannelCounts.minimum, 2, supportedChannelCounts.maximum)); + preferredFormat.setSampleRate(qBound(supportedSampleRates.minimum, 48000, supportedSampleRates.maximum)); + QAudioFormat::SampleFormat f = QAudioFormat::Int16; + if (!supportedSampleFormats.contains(f)) + f = supportedSampleFormats.value(0, QAudioFormat::Unknown); + preferredFormat.setSampleFormat(f); } } @@ -65,50 +87,4 @@ QGStreamerAudioDeviceInfo::~QGStreamerAudioDeviceInfo() gst_object_unref(gstDevice); } -bool QGStreamerAudioDeviceInfo::isFormatSupported(const QAudioFormat &) const -{ - // #### - return true; -} - -QAudioFormat QGStreamerAudioDeviceInfo::preferredFormat() const -{ - QAudioFormat format; - format.setByteOrder(QAudioFormat::LittleEndian); - format.setChannelCount(2); - format.setSampleRate(48000); - format.setSampleSize(16); - return format; -} - -QString QGStreamerAudioDeviceInfo::description() const -{ - return m_description; -} - -QList<int> QGStreamerAudioDeviceInfo::supportedSampleRates() const -{ - return QList<int>() << 8000 << 11025 << 22050 << 44100 << 48000; -} - -QList<int> QGStreamerAudioDeviceInfo::supportedChannelCounts() const -{ - return QList<int>() << 1 << 2 << 4 << 6 << 8; -} - -QList<int> QGStreamerAudioDeviceInfo::supportedSampleSizes() const -{ - return QList<int>() << 8 << 16 << 24 << 32; -} - -QList<QAudioFormat::Endian> QGStreamerAudioDeviceInfo::supportedByteOrders() const -{ - return QList<QAudioFormat::Endian>() << QAudioFormat::BigEndian << QAudioFormat::LittleEndian; -} - -QList<QAudioFormat::SampleType> QGStreamerAudioDeviceInfo::supportedSampleTypes() const -{ - return QList<QAudioFormat::SampleType>() << QAudioFormat::SignedInt << QAudioFormat::UnSignedInt << QAudioFormat::Float; -} - QT_END_NAMESPACE diff --git a/src/multimedia/platform/gstreamer/audio/qaudiodeviceinfo_gstreamer_p.h b/src/multimedia/platform/gstreamer/audio/qaudiodeviceinfo_gstreamer_p.h index 79cd1a51d..72df0c43d 100644 --- a/src/multimedia/platform/gstreamer/audio/qaudiodeviceinfo_gstreamer_p.h +++ b/src/multimedia/platform/gstreamer/audio/qaudiodeviceinfo_gstreamer_p.h @@ -69,16 +69,6 @@ public: QGStreamerAudioDeviceInfo(const QByteArray &device, QAudio::Mode mode); ~QGStreamerAudioDeviceInfo(); - QAudioFormat preferredFormat() const override; - bool isFormatSupported(const QAudioFormat &format) const override; - QString description() const override; - QList<int> supportedSampleRates() const override; - QList<int> supportedChannelCounts() const override; - QList<int> supportedSampleSizes() const override; - QList<QAudioFormat::Endian> supportedByteOrders() const override; - QList<QAudioFormat::SampleType> supportedSampleTypes() const override; - - QString m_description; GstDevice *gstDevice = nullptr; }; diff --git a/src/multimedia/platform/gstreamer/audio/qaudiooutput_gstreamer.cpp b/src/multimedia/platform/gstreamer/audio/qaudiooutput_gstreamer.cpp index eaa4c52f2..a221fcf85 100644 --- a/src/multimedia/platform/gstreamer/audio/qaudiooutput_gstreamer.cpp +++ b/src/multimedia/platform/gstreamer/audio/qaudiooutput_gstreamer.cpp @@ -286,7 +286,7 @@ int QGStreamerAudioOutput::bytesFree() const int QGStreamerAudioOutput::periodSize() const { // max 5ms periods. Gstreamer itself will ask for 4k data at a time - return qMin(4096, 5*m_format.sampleRate()*m_format.sampleSize()*m_format.channelCount()/8/1000); + return qMin(4096, 5*m_format.sampleRate()*m_format.bytesPerFrame()/1000); } void QGStreamerAudioOutput::setBufferSize(int value) @@ -314,7 +314,7 @@ int QGStreamerAudioOutput::notifyInterval() const qint64 QGStreamerAudioOutput::processedUSecs() const { qint64 result = qint64(1000000) * m_totalTimeValue / - (m_format.channelCount() * (m_format.sampleSize() / 8)) / + m_format.bytesPerFrame() / m_format.sampleRate(); return result; diff --git a/src/multimedia/platform/gstreamer/common/qgstutils.cpp b/src/multimedia/platform/gstreamer/common/qgstutils.cpp index 5f1c64333..694bc751f 100644 --- a/src/multimedia/platform/gstreamer/common/qgstutils.cpp +++ b/src/multimedia/platform/gstreamer/common/qgstutils.cpp @@ -219,35 +219,33 @@ QSize QGstUtils::capsCorrectedResolution(const GstCaps *caps) namespace { -struct AudioFormat -{ - GstAudioFormat format; - QAudioFormat::SampleType sampleType; - QAudioFormat::Endian byteOrder; - int sampleSize; -}; -static const AudioFormat qt_audioLookup[] = -{ - { GST_AUDIO_FORMAT_S8 , QAudioFormat::SignedInt , QAudioFormat::LittleEndian, 8 }, - { GST_AUDIO_FORMAT_U8 , QAudioFormat::UnSignedInt, QAudioFormat::LittleEndian, 8 }, - { GST_AUDIO_FORMAT_S16LE, QAudioFormat::SignedInt , QAudioFormat::LittleEndian, 16 }, - { GST_AUDIO_FORMAT_S16BE, QAudioFormat::SignedInt , QAudioFormat::BigEndian , 16 }, - { GST_AUDIO_FORMAT_U16LE, QAudioFormat::UnSignedInt, QAudioFormat::LittleEndian, 16 }, - { GST_AUDIO_FORMAT_U16BE, QAudioFormat::UnSignedInt, QAudioFormat::BigEndian , 16 }, - { GST_AUDIO_FORMAT_S32LE, QAudioFormat::SignedInt , QAudioFormat::LittleEndian, 32 }, - { GST_AUDIO_FORMAT_S32BE, QAudioFormat::SignedInt , QAudioFormat::BigEndian , 32 }, - { GST_AUDIO_FORMAT_U32LE, QAudioFormat::UnSignedInt, QAudioFormat::LittleEndian, 32 }, - { GST_AUDIO_FORMAT_U32BE, QAudioFormat::UnSignedInt, QAudioFormat::BigEndian , 32 }, - { GST_AUDIO_FORMAT_S24LE, QAudioFormat::SignedInt , QAudioFormat::LittleEndian, 24 }, - { GST_AUDIO_FORMAT_S24BE, QAudioFormat::SignedInt , QAudioFormat::BigEndian , 24 }, - { GST_AUDIO_FORMAT_U24LE, QAudioFormat::UnSignedInt, QAudioFormat::LittleEndian, 24 }, - { GST_AUDIO_FORMAT_U24BE, QAudioFormat::UnSignedInt, QAudioFormat::BigEndian , 24 }, - { GST_AUDIO_FORMAT_F32LE, QAudioFormat::Float , QAudioFormat::LittleEndian, 32 }, - { GST_AUDIO_FORMAT_F32BE, QAudioFormat::Float , QAudioFormat::BigEndian , 32 }, - { GST_AUDIO_FORMAT_F64LE, QAudioFormat::Float , QAudioFormat::LittleEndian, 64 }, - { GST_AUDIO_FORMAT_F64BE, QAudioFormat::Float , QAudioFormat::BigEndian , 64 } +static const char *audioSampleFormatNames[QAudioFormat::NSampleFormats] = { + nullptr, +#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN + "U8", + "S16LE", + "S32LE", + "F32LE" +#else + "U8", + "S16BE", + "S32BE", + "F32BE" +#endif }; +static QAudioFormat::SampleFormat gstSampleFormatToSampleFormat(const char *fmt) +{ + if (fmt) { + for (int i = 1; i < QAudioFormat::NSampleFormats; ++i) { + if (strcmp(fmt, audioSampleFormatNames[i])) + continue; + return QAudioFormat::SampleFormat(i); + } + } + return QAudioFormat::Unknown; +} + } /*! @@ -258,21 +256,19 @@ static const AudioFormat qt_audioLookup[] = QAudioFormat QGstUtils::audioFormatForCaps(const GstCaps *caps) { QAudioFormat format; - GstAudioInfo info; - if (gst_audio_info_from_caps(&info, caps)) { - for (int i = 0; i < lengthOf(qt_audioLookup); ++i) { - if (qt_audioLookup[i].format != info.finfo->format) - continue; + QGstStructure s = QGstCaps(caps).at(0); + if (s.name() != "audio/x-raw") + return format; - format.setSampleType(qt_audioLookup[i].sampleType); - format.setByteOrder(qt_audioLookup[i].byteOrder); - format.setSampleSize(qt_audioLookup[i].sampleSize); - format.setSampleRate(info.rate); - format.setChannelCount(info.channels); + auto rate = s["rate"].toInt(); + auto channels = s["channels"].toInt(); + QAudioFormat::SampleFormat fmt = gstSampleFormatToSampleFormat(s["format"].toString()); + if (!rate || !channels || fmt == QAudioFormat::Unknown) + return format; - return format; - } - } + format.setSampleRate(*rate); + format.setChannelCount(*channels); + format.setSampleFormat(fmt); return format; } @@ -301,26 +297,32 @@ GstCaps *QGstUtils::capsForAudioFormat(const QAudioFormat &format) if (!format.isValid()) return 0; - const QAudioFormat::SampleType sampleType = format.sampleType(); - const QAudioFormat::Endian byteOrder = format.byteOrder(); - const int sampleSize = format.sampleSize(); + auto sampleFormat = format.sampleFormat(); + return gst_caps_new_simple( + "audio/x-raw", + "format" , G_TYPE_STRING, audioSampleFormatNames[sampleFormat], + "rate" , G_TYPE_INT , format.sampleRate(), + "channels", G_TYPE_INT , format.channelCount(), + "layout" , G_TYPE_STRING, "interleaved", + nullptr); +} - for (int i = 0; i < lengthOf(qt_audioLookup); ++i) { - if (qt_audioLookup[i].sampleType != sampleType - || qt_audioLookup[i].byteOrder != byteOrder - || qt_audioLookup[i].sampleSize != sampleSize) { - continue; - } +QList<QAudioFormat::SampleFormat> QGValue::getSampleFormats() const +{ + if (!GST_VALUE_HOLDS_LIST(value)) + return {}; - return gst_caps_new_simple( - "audio/x-raw", - "format" , G_TYPE_STRING, gst_audio_format_to_string(qt_audioLookup[i].format), - "rate" , G_TYPE_INT , format.sampleRate(), - "channels", G_TYPE_INT , format.channelCount(), - "layout" , G_TYPE_STRING, "interleaved", - nullptr); + QList<QAudioFormat::SampleFormat> formats; + guint nFormats = gst_value_list_get_size(value); + for (guint f = 0; f < nFormats; ++f) { + QGValue v = gst_value_list_get_value(value, f); + auto *name = v.toString(); + QAudioFormat::SampleFormat fmt = gstSampleFormatToSampleFormat(name); + if (fmt == QAudioFormat::Unknown) + continue;; + formats.append(fmt); } - return 0; + return formats; } void QGstUtils::initializeGst() diff --git a/src/multimedia/platform/gstreamer/common/qgstutils_p.h b/src/multimedia/platform/gstreamer/common/qgstutils_p.h index bcc5ac4f4..75c525771 100644 --- a/src/multimedia/platform/gstreamer/common/qgstutils_p.h +++ b/src/multimedia/platform/gstreamer/common/qgstutils_p.h @@ -163,13 +163,14 @@ public: return QGRange<float>{ *min.getFraction(), *max.getFraction() }; } - std::optional<QGRange<int>> getIntRange() const + std::optional<QGRange<int>> toIntRange() const { if (!GST_VALUE_HOLDS_INT_RANGE(value)) return std::nullopt; return QGRange<int>{ gst_value_get_int_range_min(value), gst_value_get_int_range_max(value) }; } + Q_MULTIMEDIA_EXPORT QList<QAudioFormat::SampleFormat> getSampleFormats() const; }; class QGstStructure { @@ -188,7 +189,6 @@ public: Q_MULTIMEDIA_EXPORT QVideoFrame::PixelFormat pixelFormat() const; Q_MULTIMEDIA_EXPORT QSize pixelAspectRatio() const; Q_MULTIMEDIA_EXPORT QGRange<float> frameRateRange() const; - }; class QGstCaps { diff --git a/src/multimedia/platform/gstreamer/qgstreamerdevicemanager.cpp b/src/multimedia/platform/gstreamer/qgstreamerdevicemanager.cpp index f3707ffad..5250c6e69 100644 --- a/src/multimedia/platform/gstreamer/qgstreamerdevicemanager.cpp +++ b/src/multimedia/platform/gstreamer/qgstreamerdevicemanager.cpp @@ -111,11 +111,11 @@ static QList<QAudioDeviceInfo> devicesFromSet(const QSet<GstDevice *> &deviceSet if (strcmp(klass, "monitor")) { auto *name = gst_structure_get_string(properties, "sysfs.path"); gboolean def; - QAudioDeviceInfo info(new QGStreamerAudioDeviceInfo(name, mode)); + auto *info = new QGStreamerAudioDeviceInfo(name, mode); if (gst_structure_get_boolean(properties, "is-default", &def) && def) - devices.prepend(info); + devices.prepend(info->create()); else - devices.append(info); + devices.append(info->create()); } gst_structure_free(properties); diff --git a/src/multimedia/platform/pulseaudio/qaudiodeviceinfo_pulse.cpp b/src/multimedia/platform/pulseaudio/qaudiodeviceinfo_pulse.cpp index d9a01750c..5f8fad2ae 100644 --- a/src/multimedia/platform/pulseaudio/qaudiodeviceinfo_pulse.cpp +++ b/src/multimedia/platform/pulseaudio/qaudiodeviceinfo_pulse.cpp @@ -43,54 +43,43 @@ QT_BEGIN_NAMESPACE -QPulseAudioDeviceInfo::QPulseAudioDeviceInfo(const char *device, const char *description, bool isDef, QAudio::Mode mode) - : QAudioDeviceInfoPrivate(device, mode), - m_description(QString::fromUtf8(description)) +QPulseAudioDeviceInfo::QPulseAudioDeviceInfo(const char *device, const char *desc, bool isDef, QAudio::Mode mode) + : QAudioDeviceInfoPrivate(device, mode) { + description = QString::fromUtf8(desc); isDefault = isDef; -} -bool QPulseAudioDeviceInfo::isFormatSupported(const QAudioFormat &format) const -{ - pa_sample_spec spec = QPulseAudioInternal::audioFormatToSampleSpec(format); - return pa_sample_spec_valid(&spec) != 0; -} - -QAudioFormat QPulseAudioDeviceInfo::preferredFormat() const -{ - QPulseAudioEngine *pulseEngine = QPulseAudioEngine::instance(); - QAudioFormat format = pulseEngine->m_preferredFormats.value(id); - return format; -} - -QString QPulseAudioDeviceInfo::description() const -{ - return m_description; -} + supportedChannelCounts = { 1, PA_CHANNELS_MAX }; + supportedSampleRates = { 1, PA_RATE_MAX }; -QList<int> QPulseAudioDeviceInfo::supportedSampleRates() const -{ - return QList<int>() << 8000 << 11025 << 22050 << 44100 << 48000; -} + constexpr bool isBigEndian = QSysInfo::ByteOrder == QSysInfo::BigEndian; -QList<int> QPulseAudioDeviceInfo::supportedChannelCounts() const -{ - return QList<int>() << 1 << 2 << 4 << 6 << 8; -} + const struct { + pa_sample_format pa_fmt; + QAudioFormat::SampleFormat qt_fmt; + } formatMap[] = { + { PA_SAMPLE_U8, QAudioFormat::UInt8 }, + { isBigEndian ? PA_SAMPLE_S16BE : PA_SAMPLE_S16LE, QAudioFormat::Int16 }, + { isBigEndian ? PA_SAMPLE_S32BE : PA_SAMPLE_S32LE, QAudioFormat::Int32 }, + { isBigEndian ? PA_SAMPLE_FLOAT32BE : PA_SAMPLE_FLOAT32LE, QAudioFormat::Float }, + }; -QList<int> QPulseAudioDeviceInfo::supportedSampleSizes() const -{ - return QList<int>() << 8 << 16 << 24 << 32; -} + pa_sample_spec spec; + spec.channels = 1; + spec.rate = 48000; -QList<QAudioFormat::Endian> QPulseAudioDeviceInfo::supportedByteOrders() const -{ - return QList<QAudioFormat::Endian>() << QAudioFormat::BigEndian << QAudioFormat::LittleEndian; -} + for (const auto &f : formatMap) { + spec.format = f.pa_fmt; + if (pa_sample_spec_valid(&spec) != 0) + supportedSampleFormats.append(f.qt_fmt); + } -QList<QAudioFormat::SampleType> QPulseAudioDeviceInfo::supportedSampleTypes() const -{ - return QList<QAudioFormat::SampleType>() << QAudioFormat::SignedInt << QAudioFormat::UnSignedInt << QAudioFormat::Float; + preferredFormat.setChannelCount(2); + preferredFormat.setSampleRate(48000); + QAudioFormat::SampleFormat f = QAudioFormat::Int16; + if (!supportedSampleFormats.contains(f)) + f = supportedSampleFormats.value(0, QAudioFormat::Unknown); + preferredFormat.setSampleFormat(f); } QT_END_NAMESPACE diff --git a/src/multimedia/platform/pulseaudio/qaudiodeviceinfo_pulse_p.h b/src/multimedia/platform/pulseaudio/qaudiodeviceinfo_pulse_p.h index ffc7d16df..2178f4c6c 100644 --- a/src/multimedia/platform/pulseaudio/qaudiodeviceinfo_pulse_p.h +++ b/src/multimedia/platform/pulseaudio/qaudiodeviceinfo_pulse_p.h @@ -67,17 +67,6 @@ class QPulseAudioDeviceInfo : public QAudioDeviceInfoPrivate public: QPulseAudioDeviceInfo(const char *device, const char *description, bool isDefault, QAudio::Mode mode); ~QPulseAudioDeviceInfo() {} - - QAudioFormat preferredFormat() const override; - bool isFormatSupported(const QAudioFormat &format) const override; - QString description() const override; - QList<int> supportedSampleRates() const override; - QList<int> supportedChannelCounts() const override; - QList<int> supportedSampleSizes() const override; - QList<QAudioFormat::Endian> supportedByteOrders() const override; - QList<QAudioFormat::SampleType> supportedSampleTypes() const override; - - QString m_description; }; QT_END_NAMESPACE diff --git a/src/multimedia/platform/pulseaudio/qaudioengine_pulse.cpp b/src/multimedia/platform/pulseaudio/qaudioengine_pulse.cpp index 50152395f..32d105f99 100644 --- a/src/multimedia/platform/pulseaudio/qaudioengine_pulse.cpp +++ b/src/multimedia/platform/pulseaudio/qaudioengine_pulse.cpp @@ -123,13 +123,10 @@ static void sinkInfoCallback(pa_context *context, const pa_sink_info *info, int info->description); #endif - QAudioFormat format = QPulseAudioInternal::sampleSpecToAudioFormat(info->sample_spec); - QWriteLocker locker(&pulseEngine->m_sinkLock); - pulseEngine->m_preferredFormats.insert(info->name, format); bool isDefault = pulseEngine->m_defaultSink == info->name; - QAudioDeviceInfo dinfo(new QPulseAudioDeviceInfo(info->name, info->description, isDefault, QAudio::AudioOutput)); - pulseEngine->m_sinks.insert(info->index, dinfo); + auto *dinfo = new QPulseAudioDeviceInfo(info->name, info->description, isDefault, QAudio::AudioOutput); + pulseEngine->m_sinks.insert(info->index, dinfo->create()); } static void sourceInfoCallback(pa_context *context, const pa_source_info *info, int isLast, void *userdata) @@ -161,15 +158,13 @@ static void sourceInfoCallback(pa_context *context, const pa_source_info *info, info->description); #endif - QAudioFormat format = QPulseAudioInternal::sampleSpecToAudioFormat(info->sample_spec); - QWriteLocker locker(&pulseEngine->m_sourceLock); // skip monitor channels if (info->monitor_of_sink != PA_INVALID_INDEX) return; bool isDefault = pulseEngine->m_defaultSink == info->name; - QAudioDeviceInfo dinfo(new QPulseAudioDeviceInfo(info->name, info->description, isDefault, QAudio::AudioInput)); - pulseEngine->m_sources.insert(info->index, dinfo); + auto *dinfo = new QPulseAudioDeviceInfo(info->name, info->description, isDefault, QAudio::AudioInput); + pulseEngine->m_sources.insert(info->index, dinfo->create()); } static void event_cb(pa_context* context, pa_subscription_event_type_t t, uint32_t index, void* userdata) @@ -215,13 +210,11 @@ static void event_cb(pa_context* context, pa_subscription_event_type_t t, uint32 switch (facility) { case PA_SUBSCRIPTION_EVENT_SINK: pulseEngine->m_sinkLock.lockForWrite(); - pulseEngine->m_preferredFormats.remove(pulseEngine->m_sinks.value(index).id()); pulseEngine->m_sinks.remove(index); pulseEngine->m_sinkLock.unlock(); break; case PA_SUBSCRIPTION_EVENT_SOURCE: pulseEngine->m_sourceLock.lockForWrite(); - pulseEngine->m_preferredFormats.remove(pulseEngine->m_sources.value(index).id()); pulseEngine->m_sources.remove(index); pulseEngine->m_sourceLock.unlock(); break; diff --git a/src/multimedia/platform/pulseaudio/qaudioengine_pulse_p.h b/src/multimedia/platform/pulseaudio/qaudioengine_pulse_p.h index 8fc949b65..8d48b3b68 100644 --- a/src/multimedia/platform/pulseaudio/qaudioengine_pulse_p.h +++ b/src/multimedia/platform/pulseaudio/qaudioengine_pulse_p.h @@ -107,7 +107,6 @@ private: public: QMap<int, QAudioDeviceInfo> m_sinks; QMap<int, QAudioDeviceInfo> m_sources; - QMap<QByteArray, QAudioFormat> m_preferredFormats; QByteArray m_defaultSink; QByteArray m_defaultSource; diff --git a/src/multimedia/platform/pulseaudio/qaudiooutput_pulse.cpp b/src/multimedia/platform/pulseaudio/qaudiooutput_pulse.cpp index 7466f5b46..b5adccd85 100644 --- a/src/multimedia/platform/pulseaudio/qaudiooutput_pulse.cpp +++ b/src/multimedia/platform/pulseaudio/qaudiooutput_pulse.cpp @@ -304,7 +304,7 @@ bool QPulseAudioOutput::open() pulseEngine->lock(); - qint64 bytesPerSecond = m_format.sampleRate() * m_format.channelCount() * m_format.sampleSize() / 8; + qint64 bytesPerSecond = m_format.sampleRate() * m_format.bytesPerFrame(); pa_proplist *propList = pa_proplist_new(); if (!m_category.isNull()) @@ -591,9 +591,7 @@ int QPulseAudioOutput::notifyInterval() const qint64 QPulseAudioOutput::processedUSecs() const { - qint64 result = qint64(1000000) * m_totalTimeValue / - (m_format.channelCount() * (m_format.sampleSize() / 8)) / - m_format.sampleRate(); + qint64 result = qint64(1000000) * m_totalTimeValue / m_format.bytesPerFrame() / m_format.sampleRate(); return result; } diff --git a/src/multimedia/platform/pulseaudio/qpulsehelpers.cpp b/src/multimedia/platform/pulseaudio/qpulsehelpers.cpp index 56ebbc4e4..c3ca6f8c9 100644 --- a/src/multimedia/platform/pulseaudio/qpulsehelpers.cpp +++ b/src/multimedia/platform/pulseaudio/qpulsehelpers.cpp @@ -50,22 +50,16 @@ pa_sample_spec audioFormatToSampleSpec(const QAudioFormat &format) spec.rate = format.sampleRate(); spec.channels = format.channelCount(); spec.format = PA_SAMPLE_INVALID; - const bool isBigEndian = (format.byteOrder() == QAudioFormat::BigEndian); - - if (format.sampleType() == QAudioFormat::UnSignedInt) { - if (format.sampleSize() == 8) - spec.format = PA_SAMPLE_U8; - } else if (format.sampleType() == QAudioFormat::SignedInt) { - if (format.sampleSize() == 16) { - spec.format = isBigEndian ? PA_SAMPLE_S16BE : PA_SAMPLE_S16LE; - } else if (format.sampleSize() == 24) { - spec.format = isBigEndian ? PA_SAMPLE_S24BE : PA_SAMPLE_S24LE; - } else if (format.sampleSize() == 32) { - spec.format = isBigEndian ? PA_SAMPLE_S32BE : PA_SAMPLE_S32LE; - } - } else if (format.sampleType() == QAudioFormat::Float) { - if (format.sampleSize() == 32) - spec.format = isBigEndian ? PA_SAMPLE_FLOAT32BE : PA_SAMPLE_FLOAT32LE; + const bool isBigEndian = QSysInfo::ByteOrder == QSysInfo::BigEndian; + + if (format.sampleFormat() == QAudioFormat::UInt8) { + spec.format = PA_SAMPLE_U8; + } else if (format.sampleFormat() == QAudioFormat::Int16) { + spec.format = isBigEndian ? PA_SAMPLE_S16BE : PA_SAMPLE_S16LE; + } else if (format.sampleFormat() == QAudioFormat::Int32) { + spec.format = isBigEndian ? PA_SAMPLE_S32BE : PA_SAMPLE_S32LE; + } else if (format.sampleFormat() == QAudioFormat::Float) { + spec.format = isBigEndian ? PA_SAMPLE_FLOAT32BE : PA_SAMPLE_FLOAT32LE; } return spec; @@ -127,85 +121,6 @@ QString stateToQString(pa_context_state_t state) } #endif -QAudioFormat sampleSpecToAudioFormat(pa_sample_spec spec) -{ - QAudioFormat format; - format.setSampleRate(spec.rate); - format.setChannelCount(spec.channels); - format.setCodec(QString::fromLatin1("audio/x-raw")); - - switch (spec.format) { - case PA_SAMPLE_U8: - format.setByteOrder(QAudioFormat::LittleEndian); - format.setSampleType(QAudioFormat::UnSignedInt); - format.setSampleSize(8); - break; - case PA_SAMPLE_ALAW: - // TODO: - break; - case PA_SAMPLE_ULAW: - // TODO: - break; - case PA_SAMPLE_S16LE: - format.setByteOrder(QAudioFormat::LittleEndian); - format.setSampleType(QAudioFormat::SignedInt); - format.setSampleSize(16); - break; - case PA_SAMPLE_S16BE: - format.setByteOrder(QAudioFormat::BigEndian); - format.setSampleType(QAudioFormat::SignedInt); - format.setSampleSize(16); - break; - case PA_SAMPLE_FLOAT32LE: - format.setByteOrder(QAudioFormat::LittleEndian); - format.setSampleType(QAudioFormat::Float); - format.setSampleSize(32); - break; - case PA_SAMPLE_FLOAT32BE: - format.setByteOrder(QAudioFormat::BigEndian); - format.setSampleType(QAudioFormat::Float); - format.setSampleSize(32); - break; - case PA_SAMPLE_S32LE: - format.setByteOrder(QAudioFormat::LittleEndian); - format.setSampleType(QAudioFormat::SignedInt); - format.setSampleSize(32); - break; - case PA_SAMPLE_S32BE: - format.setByteOrder(QAudioFormat::BigEndian); - format.setSampleType(QAudioFormat::SignedInt); - format.setSampleSize(32); - break; - case PA_SAMPLE_S24LE: - format.setByteOrder(QAudioFormat::LittleEndian); - format.setSampleType(QAudioFormat::SignedInt); - format.setSampleSize(24); - break; - case PA_SAMPLE_S24BE: - format.setByteOrder(QAudioFormat::BigEndian); - format.setSampleType(QAudioFormat::SignedInt); - format.setSampleSize(24); - break; - case PA_SAMPLE_S24_32LE: - format.setByteOrder(QAudioFormat::LittleEndian); - format.setSampleType(QAudioFormat::SignedInt); - format.setSampleSize(24); - break; - case PA_SAMPLE_S24_32BE: - format.setByteOrder(QAudioFormat::BigEndian); - format.setSampleType(QAudioFormat::SignedInt); - format.setSampleSize(24); - break; - case PA_SAMPLE_MAX: - case PA_SAMPLE_INVALID: - default: - format.setByteOrder(QAudioFormat::LittleEndian); - format.setSampleType(QAudioFormat::Unknown); - format.setSampleSize(0); - } - - return format; -} } QT_END_NAMESPACE diff --git a/src/multimedia/platform/pulseaudio/qpulsehelpers_p.h b/src/multimedia/platform/pulseaudio/qpulsehelpers_p.h index 279cecc2f..30192e4d1 100644 --- a/src/multimedia/platform/pulseaudio/qpulsehelpers_p.h +++ b/src/multimedia/platform/pulseaudio/qpulsehelpers_p.h @@ -63,7 +63,6 @@ pa_sample_spec audioFormatToSampleSpec(const QAudioFormat &format); QString stateToQString(pa_stream_state_t state); QString stateToQString(pa_context_state_t state); QString sampleFormatToQString(pa_sample_format format); -QAudioFormat sampleSpecToAudioFormat(pa_sample_spec spec); } QT_END_NAMESPACE |