/*!
    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);
    }
Beispiel #2
0
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;
                }
            }