Qt音视频开发7-ffmpeg音频播放
时间:2022-07-23
本文章向大家介绍Qt音视频开发7-ffmpeg音频播放,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
一、前言
之前用ffmpeg解码出来了音频,只是做了存储部分,比如存储成aac文件,播放的话早期用的是sdl来播放音频,自从Qt5以后提供了QAudioOutput来播放输入的音频数据,就更加方便了,可以直接将解码好的音频数据写入就能播放了,这些就少了个学习sdl的成本,而且和Qt就更加融合,不需要额外的第三方库,解码好的视频,其实就是一张张图片数据,可以直接用QPainter绘制或者QOpenGlWidget通过GPU显示,解码好的音频用QAudioOutput播放,这对于很多初学者来说,是个很好的消息,完美。
音频播放大致的流程如下:
- 初始化格式QAudioFormat,设置对应的属性。
- 初始化一个QAudioOutput音频播放对象。
- 将QAudioOutput启动后的播放设备交给QIODevice。
- 打开音频流后初始化SwrContext用来转换音频数据。
- 循环解码音频数据后调用swr_convert转换音频数据。
- 将转换好的音频数据直接write到QIODevice。
二、功能特点
- 多线程实时播放视频流+本地视频+USB摄像头等。
- 支持windows+linux+mac,支持ffmpeg3和ffmpeg4,支持32位和64位。
- 多线程显示图像,不卡主界面。
- 自动重连网络摄像头。
- 可设置边框大小即偏移量和边框颜色。
- 可设置是否绘制OSD标签即标签文本或图片和标签位置。
- 可设置两种OSD位置和风格。
- 可设置是否保存到文件以及文件名。
- 可直接拖曳文件到ffmpegwidget控件播放。
- 支持h265视频流+rtmp等常见视频流。
- 可暂停播放和继续播放。
- 支持存储单个视频文件和定时存储视频文件。
- 自定义顶部悬浮条,发送单击信号通知,可设置是否启用。
- 可设置画面拉伸填充或者等比例填充。
- 可设置解码是速度优先、质量优先、均衡处理。
- 可对视频进行截图(原始图片)和截屏。
- 录像文件存储支持裸流和MP4文件。
- 支持qsv、dxva2、d3d11va等硬解码。
- 支持opengl绘制视频数据,极低CPU占用。
- 支持嵌入式linux,交叉编译即可。
三、效果图
四、相关站点
- 国内站点:https://gitee.com/feiyangqingyun/QWidgetDemo
- 国际站点:https://github.com/feiyangqingyun/QWidgetDemo
- 个人主页:https://blog.csdn.net/feiyangqingyun
- 知乎主页:https://www.zhihu.com/people/feiyangqingyun/
- 体验地址:https://blog.csdn.net/feiyangqingyun/article/details/97565652
五、核心代码
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);
}
}
}
- 前端魔法堂——调用栈,异常实例中的宝藏
- 开启MySQL的binlog日志
- C#解析JSON
- 动手写个数字输入框1:input[type=number]的遗憾
- 小猪农场获百万天使轮,六声域名源自运营主体
- Intellij idea 的maven项目自动下载jar包
- python3和python2共存
- 揭密微信跳一跳小游戏那些外挂
- 特斯拉出现人才流失潮,竟因为一些工程师认为Autopilot自动驾驶技术并不安全
- 微信又更新了,这次放出年度大招!新变化让不少人拍手叫好!
- “JINAN”:未来电动汽车边跑边充电
- Bagging算法
- 基于Region Proposal的深度学习目标检测简述(一)
- 10大数据挖掘算法及其简介
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 学了这个,三歪再也不想写各种setter了
- 使用 GitLab CI 与 Argo CD 进行 GitOps 实践
- Java 语言中十大“坑爹”功能!
- 面试:说说啥是一致性哈希算法?
- 问一下,线程池里面到底该设置多少个线程?
- 进程和线程基础知识全家桶,30 张图一套带走
- Python-matplotlib 学术柱状图绘制
- 为什么要避免大事务以及大事务如何解决?
- [即时通信IM]群@消息如何实现?
- 利用PySpark对 Tweets 流数据进行情感分析实战
- ConcurrentHashMap源码学习
- HashMap源码学习
- Pytest自动化测试fixture之conftest.py
- ArrayList源码学习
- 科技将带给我们什么变化?讲述基于 HTML5 WebGL 的 3D 科幻风机