Qt 基于FFmpeg的视频播放器 - 播放、暂停以及拖动滑动条跳转

Qt 基于FFmpeg的视频转换器 - 播放、暂停以及拖动进度条跳转

  • 引言
  • 一、设计思路
  • 二、核心源码以及相关参考链接

引言

效果展示 另存为gif

  • 本文基于FFmpeg,使用Qt制作了一个极简的视频播放器. 相比之前的版本,加入了播放暂停拖动滑动条跳转功能,如上所示 (左图):
  • 使用AVSEEK_FLAG_ANY可以精准跳转到某一帧,但会出现花屏 (左图).
  • 使用EV录屏,再使用本软件将其转为gif (左图),再GifCam截取本软件转gif的过程 (右图),GifCam无法截取鼠标.

可参考之前的博客:
Qt 基于FFmpeg的视频播放器 - QtFFmpegPlayer
Qt 基于FFmpeg的视频转换器 - 转GIF动图

一、设计思路

    1. 界面设计,鼠标移动到相应位置才会显示相关控件 (按钮、进度条),override鼠标移动事件
void QWidget_PlayVideo::mouseMoveEvent(QMouseEvent *event)
{// 布局在鼠标移动过程中会变化,使得布局内控件闪烁
//    if( m_Hlayout->geometry().contains(event->pos())){
//        for(int i = 0; i < m_Hlayout->count(); i++){
//            QLayoutItem *item = m_Hlayout->itemAt(i);
//            item->widget()->show();
//        }
//    }
//    else{
//        for(int i = 0; i < m_Hlayout->count(); i++){
//            QLayoutItem *item = m_Hlayout->itemAt(i);
//            item->widget()->hide();
//        }
//    }// 使用按钮和滑块的geometry进行判断:鼠标是否移动到窗口底部if( m_btn_startorstop->geometry().contains(event->pos()) ||m_slider->geometry().contains(event->pos())){for(int i = 0; i < m_Hlayout->count(); i++){QLayoutItem *item = m_Hlayout->itemAt(i);item->widget()->show();}}else{for(int i = 0; i < m_Hlayout->count(); i++){QLayoutItem *item = m_Hlayout->itemAt(i);item->widget()->hide();}}
}

