/*! Returns the closest QAudioFormat to the supplied \a settings that the system supports. These settings are provided by the platform/audio plugin being used. They are also dependent on the \l {QAudio}::Mode being used. */ QAudioFormat QAudioDeviceInfo::nearestFormat(const QAudioFormat &settings) const { if (isFormatSupported(settings)) return settings; QAudioFormat nearest = settings; QList<QString> testCodecs = supportedCodecs(); QList<int> testChannels = supportedChannelCounts(); QList<QAudioFormat::Endian> testByteOrders = supportedByteOrders(); QList<QAudioFormat::SampleType> testSampleTypes; QList<QAudioFormat::SampleType> sampleTypesAvailable = supportedSampleTypes(); QMap<int,int> testSampleRates; QList<int> sampleRatesAvailable = supportedSampleRates(); QMap<int,int> testSampleSizes; QList<int> sampleSizesAvailable = supportedSampleSizes(); // Get sorted lists for checking if (testCodecs.contains(settings.codec())) { testCodecs.removeAll(settings.codec()); testCodecs.insert(0, settings.codec()); } testChannels.removeAll(settings.channelCount()); testChannels.insert(0, settings.channelCount()); testByteOrders.removeAll(settings.byteOrder()); testByteOrders.insert(0, settings.byteOrder()); if (sampleTypesAvailable.contains(settings.sampleType())) testSampleTypes.append(settings.sampleType()); if (sampleTypesAvailable.contains(QAudioFormat::SignedInt)) testSampleTypes.append(QAudioFormat::SignedInt); if (sampleTypesAvailable.contains(QAudioFormat::UnSignedInt)) testSampleTypes.append(QAudioFormat::UnSignedInt); if (sampleTypesAvailable.contains(QAudioFormat::Float)) testSampleTypes.append(QAudioFormat::Float); if (sampleSizesAvailable.contains(settings.sampleSize())) testSampleSizes.insert(0,settings.sampleSize()); sampleSizesAvailable.removeAll(settings.sampleSize()); foreach (int size, sampleSizesAvailable) { int larger = (size > settings.sampleSize()) ? size : settings.sampleSize(); int smaller = (size > settings.sampleSize()) ? settings.sampleSize() : size; bool isMultiple = ( 0 == (larger % smaller)); int diff = larger - smaller; testSampleSizes.insert((isMultiple ? diff : diff+100000), size); }
QVariantMap MediaSink::addStream(int streamIndex, const QbCaps &streamCaps, const QVariantMap &codecParams) { QString outputFormat; if (this->supportedFormats().contains(this->m_outputFormat)) outputFormat = this->m_outputFormat; else { AVOutputFormat *format = av_guess_format(NULL, this->m_location.toStdString().c_str(), NULL); if (format) outputFormat = QString(format->name); } if (outputFormat.isEmpty()) return QVariantMap(); QVariantMap outputParams; outputParams["index"] = streamIndex; QString codec; if (codecParams.contains("codec")) { if (supportedCodecs(outputFormat, streamCaps.mimeType()) .contains(codecParams["codec"].toString())) { codec = codecParams["codec"].toString(); } else codec = this->defaultCodec(outputFormat, streamCaps.mimeType()); } else codec = this->defaultCodec(outputFormat, streamCaps.mimeType()); outputParams["codec"] = codec; QVariantMap codecDefaults = this->defaultCodecParams(codec); outputParams["codecOptions"] = codecParams.value("codecOptions", QVariantMap()); if (streamCaps.mimeType() == "audio/x-raw") { int bitRate = codecParams.value("bitRate", codecDefaults["defaultBitRate"]).toInt(); outputParams["bitRate"] = bitRate > 0? bitRate: codecDefaults["defaultBitRate"].toInt(); QbAudioCaps audioCaps(streamCaps); QString sampleFormat = QbAudioCaps::sampleFormatToString(audioCaps.format()); QStringList supportedSampleFormats = codecDefaults["supportedSampleFormats"].toStringList(); if (!supportedSampleFormats.isEmpty() && !supportedSampleFormats.contains(sampleFormat)) { QString defaultSampleFormat = codecDefaults["defaultSampleFormat"].toString(); audioCaps.format() = QbAudioCaps::sampleFormatFromString(defaultSampleFormat); audioCaps.bps() = av_get_bytes_per_sample(av_get_sample_fmt(defaultSampleFormat.toStdString().c_str())); } QVariantList supportedSampleRates = codecDefaults["supportedSampleRates"].toList(); if (!supportedSampleRates.isEmpty()) { int sampleRate = 0; int maxDiff = std::numeric_limits<int>::max(); foreach (QVariant rate, supportedSampleRates) { int diff = qAbs(audioCaps.rate() - rate.toInt()); if (diff < maxDiff) { sampleRate = rate.toInt(); if (!diff) break; maxDiff = diff; } }