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

news2024/11/13 9:02:15

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.coloradmin.cn/o/1870450.html

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

相关文章

局域网聊天软件 matrix

窝有 3 只 Android 手机 (3 号手机, 6 号手机, 9 号手机), 2 台 ArchLinux PC (4 号 PC, 6 号 PC), 1 台 Fedora CoreOS 服务器 (5 号). (作为穷人, 窝使用的基本上是老旧的二手设备, 比如 5 年前的手机, 9 年前的笔记本, 10 年前的古老 e5v3 主机, 都比较便宜. ) 窝经常需要 …

format()函数

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 语法介绍 format()可以对数据进行格式化处理操作&#xff0c;语法如下&#xff1a; format(value, format_spec) format_spec为格式化解释。当参数…

高性能Web服务器-Nginx的常用模块

文章目录 Nginx安装Nginx平滑升级与回滚平滑升级流程第1步&#xff0c;下载新版本第2步&#xff0c;编译第3步&#xff0c;执行make第4步&#xff0c;对比新旧版本第5步&#xff0c;备份旧nginx二进制文件第6步&#xff0c;模拟用户正在访问nginx第7步&#xff0c;替换旧的ngin…

The First Descendant第一后裔联机失败、联机报错这样处理

第一后裔/The First Descendant是一款免费的多人合作射击游戏&#xff0c;玩家将进入一片混乱的英格里斯大陆&#xff0c;扮演继承者后裔&#xff0c;通过各种主支线任务和故事剧情触发&#xff0c;最终揭开自身的秘密&#xff0c;并带领大家一起抵抗邪恶势力的入侵。为了避免玩…

Flume学习

Flume(分布式数据采集系统)学习 1.Flume架构 什么是flume&#xff1f; flume是一个分布式、可靠、和高可用的海量日志采集、聚合和传输的系统。 支持在日志系统中定制各类数据发送方&#xff0c;用于收集数据; 同时&#xff0c;Flume提供对数据进行简单处理&#xff0c;并写到…

华为昇腾310B1芯片DVPP模块VENC视频编码接口调用流程以及视频编码代码梳理

目录 1 接口调用流程 2 代码流程梳理 1 接口调用流程 在CANN 8.0.RC1 AscendCL应用软件开发指南 (C&C, 推理) 01.pdf 文档中有接口调用流程 2 代码流程梳理 代码在samples: CANN Samples - Gitee.com 然后我把这个代码完整的看了一遍&#xff0c;然后梳理了详细的代码…

web学习笔记(七十二)

目录 1.vue2通过$parent实现组件传值——父传子 2.vue2 通过$children实现组件传值——子传父 3. provide和inject传值&#xff08;依赖注入&#xff09; 4.vue2如何操作dom 5.vue2如何拿到最新的dom 6.filters过滤器 7.vue2的生命周期 8.vuex的用法 1.vue2通过$parent…

【SCI索引,Fellow主讲】2024年可持续发展与能源资源国际学术会议(SDER 2024,8月9-11)

2024年可持续发展与能源资源国际学术会议&#xff08;SDER 2024&#xff09;将在2024年8月9-11日于中国重庆召开。 大会旨在为从事可持续发展与能源资源方面的专家学者、工程技术人员、技术研发人员提供一个共享科研成果和前沿技术&#xff0c;了解学术发展趋势&#xff0c;拓…

2.4G特技翻斗车方案定制

遥控翻斗车不仅能够提供基本的前进、后退、左转和右转功能&#xff0c;还设计有多种特技动作和互动模式&#xff0c;以增加娱乐性和互动性。 1、无线遥控&#xff1a;玩具翻斗车一般通过2.4G无线遥控器进行控制&#xff0c;允许操作者在一定距离内远程操控车辆。 2、炫彩灯光…

Java程序员接单的十条“野路子”,分分钟收入20K!

Java程序员除了主业工作外&#xff0c;也要适当扩展兼职接单这条路。毕竟Java接单可以说是Java程序员进行技术变现的最佳方式之一。 因为Java程序员兼职接单的难度相对更低&#xff0c;单量也比较可观&#xff0c;最重要的是性价比也很顶&#xff0c;且听我一一道来&#xff1a…

