QT+FFMEPG解码播放RTSP或视频文件中的音频流数据

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;

 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值