当前位置: 首页 > 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;}


http://www.mrgr.cn/news/59864.html

相关文章:

  • 基于neo4j的旅游知识图谱维护与问答系统
  • el-table相关的功能实现
  • python pip更换(切换)国内镜像源
  • gin入门教程(7): 使用 Logrus + Lumberjack 创建日志中间件
  • Prompt Engineering (Prompt工程)
  • 【verilog】四位全加器
  • UE ---- 射击游戏
  • 【Linux网络】传输层协议UDP与TCP
  • Mochi 1:AI视频生成领域的创新与应用
  • 绝了,这款播放器让发烧友疯狂种草,堪称音乐神器
  • 从零入门扣子Bot开发
  • Map和Set(数据结构)
  • 网络学习/复习2套接字
  • Linux基础-基础命令和相关知识4
  • 实现mysql和es的数据同步以及es的集群
  • 刷c语言练习题13(牛客网)
  • 【数据结构与算法】《Java 算法宝典:探秘从排序到回溯的奇妙世界》
  • 银河麒麟V10系统下libopenblas.so.0和libllmlmf库的安装
  • QT 实现自定义动态选择指示器
  • GPU的使用寿命可能只有1~3年
  • SpringBoot整合API接口做快递智能识别
  • 蓝桥杯普及题
  • Python实现基于WebSocket的stomp协议调试助手工具
  • 软硬链接与动静态库的加载
  • 鹏哥C语言95---第17次作业:指针初阶+结构体
  • 最短路径问题的经典算法——Dijkstra[被证明具有普遍最优性(Universal Optimality)]