Qt音视频开发10-ffmpeg控制播放
一、前言
很多人在用ffmpeg做视频流解码的时候,都会遇到一个问题,如何暂停,如果打开的是本地视频文件,暂停你只需要停止解码即可,但是视频流你会发现根本没用,一旦你停止了解码,下次重新解码的时候,居然还是以前的图片,他是从你最后暂停开始的地方重新解码的,这就懵逼了,为啥呢?我个人的理解是视频流这玩意,一旦你打开了,他就源源不断涌过来,你不处理,他就越来越多,你必须要读取他,从缓冲区拿走这些数据才行,所以如果想要暂停视频流,正确的做法是照常解码,只是不处理和绘制图片就行,说白了其实就是伪暂停,看起来是暂停了,其实后台还在不断的解码中。
用ffmpeg播放本地文件的时候,如果不加延时,你会发现刷刷几秒钟就播放完了,具体看电脑的性能,性能好的电脑也就几秒钟播放一个5分钟的视频,是不是会觉得很奇怪呢,怎么播放的这么快呢,其实ffmpeg解码只管解码,疯狂解码模式,使命的干,榨干你的CPU或者GPU资源(如果开启了硬解码则走GPU),解码后的每一帧都带有pts dts等信息,需要自己根据这些信息来做延时处理,比如还没到下一帧的时候,你就延时一段时间再去解码,至于延时多久有一个通用的计算方法,在打开流后记住开始的时间。然后解码中取出对应流(视频流或者音频流等)的基准时间time_base,调用av_rescale_q计算出pts时间,然后用av_gettime() - startTime得到当前的时间,用pts_time - now_time得到时间差值,如果是正数,则这个时间就是需要延时的微秒数,注意是微秒数而不是毫秒数哦,直接调用av_usleep来延时即可。
二、功能特点
- 多线程实时播放视频流+本地视频+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 FFmpegWidget::updateImage(const QImage &image)
{
//暂停或者不可见 rtsp视频流需要停止绘制
if (!this->property("isPause").toBool() && this->isVisible() && thread->isRunning()) {
//拷贝图片有个好处,当处理器比较差的时候,图片不会产生断层,缺点是占用时间
//默认QImage类型是浅拷贝,可能正在绘制的时候,那边已经更改了图片的上部分数据
this->image = copyImage ? image.copy() : image;
this->update();
}
}
void FFmpegWidget::updateFrame(AVFrame *frame)
{
#ifdef opengl
//暂停或者不可见 rtsp视频流需要停止绘制
if (!this->property("isPause").toBool() && (yuvWidget->isVisible() || nv12Widget->isVisible()) && thread->isRunning()) {
//采用了硬件加速的直接用nv12渲染,否则采用yuv渲染
if (thread->getHardware() == "none") {
yuvWidget->setFrameSize(frame->width, frame->height);
yuvWidget->updateTextures(frame->data[0], frame->data[1], frame->data[2], frame->linesize[0], frame->linesize[1], frame->linesize[2]);
} else {
nv12Widget->setFrameSize(frame->width, frame->height);
nv12Widget->updateTextures(frame->data[0], frame->data[1], frame->linesize[0], frame->linesize[1]);
}
}
#endif
}
void FFmpegThread::delayTime(int streamIndex, AVPacket *packet)
{
//视频流不用延时
if (isRtsp) {
return;
}
//没有视频时长的文件和asf的本地文件采用另外的延时计算
if (streamIndex == videoStreamIndex) {
if (interval != 1 || videoTime < 0 || url.toLower().endsWith("asf")) {
sleepVideo();
return;
}
}
qint64 offset_time = getDelayTime(streamIndex, packet);
if (offset_time > 0) {
av_usleep(offset_time);
}
}
qint64 FFmpegThread::getDelayTime(int streamIndex, AVPacket *packet)
{
AVRational time_base = formatCtx->streams[streamIndex]->time_base;
AVRational time_base_q = {1, AV_TIME_BASE};
int64_t pts_time = av_rescale_q(packet->pts, time_base, time_base_q);
int64_t now_time = av_gettime() - startTime;
int64_t offset_time = pts_time - now_time;
return offset_time;
}
Qt音视频开发10-ffmpeg控制播放的更多相关文章
- 【秒懂音视频开发】02_Windows开发环境搭建
音视频开发库的选择 每个主流平台基本都有自己的音视频开发库(API),用以处理音视频数据,比如: iOS:AVFoundation.AudioUnit等 Android:MediaPlayer.Med ...
- 音视频开发-FFmpeg
音视频开发是个非常复杂的,庞大的开发话题,初涉其中,先看一下结合 OEIP(开源项目) 新增例子. 可以打开flv,mp4类型文件,以及rtmp协议音视频数据,声音的播放使用SDL. 把采集的麦/声卡 ...
- Android 音视频开发(一):PCM 格式音频的播放与采集
什么是 PCM 格式 声音从模拟信号转化为数字信号的技术,经过采样.量化.编码三个过程将模拟信号数字化. 采样 顾名思义,对模拟信号采集样本,该过程是从时间上对信号进行数字化,例如每秒采集 44100 ...
- Android WebRTC 音视频开发总结
www.cnblogs.com/lingyunhu/p/3621057.html 前面介绍了WebRTCDemo的基本结构,本节主要介绍WebRTC音视频服务端的处理,,转载请说明出处(博客园RTC. ...
- WebRTC 音视频开发
WebRTC 音视频开发 webrtc Android IOS WebRTC 音视频开发总结(七八)-- 为什么WebRTC端到端监控很关键? 摘要: 本文主要介绍WebRTC端到端监控(我们翻译 ...
- Android 音视频开发学习思路
Android 音视频开发这块目前的确没有比较系统的教程或者书籍,网上的博客文章也都是比较零散的.只能通过一点点的学习和积累把这块的知识串联积累起来. 初级入门篇: Android 音视频开发(一) ...
- 转:Android IOS WebRTC 音视频开发总结 (系列文章集合)
随笔分类 - webrtc Android IOS WebRTC 音视频开发总结(七八)-- 为什么WebRTC端到端监控很关键? 摘要: 本文主要介绍WebRTC端到端监控(我们翻译和整理的,译 ...
- moviepy音视频开发:使用credits1给视频加片头片尾字幕
☞ ░ 前往老猿Python博文目录 ░ 一.概述 在<moviepy音视频剪辑:视频基类VideoClip子类DataVideoClip.UpdatedVideoClip.ImageClip. ...
- moviepy音视频开发:音频剪辑基类AudioClip
☞ ░ 前往老猿Python博文目录 ░ 一.背景知识介绍 1.1.声音三要素: 音调:人耳对声音高低的感觉称为音调(也叫音频).音调主要与声波的频率有关.声波的频率高,则音调也高. 音量:也就是响度 ...
- Android音视频开发(1):H264 基本原理
前言 H264 视频压缩算法现在无疑是所有视频压缩技术中使用最广泛,最流行的.随着 x264/openh264 以及 ffmpeg 等开源库的推出,大多数使用者无需再对H264的细节做过多的研究,这大 ...
随机推荐
- Linux+PXE+DHCP+TFTP+NFS实现无人值守安装
一.实验环境:OS:Redhat6.4软件:DHCP服务.TFTP服务.NFS服务硬件:Dell R630服务器两台物理连接图: em1 em1 二.工作原理:服务器通过PXE网卡启动,从dhcp服务 ...
- 旧电脑配置玩魔兽世界带不动?云电脑轻松解决,用ToDesk!
最近魔兽世界重新回归,不少游戏老玩家都摩拳擦掌准备上线回忆青春,但发现手里的旧电脑早已带不动游戏,硬要打开很容易出现画面卡顿.延迟严重,甚至频繁掉线,这些问题都让游戏乐趣大打折扣.但要为此再重新买一台 ...
- 多个modal遮罩层覆盖不全的问题
多个modal遮罩层覆盖不全的问题 如下有两个 modal的情况,要解决的是 在delete操作时弹出的modal 周围没有遮罩层环绕使得 确认 modal 辨识度不高 的问题 这里是修改好了的效果 ...
- Power BI新卡片更改显示单位
Power BI 不知道什么时候发布了新卡片,照现在官方来说,该视觉对象目前还属于预览版,但已经可以正常使用了,对比旧的卡片,显示效果个人觉得会友好一些,详见官方说明:创建"新"卡 ...
- DPaRL:耶鲁+AWS出品,开放世界持续学习场景的新解法 | ECCV'24
来源:晓飞的算法工程笔记 公众号,转载请注明出处 论文: Open-World Dynamic Prompt and Continual Visual Representation Learning ...
- 重温c语言之,7天开整,就是随便的写写,第二天
一:操作符 除法: 如果都是整数,除数,被除数都是整数,那么结果:就是整数的商(没有小数部分的),例如:7/2=3: 如果除数或者被除数其中一个是浮点数,那么结果就是(条件是:能除尽的,并且小数在基础 ...
- position 的值, relative 和 absolute 分别是相对于谁进行定位的?
relative: 相对定位 相对于自己本身在正常文档流中的位置进行定位 相对它原来的位置.原来在标准流中的位置继续占有. absolute: 绝对定位 相对于最近一级定位不为static的父元素进 ...
- Python如何根据给定模型计算权值
在机器学习和深度学习中,模型的权值(或参数)通常是通过训练过程(如梯度下降)来学习和调整的.然而,如果我们想根据一个已经训练好的模型来计算或提取其权值,Python 提供了许多工具和库,其中最常用的是 ...
- memcached 和 Grails,第 1 部分:安装和使用 memcached
学习 memcached 命令并评估缓存性能 本文是系列文章的第 1 部分,主要介绍 memcached 和 Grails.作者 James Goodwill 将向您介绍开源解决方案 memcache ...
- 从几个sample来学习Java堆,方法区,Java栈和本地方法栈
最近在看<深入理解Java虚拟机>,书中给了几个例子,比较好的说明了几种OOM(OutOfMemory)产生的过程,大部分的程序员在写程序时不会太关注Java运行时数据区域的结构: 感觉有 ...