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

SDL打开YUV视频

文章目录

      • 问题1:如何控制帧率?
      • 问题2:如何触发退出事件?
      • 问题3:如何实时调整视频窗口的大小
      • 问题4:YUV如何一次读取一帧的数据?

问题1:如何控制帧率?

在这里插入图片描述
单独用一个子线程给主线程发送刷新画面的事件 主线程负责刷新画面 每次发送刷新画面的命令后就延迟一段事件 具体的帧率公式为1000 / 延迟事件 = 帧率

问题2:如何触发退出事件?

SDL_QUIT 事件通常由用户触发,当关闭窗口时,SDL 会生成此事件。这可以通过用户点击窗口的关闭按钮(如窗口右上角的 “X”)或通过其他机制关闭窗口(例如按 Alt+F4)来触发。在事件循环中检测到 SDL_QUIT 后,通常会执行相应的退出操作,如设置退出标志(s_thread_exit = 1),从而安全地终止程序或线程。
在这里插入图片描述

问题3:如何实时调整视频窗口的大小

在这里插入图片描述
接受窗口变化的消息 实时更新窗口的尺寸 根据窗口和视频部分的比例
让实时渲染的时候 视频部分乘上这部分比例 就能到达 视频和窗口同步大小

问题4:YUV如何一次读取一帧的数据?

在 YUV420 格式中,一帧的数据大小可以通过以下方式计算:

Y 分量占据整个画面的大小:video_width * video_height
U 和 V 分量各占 Y 分量的四分之一:(video_width * video_height) / 4
因此,一帧的总大小为:
y_frame_len + u_frame_len + v_frame_len = video_width * video_height + 2 * (video_width * video_height / 4)

简化为:
yuv_frame_len = video_width * video_height * 1.5

这样你就可以通过 yuv_frame_len 获取一帧的总大小。

