Files
fmviewer3/project/fm_viewer/fav/AudioOutput.h
2026-02-21 17:11:31 +09:00

234 lines
8.6 KiB
C++

/******************************************************************************
QtAV: Multimedia framework based on Qt and FFmpeg
Copyright (C) 2012-2016 Wang Bin <wbsecg1@gmail.com>
* This file is part of QtAV
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
******************************************************************************/
#ifndef QAV_AUDIOOUTPUT_H
#define QAV_AUDIOOUTPUT_H
#include <QtCore/QObject>
#include <QtCore/QStringList>
#include "AVOutput.h"
#include "AudioFrame.h"
/*!
* AudioOutput ao;
* ao.setAudioFormat(fmt);
* ao.open();
* while (has_data) {
* data = read_data(ao->bufferSize());
* ao->play(data, pts);
* }
* ao->close();
* See QtAV/tests/ao/main.cpp for detail
*/
namespace FAV {
class AudioFormat;
class AudioOutputPrivate;
class Q_AV_EXPORT AudioOutput : public QObject, public AVOutput
{
Q_OBJECT
DPTR_DECLARE_PRIVATE(AudioOutput)
Q_ENUMS(DeviceFeature)
Q_FLAGS(DeviceFeatures)
Q_PROPERTY(qreal volume READ volume WRITE setVolume NOTIFY volumeChanged)
Q_PROPERTY(bool mute READ isMute WRITE setMute NOTIFY muteChanged)
Q_PROPERTY(DeviceFeatures deviceFeatures READ deviceFeatures WRITE setDeviceFeatures NOTIFY deviceFeaturesChanged)
Q_PROPERTY(QStringList backends READ backends WRITE setBackends NOTIFY backendsChanged)
public:
/*!
* \brief DeviceFeature Feature enum
* Features supported by the audio playback api (we call device or backend here)
* If a feature is not supported, e.g. SetVolume, then a software implementation is used.
*/
enum DeviceFeature {
NoFeature = 0,
SetVolume = 1, /// Use backend volume control api rather than software scale. Ignore if backend does not support.
SetMute = 1 << 1,
SetSampleRate = 1 << 2, /// NOT IMPLEMENTED
SetSpeed = 1 << 3, /// NOT IMPLEMENTED
};
Q_DECLARE_FLAGS(DeviceFeatures, DeviceFeature)
/*!
* \brief backendsAvailable
* All registered backends in default priority order
* \return
*/
static QStringList backendsAvailable();
/*!
* \brief AudioOutput
* Audio format set to preferred sample format and channel layout
*/
AudioOutput(QObject *parent = 0);
~AudioOutput();
/*!
* \brief setBackends
* set the given backends. Old backend instance and backend() is updated soon if backendsChanged.
* It is called internally with a default backend names when AudioOutput is created.
*/
void setBackends(const QStringList &backendNames = QStringList());
QStringList backends() const;
/*!
* \brief backend
* backend name currently in use
*/
QString backend() const;
QString status() const;
/*!
* \brief flush
* Play the buffered audio data
* \return
*/
void flush();
/*!
* \brief clear
* Clear audio buffers and set time to 0. The default behavior is flush and reset time
*/
void clear();
bool open();
bool close();
bool isOpen() const;
/*!
* \brief play
* Play out the given audio data. It may block current thread until the data can be written to audio device
* for async playback backend, or until the data is completely played for blocking playback backend.
* \param data Audio data to play
* \param pts Timestamp for this data. Useful if need A/V sync. Ignore it if only play audio
* \return false if currently isPaused(), no backend is available or backend failed to play
*/
bool play(const QByteArray& data, qreal pts = 0.0);
/*!
* \brief pause
* Pause audio rendering. play() will fail.
*/
void pause(bool value);
bool isPaused() const;
/*!
* \brief setAudioFormat
* Set/Request to use the given \l format. If it's not supported, an preferred format will be used.
* \param format requested format
* \return actual format to use. Invalid format if backend is not available
* NOTE: Check format support may fail for some backends (OpenAL) if it's closed.
*/
AudioFormat setAudioFormat(const AudioFormat& format);
const AudioFormat& requestedFormat() const;
/*!
* \brief audioFormat
* \return actual format for requested format
*/
const AudioFormat& audioFormat() const;
/*!
* \brief setVolume
* Set volume level.
* If SetVolume feature is not set or not supported, software implementation will be used.
* Call this after open(), because it will call backend api if SetVolume feature is enabled
* \param volume linear. 1.0: original volume.
*/
void setVolume(qreal value);
qreal volume() const;
/*!
* \brief setMute
* If SetMute feature is not set or not supported, software implementation will be used.
* Call this after open(), because it will call backend api if SetMute feature is enabled
*/
void setMute(bool value = true);
bool isMute() const;
/*!
* \brief setSpeed set audio playing speed
* Currently only store the value and does nothing else in audio output. You may change sample rate to get the same effect.
* The speed affects the playing only if audio is available and clock type is
* audio clock. For example, play a video contains audio without special configurations.
* To change the playing speed in other cases, use AVPlayer::setSpeed(qreal)
* \param speed linear. > 0
* TODO: resample internally
*/
void setSpeed(qreal speed);
qreal speed() const;
/*!
* \brief isSupported
* check \a isSupported(format.sampleFormat()) and \a isSupported(format.channelLayout())
* \param format
* \return true if \a format is supported. default is true
* NOTE: may fail for some backends if it's closed, for example OpenAL
*/
bool isSupported(const AudioFormat& format) const;
/*!
* \brief bufferSamples
* Number of samples that audio output accept in 1 buffer. Feed the audio output this size of data every time.
* Smaller buffer samples gives more buffers for a given data to avoid stutter. But if it's too small, the duration of 1 buffer will be too small to play, for example 1ms. Currently the default value is 512.
* Some backends(OpenAL) are affected significantly by this property
*/
int bufferSamples() const;
void setBufferSamples(int value);
int bufferSize() const; /// bufferSamples()*bytesPerSample
/*!
* \brief bufferCount
* Total buffer count. If it's not large enough, playing high sample rate audio may be poor.
* The default value is 16. TODO: depending on audio format(sample rate?)
* Some backends(OpenAL) are affected significantly by this property
*/
int bufferCount() const;
void setBufferCount(int value);
int bufferSizeTotal() const { return bufferCount() * bufferSize();}
/*!
* \brief setDeviceFeatures
* Unsupported features will not be set.
* You can call this in a backend ctor.
*/
void setDeviceFeatures(DeviceFeatures value);
/*!
* \brief deviceFeatures
* \return features set by setFeatures() excluding unsupported features
*/
DeviceFeatures deviceFeatures() const;
/*!
* \brief supportedDeviceFeatures
* Supported features of the backend, defined by AudioOutput(DeviceFeatures,AudioOutput&,QObject*) in a backend ctor
*/
DeviceFeatures supportedDeviceFeatures() const;
qreal timestamp() const;
// timestamp of current playing data
Q_SIGNALS:
void volumeChanged(qreal);
void muteChanged(bool);
void deviceFeaturesChanged();
void backendsChanged();
protected:
// Store and fill data to audio buffers
bool receiveData(const QByteArray &data, qreal pts = 0.0);
/*!
* \brief waitForNextBuffer
* wait until you can feed more data
*/
bool waitForNextBuffer();
private Q_SLOTS:
void reportVolume(qreal value);
void reportMute(bool value);
private:
void onCallback();
friend class AudioOutputBackend;
Q_DISABLE_COPY(AudioOutput)
};
} //namespace FAV
#endif // QAV_AUDIOOUTPUT_H