当前位置: 首页 > news >正文

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举例 适配器模式 适配器模式&#xff08;Adapter Pattern&#xff09;是一种结构型设计模式&#xff0c;它允许接口不兼容的类一起工作。 其核心思想是通过一个适配器类将不兼容的接口转换成客户端期望的另一个接口&…...

多传感器数字化分析系统

在工业飞速发展的今天&#xff0c;设备的安全稳定运行成为企业高效生产的关键因素。然而&#xff0c;传统的人工巡检方式面临着诸多挑战&#xff0c;如效率低下、漏检误检以及难以精准掌握设备运行状态等。旗晟凭借深厚的技术积累和创新精神&#xff0c;推出了多传感器数字化分…...

Java 基础教学:面向对象编程基础-封装、继承与多态

面向对象编程&#xff08;OOP&#xff09;是现代编程的重要范式&#xff0c;Java 语言提供了丰富的 OOP 特性&#xff0c;主要包括封装、继承和多态。本文将详细讲解这三个概念及其实现方式&#xff0c;并提供相应的代码示例。 1. 封装 1.1 概念 封装是将对象的状态&#xf…...

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:视觉分割的革命性飞跃

在人工智能的浪潮中&#xff0c;每一次技术的革新都如同一场视觉盛宴&#xff0c;让我们见证着数字时代的变迁。Meta再次以Segment Anything Model 2&#xff08;SAM 2&#xff09;引领了图像和视频分割技术的新纪元。作为首个用于实时、可提示的图像和视频对象分割的统一模型&…...

使用语言模型进行文本摘要的五个级别(llm)

视频链接&#xff1a;5 Levels Of LLM Summarizing: Novice to Expert...

ubuntu交叉编译libffi库给arm平台使用

1.下载并解压&#xff1a; 2.生成makefile 编译&#xff1a; make 编译成功&#xff1a; 安装&#xff1a; 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?可以同步音频吗?

众所周知&#xff0c;苹果品牌的设备自己有AirPlay的投屏功能&#xff0c;iPhone要投屏到MacBook只要连接同一网络&#xff0c;然后开启AirPlay就可以投屏。但其他品牌的手机没有AirPlay&#xff0c;怎么将手机屏幕投射到MacBook呢&#xff1f; 安卓系统的手机可以使用无线投屏…...

BUU usualCrypt1

查壳&#xff0c;32bit&#xff0c;丢进ida32中进行反编译&#xff0c;简单的不多说&#xff0c;直接进main分析 简单分析&#xff0c;打上注释&#xff0c;没啥好看的&#xff0c;就一个加密函数&#xff0c;加密完后和一个字符串进行比较&#xff0c;由此可以逆推出加密前的字…...

第十七章 标准库特殊设施

17.1 tuple类型 当希望将一些数据合成单一对象&#xff0c;但又不想麻烦地定义一个新数据结构来表示这些数据时&#xff0c;tuple非常有用。tuple是类似pair的模板。 tuple<size_t, size_t, size_t> threeD; //三个成员都设置为0//为每个成员提供初始值 tuple<strin…...

【格言分享】程序员的经典名言解读

上一期文章我们分享了一些程序员的经典名言,每一句都蕴含着深刻的道理。 接下来就给大家一个一个分析一下 这些格言确实捕捉到了编程和软件开发的精髓,每一条都蕴含着丰富的经验和智慧。下面我将逐一解释这些格言,并分享一些我的看法。 C程序员永远不会灭亡。他们只是cast…...

SpringBoot接收LocalDateTime参数

一、通过RequestBody接收 方式1&#xff1a;实体类上加上 JsonFormat&#xff0c;并通过 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/&#xff08;购买 / 自寻破解法&#xff09;GitHub账号 https://github.com/PicGo https://github.com/Molunerfinn/PicGo/relea…...

【书生.浦语实战营】——入门岛

【书生.浦语实战营】——入门岛_第一关_Linux基础 任务分布1. 本地vscode远程连接并进行端口映射端口映射What——何为端口映射How——怎么进行端口映射 2. Linux基础命令touch &#xff1a;创建文件mkdir &#xff1a;创建目录cd:进入 退出 目录pwd :确定当前所在目录cat:可以…...

WPF+MVVM案例实战(十四)- 封装一个自定义消息弹窗控件(下)

文章目录 1、案例效果2、弹窗控件使用1.引入用户控件2、按钮命令实现 3、总结4、源代码获取 1、案例效果 2、弹窗控件使用 1.引入用户控件 打开 Wpf_Examples 项目&#xff0c;在引用中添加用户控件库&#xff0c;在 MainWindow.xaml 界面引用控件库&#xff0c;代码如下&…...

嵌入式——STM32外设应用

