当前位置: 首页 > 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…...

[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?

&#x1f9e0; 智能合约中的数据是如何在区块链中保持一致的&#xff1f; 为什么所有区块链节点都能得出相同结果&#xff1f;合约调用这么复杂&#xff0c;状态真能保持一致吗&#xff1f;本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里&#xf…...

Docker 离线安装指南

参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性&#xff0c;不同版本的Docker对内核版本有不同要求。例如&#xff0c;Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本&#xff0c;Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...

内存分配函数malloc kmalloc vmalloc

内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...

【Oracle APEX开发小技巧12】

有如下需求&#xff1a; 有一个问题反馈页面&#xff0c;要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据&#xff0c;方便管理员及时处理反馈。 我的方法&#xff1a;直接将逻辑写在SQL中&#xff0c;这样可以直接在页面展示 完整代码&#xff1a; SELECTSF.FE…...

Keil 中设置 STM32 Flash 和 RAM 地址详解

文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...

Qt Http Server模块功能及架构

Qt Http Server 是 Qt 6.0 中引入的一个新模块&#xff0c;它提供了一个轻量级的 HTTP 服务器实现&#xff0c;主要用于构建基于 HTTP 的应用程序和服务。 功能介绍&#xff1a; 主要功能 HTTP服务器功能&#xff1a; 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...

C++.OpenGL (10/64)基础光照(Basic Lighting)

基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...

[Java恶补day16] 238.除自身以外数组的乘积

给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O(n) 时间复杂度…...

Rapidio门铃消息FIFO溢出机制

关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系&#xff0c;以下是深入解析&#xff1a; 门铃FIFO溢出的本质 在RapidIO系统中&#xff0c;门铃消息FIFO是硬件控制器内部的缓冲区&#xff0c;用于临时存储接收到的门铃消息&#xff08;Doorbell Message&#xff09;。…...

HashMap中的put方法执行流程(流程图)

1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中&#xff0c;其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下&#xff1a; 初始判断与哈希计算&#xff1a; 首先&#xff0c;putVal 方法会检查当前的 table&#xff08;也就…...