Nature推荐的三种ChatGPT论文写作指令(含PDF下载)

1. 润色学术论文 ChatGPT学术润色指令&#xff1a; “I’m writing a paper on [topic]for a leading [discipline] academic journal. WhatItried to say in the following section is [specific point]. Please rephrase itfor clarity, coherence and conciseness, ensuri…

Charles抓包工具系列文章(五)-- DNS spoofing (DNS域名伪装)

一、背景 DNS域名是依赖DNS域名服务器&#xff0c;特别是内部域名&#xff0c;最后寻址到后端服务地址。 当我们无法修改客户端的域名&#xff0c;而想让其指向到我们期望地址时&#xff0c;可以采用charles的DNS spoofing。 何谓DNS 欺骗&#xff1a;将自己的主机名指定给远…

电商平台数据功能封装API需要注意些什么?如何调用封装后的API?

一、引言 随着电商行业的蓬勃发展&#xff0c;电商平台的数据功能愈发复杂多样&#xff0c;如何高效、安全地管理和使用这些数据成为了电商平台开发者面临的重要问题。API&#xff08;Application Programming Interface&#xff09;作为不同软件之间进行通信的桥梁&#xff0…

Win32消息机制原理及消息运转

一.消息机制原理 1.消息类型&#xff1a; WIndows定义的一系列WM_XXX开头的&#xff0c;用来表示键盘按键&#xff0c;鼠标点击&#xff0c;窗口变化&#xff0c;用户自定义等各种消息; 2.消息队列&#xff1a; Windows为每一个正在运行的程序维护一个消息队列应用程序的消…

Pycharm 文件标头设置

一、设置模板步骤&#xff1a; “文件File--设置Settings--编辑器Editor--File and Code Templates- Python Script” 里面设置模板 官方预设变量表 变量名 含义 ${DATE} 当前系统日期 ${DAY} 当前月的第几日 ${DAY_NAME_SHORT} 当前星期几的单词缩写&#xff08…

计算机网络之数据通信原理(下)

上一讲内容&#xff1a;数据传输方式、数据传输形式、传输差错处理、常用差错检测方法 数据通信过程中&#xff0c;一个很重要的问题就是如何控制数据的传输&#xff0c;就涉及到了传输控制规程&#xff08;协议&#xff09; 下面介绍两种&#xff1a; ①BSC&#xff1a;面向…

java基于ssm+jsp 弹幕视频网站

1前台首页功能模块 弹幕视频网站&#xff0c;在弹幕视频网站可以查看首页、视频信息、商品信息、论坛信息、我的、跳转到后台、购物车、客服等内容&#xff0c;如图1所示。 图1前台首页界面图 登录&#xff0c;通过登录填写账号、密码等信息进行登录操作&#xff0c;如图2所示…

高性能并行计算课程论文:并行网络爬虫的设计与实现

目录 1.绪论 1.1 研究背景 1.2 研究意义 ​​​​​​​1.3 文章结构 2. 网络爬虫相关理论 ​​​​​​​2.1 URL地址格式 ​​​​​​​2.2 网页爬取策略 2.2.1 深度优先策略 2.2.2 广度优先策略 2.2.3 最佳优先策略 ​​​​​​​2.3 网页分析算法 ​​​​​​​2.3.1 正…

three.js - matcap材质(MeshMatcapMaterial)

说一下matcap纹理 先总结&#xff1a;MeshMatcapMaterial材质&#xff0c;通过采样含有光照信息的贴图来模拟光照效果。这种材质特别适用于模拟静态光源下的光照&#xff0c;并且&#xff0c;因其简单性和快速性而被广泛应用于各种场景。但是&#xff0c;由于其性能考虑&#x…

Zynq7000系列FPGA中的DMA控制器——PL外设请求接口

图9-4中展示了PL外设请求接口主要由两部分组成&#xff1a;PL外设请求总线和DMAC确认总线。这两部分分别使用特定的前缀进行标识&#xff0c;具体如下&#xff1a; PL外设请求总线&#xff08;PL Peripheral Request Bus&#xff09;&#xff1a; 前缀&#xff1a;DR功能&…