QT播放音频实现如下:
#include <QWidget>
#include <QAudio>
#include <QAudioFormat>
#include <QAudioOutput>
#include <QIODevice>
class AudioOutput : public QWidget
{
Q_OBJECT
public:
AudioOutput(QWidget *parent = Q_NULLPTR);
~AudioOutput();
......
void OpenOutput();
bool StartOutput();
void StopOutput();
void WriteAudio(const char *data, int size);
private:
QAudioOutput *output;
QIODevice *outputDevice;
QMutex m_Mutex;
......
};
AudioOutput::AudioOutput(QWidget *parent)
: QWidget(parent)
{
output = NULL;
outputDevice = NULL;
}
AudioOutput::~AudioOutput()
{
StopOutput();
outputDevice = NULL;
if (output != NULL)
{
delete output;
output = NULL;
}
}
void AudioOutput::OpenOutput()
{
//音频输出配置
QAudioFormat outformat;
outformat.setSampleRate(16000);
outformat.setChannelCount(1);
outformat.setSampleSize(16);
outformat.setCodec("audio/pcm");
outformat.setSampleType(QAudioFormat::SignedInt);
outformat.setByteOrder(QAudioFormat::LittleEndian);
QAudioDeviceInfo outDeviceInfo(QAudioDeviceInfo::defaultOutputDevice());
if (outDeviceInfo.isNull()){
qDebug() << "can not find output device";
}
//支持的音频输出的编码和采样率
//QStringList outlistcode = outDeviceInfo.supportedCodecs();
//QList<int> outlistrate = outDeviceInfo.supportedSampleRates();
if (!outDeviceInfo.isFormatSupported(outformat))
{
outformat = outDeviceInfo.nearestFormat(outformat);
}
if (output == NULL)
{
output = new QAudioOutput(outformat, this);
}
}
bool AudioOutput::StartOutput()
{
outputDevice = output->start();
if (outputDevice == NULL)
{
qDebug() << "start output audio fail";
return false;
}
return true;
}
void AudioOutput::StopOutput()
{
outputDevice = NULL;
if (output != NULL)
{
output->stop();
}
}
void AudioOutput::WriteAudio(const char *data, int size)
{
m_Mutex.lock();
if (outputDevice != NULL && size > 0)
{
outputDevice->write(data, size);
}
m_Mutex.unlock();
}
调用顺序:OpenOutput,StartOutput,WriteAudio,StopOutput
使用FFMPEG解码音频流数据并调用AudioOutput播放:
bool CFFMpegRtsp::Play()
{
......
while(!m_bExit)
{
bool bResult = (av_read_frame(pFormatContext, &packet) >= 0);
if (bResult)
{
if (packet.stream_index == audio_stream_index && videoWgt->IsAudioOpen())
{
if (auo_convert_ctx == NULL)
{
out_channels = av_get_channel_layout_nb_channels(1);
auo_convert_ctx = swr_alloc_set_opts(
NULL,
out_channels,
AV_SAMPLE_FMT_S16,
16000,
av_get_default_channel_layout(pAudioCodecCtx->channels),
pAudioCodecCtx->sample_fmt,
pAudioCodecCtx->sample_rate,
0, NULL);
int res = swr_init(auo_convert_ctx);
}
if (auo_convert_ctx != NULL)
{
int got_picture = 0;
int iRet = avcodec_decode_audio4(pAudioCodecCtx, m_pDecFrame, &got_picture, &packet);
if (iRet > 0 && got_picture)
{
int len = swr_convert(auo_convert_ctx, &m_pAudioBuffer, MAX_AUDIO_FRAME_SIZE, (const uint8_t **)m_pDecFrame->data, m_pDecFrame->nb_samples);
if (len > 0)
{
int size = av_samples_get_buffer_size(m_pDecFrame->linesize, out_channels, len, AV_SAMPLE_FMT_S16, 0);
m_audioOut->WriteAudioData((const char *)m_pAudioBuffer, size);
}
}
}
}
......
}
......
}
......
}
一些变量的定义:
#define MAX_AUDIO_FRAME_SIZE 192000
SwrContext *auo_convert_ctx;
AudioOutput *m_audioOut;