Qt展厅播放器/多媒体播放器/中控播放器/帧同步播放器/硬解播放器/监控播放器
一、前言说明
音视频开发除了应用在安防监控、视频网站、各种流媒体app开发之外,还有一个小众的市场,那就是多媒体展厅场景,这个场景目前处于垄断地位的软件是HirenderS3,做的非常早而且非常全面,都是通用的需求,这个场景需求,在播放这块,有几个明显的需求是,播放的视频文件分辨率特别大,一般是4K/8K甚至到16K,展厅的屏幕很大,分辨率小了的话,不够清晰,所以至少会上4K分辨率,一般超过2K的分辨率,一定要上硬解码,不然CPU很可能撑不住,这里问题就来了,在底层(不清楚是操作系统层面还是硬件层面),264只能支持4K硬解,265支持到8K硬解,再往上的分辨率都不支持的,而现在不少的多媒体文件是8K的264格式,12K/16K的265,那怎么办,不开启硬解的话,资源极其紧张,几乎是快占满的节奏,所以要从逻辑层面去优化,一个办法是外接多个显卡对应显示器,文件切割成多个4K或者8K,每个文件指定一个显卡去硬解,显示在指定的显示器上。一个办法是用多个显示窗体拼接,每个播放窗体都可以硬解。
还有个重要需求点是同步问题,如果是本地多个画面拼接,则需要帧同步,不然开起来多画面是不够衔接的,大于1帧的误差能够肉眼可见,多个电脑之间不同播放器也需要帧同步,所以就产生了两种帧同步需求,一个是本地帧同步,一个是网络帧同步,本地帧同步主要是控制同时解码同一帧后同时刷新显示,网络帧同步比较麻烦,因为必须通过网络数据通知当前都是播放第一帧,这个网络通信都是有延迟的,所以还需要考虑延迟的时间。
二、效果图


