FFmpeg 4.3 音视频-多路H265监控录放C++开发六,使用SDLVSQT显示yuv文件
使用QT 显示YUV 文件
在最后一帧的时候会不停的显示最后一帧图片。
Vsqtshowyuv.h
#pragma once#include <QtWidgets/QWidget>
#include "ui_vsqtshowyuv.h"
#include <sdl/SDL.h>
#include <iostream>
#include <fstream>
#include <QFile>
using namespace std;#undef main
class Vsqtshowyuv : public QWidget
{Q_OBJECTpublic:Vsqtshowyuv(QWidget *parent = nullptr);~Vsqtshowyuv();private:Ui::VsqtshowyuvClass ui;WId _labelid = 0;//我们这里要显示的yuv是400x300x25 的,在yuv的file 中我们是无法知道yuv大小的,因此要固定。///后面我们解析的mp4文件,flv文件,由于头文件是有 视频文件的大小的,因此可以通过代码从mp4文件中获得int _label_width = 400;int _label_height = 300;SDL_Window* _sdlwindow = nullptr;SDL_Renderer* _sdlrenderer = nullptr;SDL_Texture* _sdltexture = nullptr;//使用qfile 也可以读取,这里我们并没有使用qfileQFile _qt_yuvfile;ifstream _yuv_file;unsigned char* _yuv_data = nullptr;
private:int startSDL();void timerEvent(QTimerEvent* ev) override;void endSDL();
};
Vsqtshowyuv.cpp
#include "vsqtshowyuv.h"
#include <fstream>Vsqtshowyuv::Vsqtshowyuv(QWidget *parent): QWidget(parent)
{int ret = 0;ui.setupUi(this);_labelid = ui.label->winId();resize(_label_width, _label_height);ui.label->resize(_label_width, _label_height);ui.label->move(0, 0);ret = startSDL(); if (ret < 0) {///如果 SDL 的初始化什么的都失败了,需要销毁资源,并且退出endSDL();cout << "startSDL error, so can not show YUV information ." << endl;ui.label->setText("can not show YUV becase SDL has error");return;}else {//我们这里要播放yuv数据,每次播放yuv视频中的一张,那么有三个事情要做:// 1。打开yuv file,// 2。并通过 starttimer 定时在timerEvent从 yuv中读取一张数据,然后显示// 3. 每个40ms 通过 timerevent 刷新一次。//我们的yuv视频是25帧,1秒25次,1000毫秒/25 = 40,也就是说,我们40毫秒更新一次//但是实际测试并不能在40ms中更新一次,这里只是通过 QT 的这个机制显示出来,在实际开发中不能用这个方法_yuv_file.open("400_300_25.yuv", ios::binary);if (!_yuv_file) {cout << "_yuv_file open 400_300_25.yuv ios::binary error, so can not show YUV information ." << endl;ui.label->setText("can not show YUV becase open 400_300_25.yuv ios::binary error");endSDL();return;}//将要存储的数据的大小 new 出来_yuv_data = new unsigned char[_label_width * _label_height * 1.5];startTimer(40);}}Vsqtshowyuv::~Vsqtshowyuv()
{endSDL();
}int Vsqtshowyuv::startSDL() {int ret = 0;/// 1. SDL initret = SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO);if (ret < 0) {ret = -1;cout << "SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO) error " << SDL_GetError() << endl;return ret;}/// 2. create SDL windows_sdlwindow = SDL_CreateWindowFrom((void *)_labelid);if (!_sdlwindow) {ret = -2;cout << "SDL_CreateWindowFrom error " << SDL_GetError() << endl;return ret;}/// 3。 create SDL renderer 渲染器_sdlrenderer = SDL_CreateRenderer(_sdlwindow, -1, SDL_RENDERER_ACCELERATED);if (!_sdlrenderer) {cout << "SDL_CreateRenderer SDL_RENDERER_ACCELERATED error now try use SDL_RENDERER_SOFTWARE create SDL_RENDERER " << SDL_GetError() << endl;_sdlrenderer = SDL_CreateRenderer(_sdlwindow, -1, SDL_RENDERER_SOFTWARE);if (!_sdlrenderer) {ret = -3;cout << "SDL_CreateRenderer SDL_RENDERER_SOFTWARE also error " << SDL_GetError() << endl;return ret;}return ret;}///4. create texture 材质,要显示YUV数据,因此用SDL_PIXELFORMAT_IYUV_sdltexture = SDL_CreateTexture(_sdlrenderer,SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_STREAMING, _label_width, _label_height);if (!_sdltexture) {ret = -4;cout << "SDL_CreateTexture error " << SDL_GetError() << endl;return ret;}return ret;
}void Vsqtshowyuv::endSDL() {if (_sdltexture) {SDL_DestroyTexture(_sdltexture);_sdltexture = nullptr;}if (_sdlrenderer) {SDL_DestroyRenderer(_sdlrenderer);_sdlrenderer = nullptr;}if (_sdlwindow) {SDL_DestroyWindow(_sdlwindow);_sdlwindow = nullptr;}SDL_Quit();
}void Vsqtshowyuv::timerEvent(QTimerEvent* ev) {cout << "timerEvent start" << endl;//将数据读取到_yuv_data,每次读取数据的大小为一张图片的大小,我们是YUV420P的图片,一张图片大小为 1.5 * 宽 * 高;实际上是一个 SDL_PIXELFORMAT_IYUV = /**< Planar mode: Y + U + V (3 planes) */int datasize = _label_width * _label_height * 1.5;//read 方法说明,The function read() is used with input streams, and reads num bytes from the stream before placing them in buffer.If EOF is encountered, read() stops, leaving however many bytes it put into buffer as they are._yuv_file.read((char*)_yuv_data, datasize);//我们这里是要做一些判断的,如果读取发生了问题,或者读取到了文件的末尾,需要做额外的处理//由于read 方法在读取到文件的EOF的时候,read会stop,这时候会发生什么情况呢 ?_yuv_data里面保存着最后一帧,因此理论上会一直刷新最后一帧图片数据//来验证猜想,验证确实是这样。SDL_UpdateTexture(_sdltexture, NULL, _yuv_data, _label_width //一行 y的字节数);SDL_RenderClear(_sdlrenderer);SDL_Rect rect;rect.x = 0;rect.y = 0;rect.w = _label_width;rect.h = _label_height;SDL_RenderCopy(_sdlrenderer, _sdltexture, NULL, &rect);SDL_RenderPresent(_sdlrenderer);cout << "timerEvent end" << endl;}
使用QT 显示循环 播放YUV 文件
#include "vsqtshowyuv.h"
#include <fstream>Vsqtshowyuv::Vsqtshowyuv(QWidget *parent): QWidget(parent)
{int ret = 0;ui.setupUi(this);_labelid = ui.label->winId();resize(_label_width, _label_height);ui.label->resize(_label_width, _label_height);ui.label->move(0, 0);ret = startSDL(); if (ret < 0) {///如果 SDL 的初始化什么的都失败了,需要销毁资源,并且退出endSDL();cout << "startSDL error, so can not show YUV information ." << endl;ui.label->setText("can not show YUV becase SDL has error");return;}else {//我们这里要播放yuv数据,每次播放yuv视频中的一张,那么有三个事情要做:// 1。打开yuv file,// 2。并通过 starttimer 定时在timerEvent从 yuv中读取一张数据,然后显示// 3. 每个40ms 通过 timerevent 刷新一次。//我们的yuv视频是25帧,1秒25次,1000毫秒/25 = 40,也就是说,我们40毫秒更新一次//但是实际测试并不能在40ms中更新一次,这里只是通过 QT 的这个机制显示出来,在实际开发中不能用这个方法_yuv_file.open("400_300_25.yuv", ios::binary);if (!_yuv_file) {cout << "_yuv_file open 400_300_25.yuv ios::binary error, so can not show YUV information ." << endl;ui.label->setText("can not show YUV becase open 400_300_25.yuv ios::binary error");endSDL();return;}//将要存储的数据的大小 new 出来_yuv_data = new unsigned char[_label_width * _label_height * 1.5];startTimer(40);}}Vsqtshowyuv::~Vsqtshowyuv()
{endSDL();
}int Vsqtshowyuv::startSDL() {int ret = 0;/// 1. SDL initret = SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO);if (ret < 0) {ret = -1;cout << "SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO) error " << SDL_GetError() << endl;return ret;}/// 2. create SDL windows_sdlwindow = SDL_CreateWindowFrom((void *)_labelid);if (!_sdlwindow) {ret = -2;cout << "SDL_CreateWindowFrom error " << SDL_GetError() << endl;return ret;}/// 3。 create SDL renderer 渲染器_sdlrenderer = SDL_CreateRenderer(_sdlwindow, -1, SDL_RENDERER_ACCELERATED);if (!_sdlrenderer) {cout << "SDL_CreateRenderer SDL_RENDERER_ACCELERATED error now try use SDL_RENDERER_SOFTWARE create SDL_RENDERER " << SDL_GetError() << endl;_sdlrenderer = SDL_CreateRenderer(_sdlwindow, -1, SDL_RENDERER_SOFTWARE);if (!_sdlrenderer) {ret = -3;cout << "SDL_CreateRenderer SDL_RENDERER_SOFTWARE also error " << SDL_GetError() << endl;return ret;}return ret;}///4. create texture 材质,要显示YUV数据,因此用SDL_PIXELFORMAT_IYUV_sdltexture = SDL_CreateTexture(_sdlrenderer,SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_STREAMING, _label_width, _label_height);if (!_sdltexture) {ret = -4;cout << "SDL_CreateTexture error " << SDL_GetError() << endl;return ret;}return ret;
}void Vsqtshowyuv::endSDL() {if (_sdltexture) {SDL_DestroyTexture(_sdltexture);_sdltexture = nullptr;}if (_sdlrenderer) {SDL_DestroyRenderer(_sdlrenderer);_sdlrenderer = nullptr;}if (_sdlwindow) {SDL_DestroyWindow(_sdlwindow);_sdlwindow = nullptr;}SDL_Quit();
}void Vsqtshowyuv::timerEvent(QTimerEvent* ev) {cout << "timerEvent start" << endl;//将数据读取到_yuv_data,每次读取数据的大小为一张图片的大小,我们是YUV420P的图片,一张图片大小为 1.5 * 宽 * 高;实际上是一个 SDL_PIXELFORMAT_IYUV = /**< Planar mode: Y + U + V (3 planes) */int datasize = _label_width * _label_height * 1.5;//read 方法说明,The function read() is used with input streams, and reads num bytes from the stream before placing them in buffer.If EOF is encountered, read() stops, leaving however many bytes it put into buffer as they are.istream& is= _yuv_file.read((char*)_yuv_data, datasize);if (_yuv_file.good()) {cout << "Read " << _yuv_file.gcount() << endl;}else {cout << "Error occurred during read" << endl;if (_yuv_file.eof()) {cout << "Reached end of file" << endl;///这里有个问题,就是我们是通过 file 关闭,然后重新打开的方式让从头读取,应该是可以改动指针来完成_yuv_file.close();_yuv_file.open("400_300_25.yuv", ios::binary);}}//我们这里是要做一些判断的,如果读取发生了问题,或者读取到了文件的末尾,需要做额外的处理//由于read 方法在读取到文件的EOF的时候,read会stop,这时候会发生什么情况呢 ?_yuv_data里面保存着最后一帧,因此理论上会一直刷新最后一帧图片数据//来验证猜想,验证确实是这样。SDL_UpdateTexture(_sdltexture, NULL, _yuv_data, _label_width //一行 y的字节数);SDL_RenderClear(_sdlrenderer);SDL_Rect rect;rect.x = 0;rect.y = 0;rect.w = _label_width;rect.h = _label_height;SDL_RenderCopy(_sdlrenderer, _sdltexture, NULL, &rect);SDL_RenderPresent(_sdlrenderer);cout << "timerEvent end" << endl;}
相关文章:
FFmpeg 4.3 音视频-多路H265监控录放C++开发六,使用SDLVSQT显示yuv文件
使用QT 显示YUV 文件 在最后一帧的时候会不停的显示最后一帧图片。 Vsqtshowyuv.h #pragma once#include <QtWidgets/QWidget> #include "ui_vsqtshowyuv.h" #include <sdl/SDL.h> #include <iostream> #include <fstream> #include <Q…...
Spring 设计模式之适配器模式
Spring 设计模式之适配器模式 适配器模式用到的场景java举例 适配器模式 适配器模式(Adapter Pattern)是一种结构型设计模式,它允许接口不兼容的类一起工作。 其核心思想是通过一个适配器类将不兼容的接口转换成客户端期望的另一个接口&…...
多传感器数字化分析系统
在工业飞速发展的今天,设备的安全稳定运行成为企业高效生产的关键因素。然而,传统的人工巡检方式面临着诸多挑战,如效率低下、漏检误检以及难以精准掌握设备运行状态等。旗晟凭借深厚的技术积累和创新精神,推出了多传感器数字化分…...
Java 基础教学:面向对象编程基础-封装、继承与多态
面向对象编程(OOP)是现代编程的重要范式,Java 语言提供了丰富的 OOP 特性,主要包括封装、继承和多态。本文将详细讲解这三个概念及其实现方式,并提供相应的代码示例。 1. 封装 1.1 概念 封装是将对象的状态…...
Ubuntu环境本地部署DbGate数据库管理工具并实现无公网IP远程访问
文章目录 前言1. 安装Docker2. 使用Docker拉取DbGate镜像3. 创建并启动DbGate容器4. 本地连接测试5. 公网远程访问本地DbGate容器5.1 内网穿透工具安装5.2 创建远程连接公网地址5.3 使用固定公网地址远程访问 前言 本文主要介绍如何在Linux Ubuntu系统中使用Docker部署DbGate数…...
【AI抠图整合包及教程】Meta SAM 2:视觉分割的革命性飞跃
在人工智能的浪潮中,每一次技术的革新都如同一场视觉盛宴,让我们见证着数字时代的变迁。Meta再次以Segment Anything Model 2(SAM 2)引领了图像和视频分割技术的新纪元。作为首个用于实时、可提示的图像和视频对象分割的统一模型&…...
使用语言模型进行文本摘要的五个级别(llm)
视频链接:5 Levels Of LLM Summarizing: Novice to Expert...
ubuntu交叉编译libffi库给arm平台使用
1.下载并解压: 2.生成makefile 编译: make 编译成功: 安装: make install 安装成功 查看安装后的libffi库...
【jvm】空间分配担保策略
目录 1. 说明2. 工作原理2.1 估算新生代存活对象大小2.2 判断老年代的剩余空间2.3 触发Full GC的条件 3. 相关参数与配置3.1 -XX:HandlePromotionFailure3.2 -XX:PretenureSizeThreshold3.3 -XX:MaxTenuringThreshold3.4 -XX:TargetSurvivorRatio 4.作用与意义 1. 说明 1.在Ja…...
iQOO手机怎样将屏幕投射到MacBook?可以同步音频吗?
众所周知,苹果品牌的设备自己有AirPlay的投屏功能,iPhone要投屏到MacBook只要连接同一网络,然后开启AirPlay就可以投屏。但其他品牌的手机没有AirPlay,怎么将手机屏幕投射到MacBook呢? 安卓系统的手机可以使用无线投屏…...
BUU usualCrypt1
查壳,32bit,丢进ida32中进行反编译,简单的不多说,直接进main分析 简单分析,打上注释,没啥好看的,就一个加密函数,加密完后和一个字符串进行比较,由此可以逆推出加密前的字…...
第十七章 标准库特殊设施
17.1 tuple类型 当希望将一些数据合成单一对象,但又不想麻烦地定义一个新数据结构来表示这些数据时,tuple非常有用。tuple是类似pair的模板。 tuple<size_t, size_t, size_t> threeD; //三个成员都设置为0//为每个成员提供初始值 tuple<strin…...
【格言分享】程序员的经典名言解读
上一期文章我们分享了一些程序员的经典名言,每一句都蕴含着深刻的道理。 接下来就给大家一个一个分析一下 这些格言确实捕捉到了编程和软件开发的精髓,每一条都蕴含着丰富的经验和智慧。下面我将逐一解释这些格言,并分享一些我的看法。 C程序员永远不会灭亡。他们只是cast…...
SpringBoot接收LocalDateTime参数
一、通过RequestBody接收 方式1:实体类上加上 JsonFormat,并通过 pattern 属性指定时间格式 public class Time {JsonFormat(pattern "yyyy-MM-dd HH:mm:ss")LocalDateTime localDateTime;JsonFormat(pattern "yyyy-MM-dd")Loca…...
Typora配置GitHub图床--结合PicGo
【当前问题】Typora文档分享时 无法看到本地路径图片 【怎么解决】把文档中的图片设置为 公开链接 【准备工具】 Typora 官网https://typoraio.cn/(购买 / 自寻破解法)GitHub账号 https://github.com/PicGo https://github.com/Molunerfinn/PicGo/relea…...
【书生.浦语实战营】——入门岛
【书生.浦语实战营】——入门岛_第一关_Linux基础 任务分布1. 本地vscode远程连接并进行端口映射端口映射What——何为端口映射How——怎么进行端口映射 2. Linux基础命令touch :创建文件mkdir :创建目录cd:进入 退出 目录pwd :确定当前所在目录cat:可以…...
WPF+MVVM案例实战(十四)- 封装一个自定义消息弹窗控件(下)
文章目录 1、案例效果2、弹窗控件使用1.引入用户控件2、按钮命令实现 3、总结4、源代码获取 1、案例效果 2、弹窗控件使用 1.引入用户控件 打开 Wpf_Examples 项目,在引用中添加用户控件库,在 MainWindow.xaml 界面引用控件库,代码如下&…...
嵌入式——STM32外设应用
STM32 微控制器以其高性能、低功耗和丰富的外设资源,在嵌入式系统设计中得到了广泛应用。以下将详细介绍 STM32 的主要外设及其典型应用,帮助开发者更好地理解和应用这些功能。 1. GPIO(通用输入输出端口) 功能:GPIO…...
HCIA(ACL)
第七节 ACL:访问控制列表 访问控制----在路由器的入或者出的接口上,匹配流量,之后产生动作---允许或拒绝 定义感兴趣流量-----帮助其他软件抓流量 匹配规则: 至上而下,逐一匹配,上调匹配按照上条执行…...
react基础之reactHooks
文章目录 React Hooks 使用指南常用 Hooks使用规则 小结 React Hooks 使用指南 React Hooks 是 React 16.8 引入的一种新特性,允许在函数组件中使用状态和其他 React 特性,而无需编写类组件。以下是一些基础的 Hooks 及其使用规则。 常用 Hooks useSta…...
eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)
说明: 想象一下,你正在用eNSP搭建一个虚拟的网络世界,里面有虚拟的路由器、交换机、电脑(PC)等等。这些设备都在你的电脑里面“运行”,它们之间可以互相通信,就像一个封闭的小王国。 但是&#…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...
ubuntu搭建nfs服务centos挂载访问
在Ubuntu上设置NFS服务器 在Ubuntu上,你可以使用apt包管理器来安装NFS服务器。打开终端并运行: sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享,例如/shared: sudo mkdir /shared sud…...
java 实现excel文件转pdf | 无水印 | 无限制
文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...
【解密LSTM、GRU如何解决传统RNN梯度消失问题】
解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...
电脑插入多块移动硬盘后经常出现卡顿和蓝屏
当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时,可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案: 1. 检查电源供电问题 问题原因:多块移动硬盘同时运行可能导致USB接口供电不足&#x…...
oracle与MySQL数据库之间数据同步的技术要点
Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异,它们的数据同步要求既要保持数据的准确性和一致性,又要处理好性能问题。以下是一些主要的技术要点: 数据结构差异 数据类型差异ÿ…...
Java 加密常用的各种算法及其选择
在数字化时代,数据安全至关重要,Java 作为广泛应用的编程语言,提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景,有助于开发者在不同的业务需求中做出正确的选择。 一、对称加密算法…...
Ascend NPU上适配Step-Audio模型
1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统,支持多语言对话(如 中文,英文,日语),语音情感(如 开心,悲伤)&#x…...
【JavaSE】绘图与事件入门学习笔记
-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角,以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向,距离坐标原点x个像素;第二个是y坐标,表示当前位置为垂直方向,距离坐标原点y个像素。 坐标体系-像素 …...