建议不要使用布局的geometry,其在鼠标移动过程会变化 (暂不清楚为什么,可能bug 或者控件隐藏之后相关布局会变化,geometry也会随之改变) - 可优化/todo

  1. 初始化就记录下相对坐标,后续可以依据相对坐标判断.
  2. 按钮和进度条固定到最下方显示
    1. 开始和暂停功能,使用一个内部变量判断是否暂停
    connect(m_btn_startorstop, &QPushButton::clicked, this, [&]{    // 按钮点击,暂停 or 继续播放if(m_FFmpegVideo->m_stopPlay == false){qDebug()<<"视频暂停";m_FFmpegVideo->m_stopPlay = true;    // 停止运行,跳出循环// todo 修改按钮,播放}else{qDebug()<<"视频继续播放";m_FFmpegVideo->m_stopPlay = false;m_PlayThread->start();m_PlayThread->quit();   // 执行完后自动关闭,否则一直在运行中... 无法重新start发送开始信号// todo 修改按钮,暂停}});

暂停直接退出线程即可,avformat_context内部会记录进度,再播放会从下一帧继续解码 /todo 使用原子类型
可参考:QThread如何优雅实现暂停(挂起)功能

    1. 拖动进度条跳转
    connect(m_FFmpegVideo, &FFmpegVideo::sig_SendFrameNum_play, this, [&](int frame_id){  // 滑动条随视频播放滑动if(b_slidermoved == false){m_slider->setValue(frame_id);}});connect(m_slider, &QSlider::sliderReleased, this, [&]{     // 滑动条手动滑动,修改视频播放位置qDebug()<< "sliderReleased: " << m_slider->value();this->m_FFmpegVideo->JumptotheFrame(m_slider->value(), m_slider->value(), m_slider->value());this->m_FFmpegVideo->m_frame_id = m_slider->value();b_slidermoved = false;});connect(m_slider, &QSlider::sliderMoved, this, [&]{b_slidermoved = true;});

使用b_slidermoved判断滑动条是否被手动拖动,是的话就先停止滑动条随视频播放滑动. /todo 目前滑动条是根据帧id进行滑动,后续可以改为按照播放时间

void FFmpegVideo::JumptotheFrame(qint64 min_frame_id, qint64 frame_id, qint64 max_frame_id)
{  // 将帧号转换为时间戳int64_t min_ts = min_frame_id * this->m_frame_timestamp;int64_t ts = frame_id * this->m_frame_timestamp;int64_t max_ts = max_frame_id * this->m_frame_timestamp;qDebug()<<"跳转到:" << ts/1000000.0 << "s";// this->av_stream_index// avformat_seek_file(this->avformat_context, -1, min_ts, ts, max_ts, AVSEEK_FLAG_FRAME);avformat_seek_file(this->avformat_context, -1, min_ts, ts, max_ts, AVSEEK_FLAG_ANY);
}

由于传递的参数是第几帧,需将帧号转为视频时间戳
使用AVSEEK_FLAG_ANY可以精准跳转到某一帧,但会出现花屏
使用AVSEEK_FLAG_FRAME不会出现花屏,但是无法精准跳转某帧,只会跳转到视频关键帧

  • /todo 还有很多待优化的bug…

二、核心源码以及相关参考链接

    1. 全部源码

已在gitee开源:QtFFmpegPlayerDemo

    1. 相关参考链接

【Qt+FFmpeg】解码播放本地视频(二)——实现播放、暂停、重播、倍速功能
【FFmpeg+Qt】视频进度条控制——点击跳转和拖动跳转
FFmpeg源码分析:av_seek_frame()与avformat_seek_file()
avformat_seek_file函数介绍
FFmpeg中的时间基(time_base), AV_TIME_BASE
ffmpeg协议之接口篇之快进快退(av_seek_frame)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/862095.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SpringSecutrity原理

一、基于RBAC实现的权限管理通常需要涉及以下几张表&#xff1a; 1. 用户表&#xff08;user&#xff09;&#xff1a;记录系统中的所有用户&#xff0c;包括用户ID、用户名、密码等信息。 2. 角色表&#xff08;role&#xff09;&#xff1a;记录系统中的所有角色&#xff0…

基于51单片机太阳能风能风光互补路灯控制器

一.硬件方案 本设计由STC89C52单片机电路太阳能电池板电路风机发电电路锂电池充电保护电路升压电路稳压电路光敏电阻电路4位高亮LED灯电路2档拨动开关电路电源电路设计而成。 二.设计功能 &#xff08;1&#xff09;采用风机和太阳能电池板给锂电池充电&#xff0c;具有充电…

系统架构设计师 - 数据库系统(2)

数据库系统 数据库系统规范化理论 ★ ★ ★ ★ ★函数依赖求候选键Armstrong公理范式判断第一范式 1NF第二范式 2NF第三范式 3NFBC 范式 BCNF 模式分解保持函数依赖分解无损分解 并发控制 ★事务的 ACID 特性并发存在的问题并发解决方案 - 封锁协议 数据库的安全性 ★安全性的分…

十三、Maven(1)

&#x1f33b;&#x1f33b;目录 一、maven价绍二、maven的功能1、项目自动化构建2、管理jar、war包3、实现项目结构设计 三、maven安装1、maven的安装环境需要jdk2、Maven的安装路径中不能出现中文和空格3、压缩包解压即可4、配置环境变量 四、maven的仓库1. Maven仓库配置2. …

选型手册:Bosch Sensortec 博世 微机电系统(MEMS)传感器和方案

前言 博世传感器公司&#xff08;Bosch Sensortec&#xff09; 是全球领先的微机电系统&#xff08;MEMS&#xff09;传感器和解决方案供应商。公司成立于2005年&#xff0c;是德国罗伯特博世有限公司&#xff08;Robert Bosch GmbH&#xff09;旗下的全资子公司。博世传感器公…

SpringBoot【3】集成 Swagger

SpringBoot 集成 Swagger 前言pom.xml 配置文件application.yml 配置文件config 包Swagger2Config entity 包UserEntity service 包impl 包SwaggerServiceImpl SwaggerService controller 包SwaggerController SwaggerApplication验证 前言 创建项目步骤、及版本选择等&#x…

展开说说:Android列表之RecyclerView

RecyclerView 它是从Android5.0出现的全新列表组件&#xff0c;更加强大和灵活。用于显示列表形式 (list) 或者网格形式 (grid) 的数据&#xff0c;替代ListView和GridView成为Android主流的列表组件。可以说Android客户端只要有表格的地方就有RecyclerView。 RecyclerView 内…

VCS编译bug汇总

‘typedef’ is not expected to be used in this contex 注册前少了分号。 Scope resolution error resolution : 声明指针时 不能与类名同名&#xff0c;即 不能声明为adapter. cannot find member "type_id" 忘记注册了 拼接运算符使用 关键要加上1b&#xff0…

[MySQL]购物管理系统—简略版

本文内容需以MySQL支持 特别感谢baidu comate AI提供的少量虚拟数据 0.建库(建立数据库——utf8字符集&#xff0c;utf8_general_ci排序规则) 1.此项目ER图如下 2.DDLDML(共九表&#xff0c;27数据) SET FOREIGN_KEY_CHECKS 0;DROP TABLE IF EXISTS goods; CREATE TABLE g…

前端vue-cli相关知识与搭建过程(项目创建,组件路由)very 详细

一.关于vue-cli 1.什么是vue Vue (读音 /vju ː /&#xff0c;类似于 view) 是一套用于构建用户界面的渐进式框架。Vue 的核心库只关注视图层&#xff0c;不仅易于上手&#xff0c;还便于与第三方库或既有项目整合。 Vue.js 是前端的主流框架之一&#xff0c;和 Angular.js…

【公开数据集获取】

Open Images Dataset https://www.youtube.com/watch?vdLSFX6Jq-F0

【M365运维】Outlook和Teams里不显示用户的组织架构

【问题】 由于一些误操作&#xff0c;把用户账户禁用并重新启用后&#xff0c;发现在Outlook和Teams里无法查看用户的组织结构图了。如下图所示&#xff1a; - 在Outlook 里&#xff0c;用户标签页的组织一直显示“正在加载..."&#xff0c;成员身份也是“找不到任何组。…

【GD32】08 - IIC(以SHT20为例)

GD32中的IIC 今天来了解一下GD32中的硬件IIC&#xff0c;其实我个人是觉得软件IIC比较方便的&#xff0c;不过之前文章里用的都是软件IIC&#xff0c;今天就算是走出自己的舒适圈&#xff0c;我们来了解了解GD32中的硬件IIC。 我这里用的型号是GD32F407&#xff0c;不同型号的…

等保测评初级简答题试题

基本要求&#xff0c;在应用安全层面的访问控制要求中&#xff0c;三级系统较二级系统增加的措施有哪些&#xff1f; 答&#xff1a;三级比二级增加的要求项有&#xff1a; 应提供对重要信息资源设置敏感标记的功能&#xff1b; 应按照安全策略严格控制用户对有敏感标记重要…

策略模式和状态模式

策略模式 在上下文中携带策略接口作为成员变量&#xff0c;在使用上下文之前需要设置策略setStrategy&#xff08;&#xff09;&#xff0c;然后使用策略接口成员变量来进行策略的执行。 步骤1&#xff1a;定义策略接口 // 策略接口 public interface Strategy {int execut…

干涉阵型成图参数记录【robust】

robust 这个玩意经常忘记&#xff0c;就是取2的时候是更加显示大尺度的结构&#xff0c;取-2更加显示小尺度结果&#xff0c;一般取0就是正常就好了

【Hive中常见的优化手段----数据采集!Join 优化!Hive索引!数据倾斜!mapreduce本地模式!map和reduce数量调整!】

前言&#xff1a; &#x1f49e;&#x1f49e;大家好&#xff0c;我是书生♡&#xff0c;今天主要和大家分享一下Hive中常见的优化手段----数据采集&#xff01;常见的Join 优化有哪几种&#xff01;什么是Hive索引&#xff01;数据怎么发生倾斜&#xff01;什么是mapreduce的本…

力扣每日一题 6/24 模拟 数组 单调栈

博客主页&#xff1a;誓则盟约系列专栏&#xff1a;IT竞赛 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ 503.下一个更大元素II 【中等】 题目&#xff1a; 给定一个循环数组 nums…

使用原子子表创建可重用的子组件

原子子表是一个图形对象&#xff0c;可帮助您在Stateflow图表中创建独立的子部件。原子子表允许&#xff1a; 对具有多个状态或层次结构的图表进行微小更改后&#xff0c;模拟速度更快。 在多个图表和模型中重复使用相同的状态或子表。 易于团队开发&#xff0c;适用于在同一图…

Python网络爬虫实战6—下一页,模拟用户点击,切换窗口

【前期提要】感兴趣的可以看看往期文章哈~ Python网络爬虫5-实战网页爬取 Python网络爬虫4-实战爬取pdf Pyhon网络爬虫3-模拟用户点击 Python网络爬虫实战2-下载url下的pdf Python网络爬虫基础1 1.需求背景 针对长虹美菱电器说明书网页形式&#xff0c;编写爬虫代码&#xff…