三、相关代码
#include "synclocal.h"
#include "qthelper.h"
#include "frmplay.h"SINGLETON_IMPL(SyncLocal)
QDateTime SyncLocal::SyncTime = QDateTime::currentDateTime().addDays(-1);
SyncLocal::SyncLocal(QObject *parent) : QThread(parent)
{isStop = false;this->reset();syncInterval = 5;syncOffset = 15;syncSleep = 500;updateInterval = 10;
}SyncLocal::~SyncLocal()
{this->stop();
}void SyncLocal::run()
{while (!isStop) {this->checkPosition();this->checkSync();this->checkPause();this->updateWidget();count++;msleep(updateInterval);//qDebug() << TIMEMS << "111" << updateInterval << count;}isStop = false;this->reset();
}void SyncLocal::checkPosition()
{//同步间隔0表示不启用/至少要2个窗体才需要同步int size = frmPlay::widgets.size();if (size < 2 || isSync || isPasue) {count = 0;return;}//永远同步到到第一个窗体/处于非播放状态/或者暂停状态不用继续frmPlay *widget = frmPlay::widgets.first();if (!widget->isPlaying() || widget->isPaused()) {return;}//优先执行手动同步指令/-1则同步到第一个窗体/>=0则同步到对应位置if (syncPosition >= -1) {position = (syncPosition == -1 ? widget->position() : syncPosition);count = 0;isSync = true;qDebug() << TIMEMS << "hand" << position;return;}//同步间隔0表示不启用if (syncInterval == 0) {count = 0;return;}//计算同步间隔需要循环多少次int maxCount = syncInterval * 1000 / updateInterval;//到了需要同步的时候执行同步if (count < maxCount) {return;}count = 0; //刚开始或者快结束先不同步position = widget->position();if (position < 2000 || qAbs(widget->duration() - position) < 2000) {return;}for (int i = 1; i < size; ++i) {offset = position - frmPlay::widgets.at(i)->position();qDebug() << TIMEMS << "posi" << position << "\t" << offset;if (qAbs(offset) >= syncOffset) {isSync = true;break;}}
}void SyncLocal::checkSync()
{//同步标志位为真则先同步if (isSync) {count = 0;isSync = false;isPasue = true;SyncTime = QDateTime::currentDateTime();qDebug() << TIMEMS << "seek" << position;//先暂停再执行设置进度foreach (frmPlay *widget, frmPlay::widgets) {widget->pause();widget->seek(position);}}
}void SyncLocal::checkPause()
{//暂停阶段说明刚才执行过同步/等待一段时间重新播放if (isPasue) {qint64 time = SyncTime.msecsTo(QDateTime::currentDateTime());if (time >= syncSleep) {foreach (frmPlay *widget, frmPlay::widgets) {widget->next();}count = 0;isPasue = false;syncPosition = -2;emit receiveSync(offset);qDebug() << TIMEMS << "play" << position;}}
}void SyncLocal::updateWidget()
{//刷新界面用来触发绘制foreach (frmPlay *widget, frmPlay::widgets) {widget->updateVideo();}
}void SyncLocal::setSyncInterval(int syncInterval)
{this->reset();this->syncInterval = syncInterval;
}void SyncLocal::setSyncOffset(int syncOffset)
{this->syncOffset = syncOffset;
}void SyncLocal::setSyncSleep(int syncSleep)
{this->syncSleep = syncSleep;
}void SyncLocal::setUpdateInterval(int updateInterval)
{this->updateInterval = updateInterval;
}void SyncLocal::stop()
{if (this->isRunning()) {this->isStop = true;this->wait();}
}void SyncLocal::reset()
{this->count = 0;this->isSync = false;this->isPasue = false;this->syncPosition = -2;
}//-1则同步到第一个窗体/>=0则同步到对应位置
void SyncLocal::sync(qint64 position)
{//至少要两个窗体才能同步/处于暂停阶段说明上一个同步还没执行完成if (frmPlay::widgets.size() >= 2 && !isPasue && syncPosition == -2) {this->syncPosition = position;}
}
四、相关地址
- 国内站点:https://gitee.com/feiyangqingyun
- 国际站点:https://github.com/feiyangqingyun
- 个人作品:https://blog.csdn.net/feiyangqingyun/article/details/97565652
- 文件地址:https://pan.baidu.com/s/1d7TH_GEYl5nOecuNlWJJ7g 提取码:01jf 文件名:bin_video_sync。
五、功能特点
- 实时帧同步,本地无缝拼接多个视频。
- 支持网络同步,可选主控端和被控端,主控端将本地播放的进度实时同步到被控端。
- 网络同步支持组播、广播、单播三种模式,默认组播,既可以跨网段,也可以避免广播数据风暴。
- 默认开启自动同步,也可以手动同步和复位同步,手动同步是立即执行一次同步,将第一个视频的进度同步到其他视频文件,复位同步是将所有视频播放进度切换到最开始0的位置。
- 支持各种视音频文件,包括但不限于mp4/mov/mkv/rmvb/avi等格式。
- 硬解码和GPU绘制,最大化利用硬件资源,支持qsv/cuda/dxva2/d3d11va/vaapi等硬解码。
- 极低的CPU占用,8K30fps只占不到1%的CPU,解码和绘制全部交给GPU。
- 提供示例按照行列生成多个视频播放窗口,每个窗口可以选择不同的视频文件,在手动同步模式下,可以切换任意一个视频播放进度,会将所有的视频按照这个进度同步。
- 自动循环播放视频文件,无缝切换循环播放,看起来非常丝滑。
- 支持Qt4/Qt5/Qt6所有版本,支持各种操作系统包括国产OS和嵌入式OS。
相关文章:
Qt展厅播放器/多媒体播放器/中控播放器/帧同步播放器/硬解播放器/监控播放器
一、前言说明 音视频开发除了应用在安防监控、视频网站、各种流媒体app开发之外,还有一个小众的市场,那就是多媒体展厅场景,这个场景目前处于垄断地位的软件是HirenderS3,做的非常早而且非常全面,都是通用的需求&…...
Kafka分区策略实现
引言 Kafka 的分区策略决定了生产者发送的消息会被分配到哪个分区中,合理的分区策略有助于实现负载均衡、提高消息处理效率以及满足特定的业务需求。 轮询策略(默认) 轮询策略是 Kafka 默认的分区策略(当消息没有指定键时&…...
【归属地】批量号码归属地查询按城市高速的分流,基于WPF的解决方案
在现代商业活动中,企业为了提高营销效果和资源利用效率,需要针对不同地区的市场特点开展精准营销。通过批量号码归属地查询并按城市分流,可以为企业的营销决策提供有力支持。 短信营销:一家连锁餐饮企业计划开展促销活动…...
为AI聊天工具添加一个知识系统 之78 详细设计之19 正则表达式 之6
本文要点 要点 本项目设计的正则表达式 是一个 动态正则匹配框架。它是一个谓词系统:谓词 是运动,主语是“维度”,表语是 语言处理。主语的一个 双动结构。 Reg三大功能 语法验证、语义检查和 语用检验,三者 :语义约…...
使用Java操作Redis数据类型的详解指南
SEO Meta Description: 详细介绍如何使用Java操作Redis的各种数据类型,包括字符串、哈希、列表、集合和有序集合,提供代码示例和最佳实践。 介绍 Redis是一种开源的内存数据结构存储,用作数据库、缓存和消息代理。它支持多种数据结构&#…...
一表总结 Java 的3种设计模式与6大设计原则
设计模式通常分为三大类:创建型、结构型和行为型。 创建型模式:主要用于解决对象创建问题结构型模式:主要用于解决对象组合问题行为型模式:主要用于解决对象之间的交互问题 创建型模式 创建型模式关注于对象的创建机制…...
Hive on Spark优化
文章目录 第1章集群环境概述1.1 集群配置概述1.2 集群规划概述 第2章 Yarn配置2.1 Yarn配置说明2.2 Yarn配置实操 第3章 Spark配置3.1 Executor配置说明3.1.1 Executor CPU核数配置3.1.2 Executor内存配置3.1.3 Executor个数配置 3.2 Driver配置说明3.3 Spark配置实操 第4章 Hi…...
Java集合面试总结(题目来源JavaGuide)
问题1:说说 List,Set,Map 三者的区别? 在 Java 中,List、Set 和 Map 是最常用的集合框架(Collection Framework)接口,它们的主要区别如下: 1. List(列表) 特点…...
计算机网络 应用层 笔记1(C/S模型,P2P模型,FTP协议)
应用层概述: 功能: 常见协议 应用层与其他层的关系 网络应用模型 C/S模型: 优点 缺点 P2P模型: 优点 缺点 DNS系统: 基本功能 系统架构 域名空间: DNS 服务器 根服务器: 顶级域…...
ES6基础内容
ES 全称 EcmaScript ,是脚本语言的规范,而平时经常编写的 JavaScript 是 EcmaScript 的一种实现,所以 ES 新特性其实指的就是 JavaScript 的新特性。 一、 let变量声明和声明特性 1.1 变量声明 <!DOCTYPE html> <html lang"en">…...
DeepSeek本地部署的一些使用体会
春节期间我也尝试了一下Deepseek的本地部署,方案选用了Ollama Chatbox或AnythingLLM。Chatbox里有很多有意思的“助手”,而AnythingLLM支持本地知识库。 网上教程很多,总的来说还是很方便的,不需要费太多脑子。甚至可以这么说&a…...
鲸鱼算法 matlab pso
算法原理 鲸鱼优化算法的核心思想是通过模拟座头鲸的捕食过程来进行搜索和优化。座头鲸在捕猎时会围绕猎物游动并产生气泡网,迫使猎物聚集。这一行为被用来设计搜索策略,使算法能够有效地找到全局最优解。 算法步骤 初始化:随机生成一…...
013-51单片机红外遥控器模拟控制空调,自动制冷制热定时开关
主要功能是通过红外遥控器模拟控制空调,可以实现根据环境温度制冷和制热,能够通过遥控器设定温度,可以定时开关空调。 1.硬件介绍 硬件是我自己设计的一个通用的51单片机开发平台,可以根据需要自行焊接模块,这是用立创…...
在Vue3 + Vite 项目中使用 Tailwind CSS 4.0
文章目录 首先是我的package.json根据官网步骤VS Code安装插件验证是否引入成功参考资料 首先是我的package.json {"name": "aplumweb","private": true,"version": "0.0.0","type": "module","s…...
Leetcode—922. 按奇偶排序数组 II【简单】
2025每日刷题(207) Leetcode—922. 按奇偶排序数组 II 实现代码 class Solution { public:vector<int> sortArrayByParityII(vector<int>& nums) {for(int i 0, j 1; i < nums.size() - 1; i 2) {// 前奇后偶if(nums[i] % 2) {w…...
一个开源 GenBI AI 本地代理(确保本地数据安全),使数据驱动型团队能够与其数据进行互动,生成文本到 SQL、图表、电子表格、报告和 BI
一、GenBI AI 代理介绍(文末提供下载) github地址:https://github.com/Canner/WrenAI 本文信息图片均来源于github作者主页 在 Wren AI,我们的使命是通过生成式商业智能 (GenBI) 使组织能够无缝访问数据&…...
使用Posix共享内存区实现进程间通信
使用Posix共享内存区实现进程间通信 使用Posix共享内存区通常涉以下步骤: 进程A 调用shm_open 创建共享内存区进程A调用ftruncate修改共享内存区大小进程A 调用mmap将共享内存区映射到进程地址空间ptrA进程A 使用ptrA对共享内存区进程更改进程B 使用shm_open打开已有共享内存…...
家政预约小程序12服务详情
目录 1 修改数据源2 创建页面3 搭建轮播图4 搭建基本信息5 显示服务规格6 搭建服务描述7 设置过滤条件总结 我们已经在首页、分类页面显示了服务的列表信息,当点击服务的内容时候需要显示服务的详情信息,本篇介绍一下详情页功能的搭建。 1 修改数据源 在…...
【C语言】指针详细解读2
1.const 修饰指针 1.1 const修饰变量 变量是可以修改的,如果把变量的地址交给⼀个指针变量,通过指针变量的也可以修改这个变量。 但是如果我们希望⼀个变量加上⼀些限制,不能被修改,怎么做呢?这就是const的作⽤。 #in…...
MongoDB 聚合
MongoDB 中聚合(aggregate)主要用于处理数据(诸如统计平均值,求和等),并返回计算后的数据结果。 有点类似 SQL 语句中的 count(*)。 aggregate() 方法 MongoDB中聚合的方法使用aggregate()。 语法 aggregate() 方法的基本语法格式如下所示࿱…...
接口测试中缓存处理策略
在接口测试中,缓存处理策略是一个关键环节,直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性,避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明: 一、缓存处理的核…...
Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...
【力扣数据库知识手册笔记】索引
索引 索引的优缺点 优点1. 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度(创建索引的主要原因)。3. 可以加速表和表之间的连接,实现数据的参考完整性。4. 可以在查询过程中,…...
(二)TensorRT-LLM | 模型导出(v0.20.0rc3)
0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述,后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作,其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...
【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)
要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况,可以通过以下几种方式模拟或触发: 1. 增加CPU负载 运行大量计算密集型任务,例如: 使用多线程循环执行复杂计算(如数学运算、加密解密等)。运行图…...
【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)
升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点,但无自动故障转移能力,Master宕机后需人工切换,期间消息可能无法读取。Slave仅存储数据,无法主动升级为Master响应请求ÿ…...
实现弹窗随键盘上移居中
实现弹窗随键盘上移的核心思路 在Android中,可以通过监听键盘的显示和隐藏事件,动态调整弹窗的位置。关键点在于获取键盘高度,并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...
2023赣州旅游投资集团
单选题 1.“不登高山,不知天之高也;不临深溪,不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...
RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)
RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发,后来由Pivotal Software Inc.(现为VMware子公司)接管。RabbitMQ 是一个开源的消息代理和队列服务器,用 Erlang 语言编写。广泛应用于各种分布…...
MySQL JOIN 表过多的优化思路
当 MySQL 查询涉及大量表 JOIN 时,性能会显著下降。以下是优化思路和简易实现方法: 一、核心优化思路 减少 JOIN 数量 数据冗余:添加必要的冗余字段(如订单表直接存储用户名)合并表:将频繁关联的小表合并成…...