STM32 微控制器以其高性能、低功耗和丰富的外设资源&#xff0c;在嵌入式系统设计中得到了广泛应用。以下将详细介绍 STM32 的主要外设及其典型应用&#xff0c;帮助开发者更好地理解和应用这些功能。 1. GPIO&#xff08;通用输入输出端口&#xff09; 功能&#xff1a;GPIO…...

HCIA(ACL)

第七节 ACL&#xff1a;访问控制列表 访问控制----在路由器的入或者出的接口上&#xff0c;匹配流量&#xff0c;之后产生动作---允许或拒绝 定义感兴趣流量-----帮助其他软件抓流量 匹配规则&#xff1a; 至上而下&#xff0c;逐一匹配&#xff0c;上调匹配按照上条执行…...

react基础之reactHooks

文章目录 React Hooks 使用指南常用 Hooks使用规则 小结 React Hooks 使用指南 React Hooks 是 React 16.8 引入的一种新特性&#xff0c;允许在函数组件中使用状态和其他 React 特性&#xff0c;而无需编写类组件。以下是一些基础的 Hooks 及其使用规则。 常用 Hooks useSta…...

Spring AI 入门:Java 开发者的生成式 AI 实践之路

一、Spring AI 简介 在人工智能技术快速迭代的今天&#xff0c;Spring AI 作为 Spring 生态系统的新生力量&#xff0c;正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务&#xff08;如 OpenAI、Anthropic&#xff09;的无缝对接&…...

(转)什么是DockerCompose?它有什么作用?

一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用&#xff0c;而无需手动一个个创建和运行容器。 Compose文件是一个文本文件&#xff0c;通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...

GO协程(Goroutine)问题总结

在使用Go语言来编写代码时&#xff0c;遇到的一些问题总结一下 [参考文档]&#xff1a;https://www.topgoer.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/goroutine.html 1. main()函数默认的Goroutine 场景再现&#xff1a; 今天在看到这个教程的时候&#xff0c;在自己的电…...

mac:大模型系列测试

0 MAC 前几天经过学生优惠以及国补17K入手了mac studio,然后这两天亲自测试其模型行运用能力如何&#xff0c;是否支持微调、推理速度等能力。下面进入正文。 1 mac 与 unsloth 按照下面的进行安装以及测试&#xff0c;是可以跑通文章里面的代码。训练速度也是很快的。 注意…...

数据结构:递归的种类(Types of Recursion)

目录 尾递归&#xff08;Tail Recursion&#xff09; 什么是 Loop&#xff08;循环&#xff09;&#xff1f; 复杂度分析 头递归&#xff08;Head Recursion&#xff09; 树形递归&#xff08;Tree Recursion&#xff09; 线性递归&#xff08;Linear Recursion&#xff09;…...

CSS3相关知识点

CSS3相关知识点 CSS3私有前缀私有前缀私有前缀存在的意义常见浏览器的私有前缀 CSS3基本语法CSS3 新增长度单位CSS3 新增颜色设置方式CSS3 新增选择器CSS3 新增盒模型相关属性box-sizing 怪异盒模型resize调整盒子大小box-shadow 盒子阴影opacity 不透明度 CSS3 新增背景属性ba…...

智警杯备赛--excel模块

数据透视与图表制作 创建步骤 创建 1.在Excel的插入或者数据标签页下找到数据透视表的按钮 2.将数据放进“请选择单元格区域“中&#xff0c;点击确定 这是最终结果&#xff0c;但是由于环境启不了&#xff0c;这里用的是自己的excel&#xff0c;真实的环境中的excel根据实训…...

循环神经网络(RNN):从理论到翻译

循环神经网络&#xff08;RNN&#xff09;是一种专为处理序列数据设计的神经网络&#xff0c;如时间序列、自然语言或语音。与传统的全连接神经网络不同&#xff0c;RNN具有"记忆"功能&#xff0c;通过循环传递信息&#xff0c;使其特别适合需要考虑上下文或顺序的任…...

跑通 TrackNet-Badminton-Tracking-tensorflow2 项目全记录

&#x1f4dd; 跑通 TrackNet-Badminton-Tracking-tensorflow2 项目全记录 git clone https://github.com/Chang-Chia-Chi/TrackNet-Badminton-Tracking-tensorflow2.git TrackNet-Badminton-Tracking-tensorflow2 conda create --prefix /cloud/TrackNet-Badminton-Tracking-…...

深度学习学习率优化方法——pytorch中各类warm up策略

warm-up具体原理以及为什么这么做在之前的博客有介绍&#xff0c;这里直接介绍如何直接使用pytorch中的warm-up策略&#xff0c;在pytorch中对于warm-up所有支持的方法都有描述&#xff0c;可以直接阅读1。 深度学习中各类学习率优化方法(AdaGrad/RMSprop/Adam/Warm-UP)原理及其…...