diff options
Diffstat (limited to 'src/multimedia/audio/qaudiodecoder.cpp')
-rw-r--r-- | src/multimedia/audio/qaudiodecoder.cpp | 345 |
1 files changed, 92 insertions, 253 deletions
diff --git a/src/multimedia/audio/qaudiodecoder.cpp b/src/multimedia/audio/qaudiodecoder.cpp index 0286e9a85..f555f46ed 100644 --- a/src/multimedia/audio/qaudiodecoder.cpp +++ b/src/multimedia/audio/qaudiodecoder.cpp @@ -1,192 +1,104 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qaudiodecoder.h" -#include "qmediaobject_p.h" -#include <qmediaservice.h> -#include "qaudiodecodercontrol.h" -#include <private/qmediaserviceprovider_p.h> +#include <private/qaudiodecoder_p.h> +#include <private/qmultimediautils_p.h> +#include <private/qplatformaudiodecoder_p.h> +#include <private/qplatformmediaintegration_p.h> #include <QtCore/qcoreevent.h> -#include <QtCore/qmetaobject.h> -#include <QtCore/qtimer.h> #include <QtCore/qdebug.h> +#include <QtCore/qmetaobject.h> #include <QtCore/qpointer.h> +#include <QtCore/qtimer.h> +#include <QtCore/qurl.h> QT_BEGIN_NAMESPACE /*! \class QAudioDecoder - \brief The QAudioDecoder class allows decoding audio. + \brief The QAudioDecoder class implements decoding audio. \inmodule QtMultimedia \ingroup multimedia \ingroup multimedia_audio \preliminary - The QAudioDecoder class is a high level class for decoding local + The QAudioDecoder class is a high level class for decoding audio media files. It is similar to the QMediaPlayer class except that audio is provided back through this API rather than routed - directly to audio hardware, and playlists and network and streaming - based media is not supported. + directly to audio hardware. \sa QAudioBuffer */ -static void qRegisterAudioDecoderMetaTypes() -{ - qRegisterMetaType<QAudioDecoder::State>("QAudioDecoder::State"); - qRegisterMetaType<QAudioDecoder::Error>("QAudioDecoder::Error"); -} - -Q_CONSTRUCTOR_FUNCTION(qRegisterAudioDecoderMetaTypes) - -class QAudioDecoderPrivate : public QMediaObjectPrivate -{ - Q_DECLARE_NON_CONST_PUBLIC(QAudioDecoder) - -public: - QAudioDecoderPrivate() - : provider(nullptr) - , control(nullptr) - , state(QAudioDecoder::StoppedState) - , error(QAudioDecoder::NoError) - {} - - QMediaServiceProvider *provider; - QAudioDecoderControl *control; - QAudioDecoder::State state; - QAudioDecoder::Error error; - QString errorString; - - void _q_stateChanged(QAudioDecoder::State state); - void _q_error(int error, const QString &errorString); -}; - -void QAudioDecoderPrivate::_q_stateChanged(QAudioDecoder::State ps) +/*! + Construct an QAudioDecoder instance with \a parent. +*/ +QAudioDecoder::QAudioDecoder(QObject *parent) : QObject{ *new QAudioDecoderPrivate, parent } { - Q_Q(QAudioDecoder); + QT6_ONLY(Q_UNUSED(unused)) - if (ps != state) { - state = ps; + Q_D(QAudioDecoder); - emit q->stateChanged(ps); + auto maybeDecoder = QPlatformMediaIntegration::instance()->createAudioDecoder(this); + if (maybeDecoder) { + d->decoder.reset(maybeDecoder.value()); + } else { + qWarning() << "Failed to initialize QAudioDecoder" << maybeDecoder.error(); } } -void QAudioDecoderPrivate::_q_error(int error, const QString &errorString) -{ - Q_Q(QAudioDecoder); - - this->error = QAudioDecoder::Error(error); - this->errorString = errorString; - - emit q->error(this->error); -} +/*! + Destroys the audio decoder object. +*/ +QAudioDecoder::~QAudioDecoder() = default; /*! - Construct an QAudioDecoder instance - parented to \a parent. + Returns true is audio decoding is supported on this platform. */ -QAudioDecoder::QAudioDecoder(QObject *parent) - : QMediaObject(*new QAudioDecoderPrivate, - parent, - QMediaServiceProvider::defaultServiceProvider()->requestService(Q_MEDIASERVICE_AUDIODECODER)) +bool QAudioDecoder::isSupported() const { - Q_D(QAudioDecoder); + Q_D(const QAudioDecoder); - d->provider = QMediaServiceProvider::defaultServiceProvider(); - if (d->service) { - d->control = qobject_cast<QAudioDecoderControl*>(d->service->requestControl(QAudioDecoderControl_iid)); - if (d->control != nullptr) { - connect(d->control, SIGNAL(stateChanged(QAudioDecoder::State)), SLOT(_q_stateChanged(QAudioDecoder::State))); - connect(d->control, SIGNAL(error(int,QString)), SLOT(_q_error(int,QString))); - - connect(d->control, SIGNAL(formatChanged(QAudioFormat)), SIGNAL(formatChanged(QAudioFormat))); - connect(d->control, SIGNAL(sourceChanged()), SIGNAL(sourceChanged())); - connect(d->control, SIGNAL(bufferReady()), this, SIGNAL(bufferReady())); - connect(d->control ,SIGNAL(bufferAvailableChanged(bool)), this, SIGNAL(bufferAvailableChanged(bool))); - connect(d->control ,SIGNAL(finished()), this, SIGNAL(finished())); - connect(d->control ,SIGNAL(positionChanged(qint64)), this, SIGNAL(positionChanged(qint64))); - connect(d->control ,SIGNAL(durationChanged(qint64)), this, SIGNAL(durationChanged(qint64))); - } - } - if (!d->control) { - d->error = ServiceMissingError; - d->errorString = tr("The QAudioDecoder object does not have a valid service"); - } + return bool(d->decoder); } - /*! - Destroys the audio decoder object. + \property QAudioDecoder::isDecoding + \brief \c true if the decoder is currently running and decoding audio data. */ -QAudioDecoder::~QAudioDecoder() +bool QAudioDecoder::isDecoding() const { - Q_D(QAudioDecoder); - - if (d->service) { - if (d->control) - d->service->releaseControl(d->control); - - d->provider->releaseService(d->service); - } -} + Q_D(const QAudioDecoder); -QAudioDecoder::State QAudioDecoder::state() const -{ - return d_func()->state; + return d->decoder && d->decoder->isDecoding(); } /*! - Returns the current error state. -*/ + Returns the current error state of the QAudioDecoder. +*/ QAudioDecoder::Error QAudioDecoder::error() const { - return d_func()->error; + Q_D(const QAudioDecoder); + return d->decoder ? d->decoder->error() : NotSupportedError; } +/*! + \property QAudioDecoder::error + + Returns a human readable description of the current error, or + an empty string is there is no error. +*/ QString QAudioDecoder::errorString() const { - return d_func()->errorString; + Q_D(const QAudioDecoder); + if (!d->decoder) + return tr("QAudioDecoder not supported."); + return d->decoder->errorString(); } /*! @@ -205,18 +117,12 @@ void QAudioDecoder::start() { Q_D(QAudioDecoder); - if (d->control == nullptr) { - QMetaObject::invokeMethod(this, "_q_error", Qt::QueuedConnection, - Q_ARG(int, QAudioDecoder::ServiceMissingError), - Q_ARG(QString, tr("The QAudioDecoder object does not have a valid service"))); + if (!d->decoder) return; - } // Reset error conditions - d->error = NoError; - d->errorString.clear(); - - d->control->start(); + d->decoder->clearError(); + d->decoder->start(); } /*! @@ -226,8 +132,8 @@ void QAudioDecoder::stop() { Q_D(QAudioDecoder); - if (d->control != nullptr) - d->control->stop(); + if (d->decoder) + d->decoder->stop(); } /*! @@ -235,12 +141,10 @@ void QAudioDecoder::stop() If \l setSourceDevice was called, this will be empty. */ -QString QAudioDecoder::sourceFilename() const +QUrl QAudioDecoder::source() const { Q_D(const QAudioDecoder); - if (d->control) - return d->control->sourceFilename(); - return QString(); + return d->unresolvedUrl; } /*! @@ -252,24 +156,28 @@ QString QAudioDecoder::sourceFilename() const You can only specify either a source filename or a source QIODevice. Setting one will unset the other. */ -void QAudioDecoder::setSourceFilename(const QString &fileName) +void QAudioDecoder::setSource(const QUrl &fileName) { Q_D(QAudioDecoder); - if (d->control != nullptr) - d_func()->control->setSourceFilename(fileName); + if (!d->decoder) + return; + + d->decoder->clearError(); + d->unresolvedUrl = fileName; + d->decoder->setSourceDevice(nullptr); + QUrl url = qMediaFromUserInput(fileName); + d->decoder->setSource(url); } /*! Returns the current source QIODevice, if one was set. - If \l setSourceFilename() was called, this will be 0. + If \l setSource() was called, this will be a nullptr. */ QIODevice *QAudioDecoder::sourceDevice() const { Q_D(const QAudioDecoder); - if (d->control) - return d->control->sourceDevice(); - return nullptr; + return d->decoder ? d->decoder->sourceDevice() : nullptr; } /*! @@ -284,24 +192,24 @@ QIODevice *QAudioDecoder::sourceDevice() const void QAudioDecoder::setSourceDevice(QIODevice *device) { Q_D(QAudioDecoder); - - if (d->control != nullptr) - d_func()->control->setSourceDevice(device); + if (d->decoder) { + d->unresolvedUrl = QUrl{}; + d->decoder->setSourceDevice(device); + } } /*! - Returns the current audio format of the decoded stream. + Returns the audio format the decoder is set to. - Any buffers returned should have this format. + \note This may be different than the format of the decoded + samples, if the audio format was set to an invalid one. \sa setAudioFormat(), formatChanged() */ QAudioFormat QAudioDecoder::audioFormat() const { Q_D(const QAudioDecoder); - if (d->control) - return d->control->audioFormat(); - return QAudioFormat(); + return d->decoder ? d->decoder->audioFormat() : QAudioFormat{}; } /*! @@ -319,45 +227,20 @@ QAudioFormat QAudioDecoder::audioFormat() const If you wish to reset the decoded format to that of the original audio file, you can specify an invalid \a format. + + \warning Setting a desired audio format is not yet supported + on the Android backend. It does work with the default FFMPEG + backend. */ void QAudioDecoder::setAudioFormat(const QAudioFormat &format) { - Q_D(QAudioDecoder); - - if (state() != QAudioDecoder::StoppedState) + if (isDecoding()) return; - if (d->control != nullptr) - d_func()->control->setAudioFormat(format); -} - -/*! - \internal -*/ - -bool QAudioDecoder::bind(QObject *obj) -{ - return QMediaObject::bind(obj); -} - -/*! - \internal -*/ - -void QAudioDecoder::unbind(QObject *obj) -{ - QMediaObject::unbind(obj); -} + Q_D(QAudioDecoder); -/*! - Returns the level of support an audio decoder has for a \a mimeType and a set of \a codecs. -*/ -QMultimedia::SupportEstimate QAudioDecoder::hasSupport(const QString &mimeType, - const QStringList& codecs) -{ - return QMediaServiceProvider::defaultServiceProvider()->hasSupport(QByteArray(Q_MEDIASERVICE_AUDIODECODER), - mimeType, - codecs); + if (d->decoder) + d->decoder->setAudioFormat(format); } /*! @@ -368,9 +251,7 @@ QMultimedia::SupportEstimate QAudioDecoder::hasSupport(const QString &mimeType, bool QAudioDecoder::bufferAvailable() const { Q_D(const QAudioDecoder); - if (d->control) - return d->control->bufferAvailable(); - return false; + return d->decoder && d->decoder->bufferAvailable(); } /*! @@ -381,9 +262,7 @@ bool QAudioDecoder::bufferAvailable() const qint64 QAudioDecoder::position() const { Q_D(const QAudioDecoder); - if (d->control) - return d->control->position(); - return -1; + return d->decoder ? d->decoder->position() : -1; } /*! @@ -394,9 +273,7 @@ qint64 QAudioDecoder::position() const qint64 QAudioDecoder::duration() const { Q_D(const QAudioDecoder); - if (d->control) - return d->control->duration(); - return -1; + return d->decoder ? d->decoder->duration() : -1; } /*! @@ -412,26 +289,11 @@ qint64 QAudioDecoder::duration() const QAudioBuffer QAudioDecoder::read() const { Q_D(const QAudioDecoder); - - if (d->control) { - return d->control->read(); - } else { - return QAudioBuffer(); - } + return d->decoder ? d->decoder->read() : QAudioBuffer{}; } // Enums /*! - \enum QAudioDecoder::State - - Defines the current state of a media player. - - \value StoppedState The decoder is not decoding. Decoding will - start at the start of the media. - \value DecodingState The audio player is currently decoding media. -*/ - -/*! \enum QAudioDecoder::Error Defines a media player error condition. @@ -440,12 +302,12 @@ QAudioBuffer QAudioDecoder::read() const \value ResourceError A media resource couldn't be resolved. \value FormatError The format of a media resource isn't supported. \value AccessDeniedError There are not the appropriate permissions to play a media resource. - \value ServiceMissingError A valid playback service was not found, playback cannot proceed. + \value NotSupportedError QAudioDecoder is not supported on this platform */ // Signals /*! - \fn QAudioDecoder::error(QAudioDecoder::Error error) + \fn void QAudioDecoder::error(QAudioDecoder::Error error) Signals that an \a error condition has occurred. @@ -453,17 +315,11 @@ QAudioBuffer QAudioDecoder::read() const */ /*! - \fn void QAudioDecoder::stateChanged(State state) - - Signal the \a state of the decoder object has changed. -*/ - -/*! \fn void QAudioDecoder::sourceChanged() Signals that the current source of the decoder has changed. - \sa sourceFilename(), sourceDevice() + \sa source(), sourceDevice() */ /*! @@ -517,26 +373,9 @@ QAudioBuffer QAudioDecoder::read() const \sa positionChanged() */ - // Properties /*! - \property QAudioDecoder::state - \brief the audio decoder's playback state. - - By default this property is QAudioDecoder::Stopped - - \sa start(), stop() -*/ - -/*! - \property QAudioDecoder::error - \brief a string describing the last error condition. - - \sa error() -*/ - -/*! - \property QAudioDecoder::sourceFilename + \property QAudioDecoder::source \brief the active filename being decoded by the decoder object. */ |