#include <stdio.h>
#include <string.h>#include <SDL.h>// 自定义消息类型
#define REFRESH_EVENT (SDL_USEREVENT + 1) // 请求画面刷新事件
#define QUIT_EVENT (SDL_USEREVENT + 2) // 退出事件// 定义分辨率
//  YUV像素分辨率
#define YUV_WIDTH 320
#define YUV_HEIGHT 240
// 定义YUV格式
#define YUV_FORMAT SDL_PIXELFORMAT_IYUVint s_thread_exit = 0; // 退出标志 = 1则退出// 通过线程去控制1s刷多少帧
int refresh_video_timer(void *data) {while (!s_thread_exit) {SDL_Event event;// 事件类型为刷新事件event.type = REFRESH_EVENT;// 将事件推送到事件队列中SDL_PushEvent(&event);SDL_Delay(40); // 1000 / 40 = 25 帧}// 停止控制视频输出帧数的时候 将这里的状态重置s_thread_exit = 0;// push quit eventSDL_Event event;event.type = QUIT_EVENT;SDL_PushEvent(&event);return 0;
}
#undef main
int main(int argc, char *argv[]) {// 初始化 SDLif (SDL_Init(SDL_INIT_VIDEO)) {fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());return -1;}// SDLSDL_Event event; // 事件SDL_Rect rect; // 矩形SDL_Window *window = NULL; // 窗口SDL_Renderer *renderer = NULL; // 渲染SDL_Texture *texture = NULL; // 纹理SDL_Thread *timer_thread = NULL; // 请求刷新线程uint32_t pixformat = YUV_FORMAT; // YUV420P,即是SDL_PIXELFORMAT_IYUV// 分辨率// 1. YUV的分辨率int video_width = YUV_WIDTH;int video_height = YUV_HEIGHT;// 2.显示窗口的分辨率int win_width = YUV_WIDTH;int win_height = YUV_WIDTH;// YUV文件句柄FILE *video_fd = NULL;const char *yuv_path = "yuv420p_320x240.yuv";size_t video_buff_len = 0;uint8_t *video_buf = NULL; // 读取数据后先把放到buffer里面// 我们测试的文件是YUV420P格式uint32_t y_frame_len = video_width * video_height;uint32_t u_frame_len = video_width * video_height / 4;uint32_t v_frame_len = video_width * video_height / 4;uint32_t yuv_frame_len = y_frame_len + u_frame_len + v_frame_len;// 创建窗口window = SDL_CreateWindow("Simplest YUV Player",SDL_WINDOWPOS_UNDEFINED,SDL_WINDOWPOS_UNDEFINED,video_width, video_height,SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);if (!window) {fprintf(stderr, "SDL: could not create window, err:%s\n", SDL_GetError());goto _FAIL;}// 基于窗口创建渲染器renderer = SDL_CreateRenderer(window, -1, 0);// 基于渲染器创建纹理texture = SDL_CreateTexture(renderer,pixformat, // 指定yuv格式SDL_TEXTUREACCESS_STREAMING,video_width,video_height);// 分配空间video_buf = ( uint8_t * )malloc(yuv_frame_len);if (!video_buf) {fprintf(stderr, "Failed to alloce yuv frame space!\n");goto _FAIL;}// 打开YUV文件video_fd = fopen(yuv_path, "rb");if (!video_fd) {fprintf(stderr, "Failed to open yuv file\n");goto _FAIL;}// 创建请求刷新线程timer_thread = SDL_CreateThread(refresh_video_timer,NULL,NULL);while (1) {// 收取SDL系统里面的事件SDL_WaitEvent(&event);if (event.type == REFRESH_EVENT) // 画面刷新事件{video_buff_len = fread(video_buf, 1, yuv_frame_len, video_fd);if (video_buff_len <= 0) {fprintf(stderr, "Failed to read data from yuv file!\n");goto _FAIL;}// 设置纹理的数据 video_width = 320, planeSDL_UpdateTexture(texture, NULL, video_buf, video_width);// 显示区域,可以通过修改w和h进行缩放rect.x = 0;rect.y = 0;float w_ratio = win_width * 1.0 / video_width;float h_ratio = win_height * 1.0 / video_height;// 320x240 怎么保持原视频的宽高比例rect.w = video_width * w_ratio;rect.h = video_height * h_ratio;//            rect.w = video_width * 0.5;//            rect.h = video_height * 0.5;// 清除当前显示SDL_RenderClear(renderer);// 将纹理的数据拷贝给渲染器 会把比例还原回来设置一个视频SDL_RenderCopy(renderer, texture, NULL, &rect);// 显示SDL_RenderPresent(renderer);} else if (event.type == SDL_WINDOWEVENT) {// If Resize 更新窗口的尺寸SDL_GetWindowSize(window, &win_width, &win_height);printf("SDL_WINDOWEVENT win_width:%d, win_height:%d\n", win_width,win_height);} else if (event.type == SDL_QUIT) // 退出事件{s_thread_exit = 1;} else if (event.type == QUIT_EVENT) {break;}}_FAIL:s_thread_exit = 1; // 保证线程能够退出// 释放资源if (timer_thread)SDL_WaitThread(timer_thread, NULL); // 等待线程退出if (video_buf)free(video_buf);if (video_fd)fclose(video_fd);if (texture)SDL_DestroyTexture(texture);if (renderer)SDL_DestroyRenderer(renderer);if (window)SDL_DestroyWindow(window);SDL_Quit();return 0;
}

相关文章:

SDL打开YUV视频

文章目录 问题1&#xff1a;如何控制帧率&#xff1f;问题2&#xff1a;如何触发退出事件&#xff1f;问题3&#xff1a;如何实时调整视频窗口的大小问题4&#xff1a;YUV如何一次读取一帧的数据&#xff1f; 问题1&#xff1a;如何控制帧率&#xff1f; 单独用一个子线程给主线…...

微服务架构面试内容整理-Archaius

Archaius 是由 Netflix 开发的一个配置管理库,主要用于处理动态配置和环境配置。在微服务架构中,Archaius 允许开发者以灵活的方式管理配置,从而更好地应对变化的需求。以下是 Archaius 的主要特点、工作原理和使用场景: 主要特点 1. 动态配置: Archaius 支持动态更新配置…...

实现 Nuxt3 预览PDF文件

安装必要的库&#xff0c;这里使用PDF.js库 npm install pdfjs-dist --save 为了解决跨域问题&#xff0c;在server/api 下 创建一个请求api&#xff0c; downloadFileByProxy.ts import { defineEventHandler } from h3;export default defineEventHandler(async event >…...

udp为什么会比tcp 有更低的延迟

UDP&#xff08;User Datagram Protocol&#xff0c;用户数据报协议&#xff09;相比TCP&#xff08;Transmission Control Protocol&#xff0c;传输控制协议&#xff09;具有更低的延迟&#xff0c;这主要归因于UDP协议的设计特点和机制。以下是对UDP比TCP延迟低的原因的详细…...

基于java+SpringBoot+Vue的洗衣店订单管理系统设计与实现

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; Springboot mybatis Maven mysql5.7或8.0等等组成&#x…...

HarmonyOS-消息推送

一. 服务简述 Push Kit&#xff08;推送服务&#xff09;是华为提供的消息推送平台&#xff0c;建立了从云端到终端的消息推送通道。所有HarmonyOS 应用可通过集成 Push Kit&#xff0c;实现向应用实时推送消息&#xff0c;使消息易见&#xff0c;构筑良好的用户关系&#xff0…...

数据分析:宏基因组DESeq2差异分析筛选差异物种

禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍原理:计算步骤:结果:加载R包准备画图主题数据链接导入数据Differential abundance (No BP vs 2BP TA)构建`countData`矩阵过滤低丰度物种构建DESeq数据对象DESeq2差异分析画图Di…...

出海企业如何借助云计算平台实现多区域部署?

云计算de小白 如需进一步了解&#xff0c;请单击链接了解有关 Akamai 云计算的更多信息 在本文中我们将告诉大家如何在Linode云计算平台上借助VLAN快速实现多地域部署。 首先我们需要明确一些基本概念和思想&#xff1a; 部署多区域 VLAN 为了在多区域部署中在不同的 VLAN …...

硬件---1电路设计安全要点以及欧姆定律

前言&#xff1a; 一直搞的东西都偏软件&#xff0c;硬件也一直在学&#xff0c;元器件、基础电路知识、PCB设计、模电运放都学的马马虎虎&#xff0c;因此决定进行系统性学习&#xff0c;内容基本来源于手里的视频和书本以及自己的感悟。 一电路安全 1电路安全 在初期基础…...

Linux如何更优质调节系统性能

一、硬件优化 增加物理内存&#xff1a;最直接的提升系统性能的方法。内存不足时&#xff0c;系统会频繁进行交换&#xff08;swapping&#xff09;活动&#xff0c;这会显著降低系统的响应速度&#xff0c;因为磁盘IO速度远低于内存访问速度。通过增加内存&#xff0c;可以减…...

第三十五章 Vue路由进阶之声明式导航(跳转传参)

目录 一、引言 二、查询参数传参 2.1. 使用方式 2.2. 完整代码 2.2.1. main.js 2.2.2. App.vue 2.2.3. Search.vue 2.2.4. Home.vue 2.2.5. index.js 三、动态路由传参 3.1. 使用方式 3.2. 完整代码 3.2.1. main.js 3.2.2. App.vue 3.2.3. Search.vue 3.2.4. Hom…...

python爬虫自动库DrissionPage保存网页快照mhtml/pdf/全局截图/打印机另存pdf

目录 零一、保存网页快照的三种方法二、利用打印机保存pdf的方法 零 最近星球有人问如何使用页面打印功能&#xff0c;另存为pdf 一、保存网页快照的三种方法 解决方案已经放在星球内&#xff1a;https://articles.zsxq.com/id_55mr53xahr9a.html当然也可以看如下代码&…...

基于毫米波雷达和TinyML的车内检测、定位与分类

英文标题&#xff1a;In-Cabin Detection, Localization and Classification based on mmWave Radar with TinyML 作者信息&#xff1a; 王志飞&#xff0c;程一格&#xff0c;彭辉&#xff0c;周会强&#xff0c;王铮&#xff0c;刘宏全所属机构&#xff1a;Calterah Semico…...

小E的射击训练

问题描述 小E正在训练场进行射击练习&#xff0c;靶有10个环&#xff0c;靶心位于坐标(0, 0)。每个环对应不同的得分&#xff0c;靶心内&#xff08;半径为1&#xff09;得10分&#xff0c;依次向外的每个环分数减少1分。若射击点在某个半径为i的圆内&#xff0c;则得11-i分。…...

React的概念以及发展前景如何?

React是一个由Facebook开发的用于构建用户界面的的开源JavaScript库&#xff0c;它主要用于构建大型、动态的Web应用程序。React的主要特点是使用VirtualDOM&#xff08;虚拟DOM&#xff09;来优化性能&#xff0c;并使用声明式的编程方式来编写UI。 React的主要概念包括&#…...

PDF生成:全面解析,C# 如何使用iTextSharp库(或其他类似库)生成PDF文档,包括如何将位图图像嵌入PDF中。

一、概述 PDF&#xff08;Portable Document Format&#xff09;是一种广泛使用的文档格式&#xff0c;由Adobe公司在1993年推出。PDF的目标是能够在任何设备上呈现固定格式的文档&#xff0c;无论是在不同的操作系统、硬件设备&#xff0c;还是在打印时&#xff0c;都能保证文…...

如何选择最适合的消息队列?详解 Kafka、RocketMQ、RabbitMQ 的使用场景

引言 在日常开发中&#xff0c;消息队列已经成为业务场景中几乎不可或缺的一部分。无论是订单系统、日志收集、分布式事务&#xff0c;还是大数据实时流处理&#xff0c;消息队列都在支撑着这些关键环节。目前市面上常用的消息队列有三种(ActiveMQ 虽然在企业集成中仍有应用&a…...

gitlab项目如何修改主分支main为master,以及可能遇到的问题

如果你希望将 Git 仓库的主分支名称从 main 修改为 master&#xff1a; 1. 本地修改分支名称 首先&#xff0c;切换到 main 分支&#xff1a; git checkout main将 main 分支重命名为 master&#xff1a; git branch -m main master2. 更新远程仓库 将本地更改推送到远程仓库…...

RRF(Reciprocal Rank Fusion,倒数排序融合)

RRF(Reciprocal Rank Fusion,倒数排序融合) 摘要 倒数排序融合 RRF 是一种简单的方法&#xff0c;用于结合多个 IR(Information Retrieval) 系统的文档排名&#xff0c;始终比任何单独的系统产生更好的结果。 通过使用 RRF 来结合几个TREC实验的结果&#xff0c;并建立一个 …...

移动开发(七):.NET MAUI使用RESTAPI实现查询天气笔记

目录 一、接口准备 二、实体部分 三、页面部分 四、后台代码逻辑 五、总结 在移动开发过程中,第三方对接是非常常见的。今天给大家分享.NET MAUI如何使用REST API实现输入城市名称查询天气的示例,希望对大家学习.NET MAUI可以提供一些帮助! 一、接口准备 首先我们需要…...

云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?

大家好&#xff0c;欢迎来到《云原生核心技术》系列的第七篇&#xff01; 在上一篇&#xff0c;我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在&#xff0c;我们就像一个拥有了一块崭新数字土地的农场主&#xff0c;是时…...

Leetcode 3576. Transform Array to All Equal Elements

Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接&#xff1a;3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到&#xf…...

基于当前项目通过npm包形式暴露公共组件

1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹&#xff0c;并新增内容 3.创建package文件夹...

python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)

更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...

Matlab | matlab常用命令总结

常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...

使用 SymPy 进行向量和矩阵的高级操作

在科学计算和工程领域&#xff0c;向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能&#xff0c;能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作&#xff0c;并通过具体…...

九天毕昇深度学习平台 | 如何安装库?

pip install 库名 -i https://pypi.tuna.tsinghua.edu.cn/simple --user 举个例子&#xff1a; 报错 ModuleNotFoundError: No module named torch 那么我需要安装 torch pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple --user pip install 库名&#x…...

佰力博科技与您探讨热释电测量的几种方法

热释电的测量主要涉及热释电系数的测定&#xff0c;这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中&#xff0c;积分电荷法最为常用&#xff0c;其原理是通过测量在电容器上积累的热释电电荷&#xff0c;从而确定热释电系数…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

day36-多路IO复用

一、基本概念 &#xff08;服务器多客户端模型&#xff09; 定义&#xff1a;单线程或单进程同时监测若干个文件描述符是否可以执行IO操作的能力 作用&#xff1a;应用程序通常需要处理来自多条事件流中的事件&#xff0c;比如我现在用的电脑&#xff0c;需要同时处理键盘鼠标…...