之前用ffmpeg解码出来了音频,只是做了存储部分,比如存储成aac文件,播放的话早期用的是sdl来播放音频,自从Qt5以后提供了QAudioOutput来播放输入的音频数据,就更加方便了,可以直接将解码好的音频数据写入就能播放了,这些就少了个学习sdl的成本,而且和Qt就更加融合,不需要额外的第三方库,解码好的视频,其实就是一张张图片数据,可以直接用QPainter绘制或者QOpenGlWidget通过GPU显示,解码好的音频用QAudioOutput播放,这对于很多初学者来说,是个很好的消息,完美。
音频播放大致的流程如下:
void FFmpegThread::initAudioDevice(int sampleRate, int sampleSize, int channelCount)
{
#if (QT_VERSION > QT_VERSION_CHECK(5,0,0))
QAudioFormat format;
format.setCodec("audio/pcm");
format.setSampleRate(sampleRate);
format.setSampleSize(sampleSize * 8);
format.setChannelCount(channelCount);
format.setSampleType(QAudioFormat::SignedInt);
format.setByteOrder(QAudioFormat::LittleEndian);
QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice());
audioDeviceOk = info.isFormatSupported(format);
if (audioDeviceOk) {
audioOutput = new QAudioOutput(format);
audioDevice = audioOutput->start();
} else {
qDebug() << TIMEMS << "Raw audio format not supported by backend, cannot play audio.";
}
#endif
}
void FFmpegThread::freeAudioDevice()
{
#if (QT_VERSION > QT_VERSION_CHECK(5,0,0))
audioOutput->stop();
audioOutput->deleteLater();
#endif
}
void FFmpegThread::decodeAudio()
{
//没有启用解码音频
if (!playAudio) {
return;
}
//保存音频流数据到文件
saveFileAac();
//设备不正常则不解码
if (!audioDeviceOk) {
return;
}
//解码音频流
frameFinish = avcodec_decode_audio4(audioCtx, audioFrame, &frameFinish, tempPacket);
if (frameFinish) {
int result = swr_convert(audioSwrCtx, &audioData, audioFrame->nb_samples, (const uint8_t **)audioFrame->data, audioFrame->nb_samples);
if (result) {
int outsize = av_samples_get_buffer_size(NULL, audioCtx->channels, audioFrame->nb_samples, AV_SAMPLE_FMT_S16, 0);
audioDevice->write((char *)audioData, outsize);
}
}
}
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。