SDL基础使用07(YUV数据显示)

SDL显示YUV数据和文件

使用SDL播放随机yuv数据 

#include <stdio.h>
#include <Windows.h>extern "C"
{
#include <SDL.h>
}#pragma comment(lib, "SDL2.lib")/* 填充随机颜色 */
static void FillYuvImage(BYTE* pYuv, int nWidth, int nHeight, int nIndex)
{int x, y, i;i = nIndex;BYTE* pY = pYuv;								// 数组开始位置BYTE* pU = pYuv + nWidth * nHeight;				// 数组开始位置 + Y数据后的位置BYTE* pV = pYuv + nWidth * nHeight * 5 / 4;		// 数组开始位置 + YU数据后的位置/* Y */for (y = 0; y < nHeight; y++){for (x = 0; x < nWidth; x++){pY[y * nWidth + x] = x + y + i * 2;}}/* Cb and Cr */for (y = 0; y < nHeight / 2; y++){for (x = 0; x < nWidth / 2; x++){pU[y * (nWidth / 2) + x] = 64 + y + i * 2;pV[y * (nWidth / 2) + x] = 64 + x + i * 5;}}
}#undef main
int main()
{// 初始化SDLif (SDL_Init(SDL_INIT_VIDEO)){printf("Could not initialize SDL - %s\n", SDL_GetError());return -1;}// 提升图像质量,否则默认缩放质量会有毛剌(设置反锯齿)SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1");// 创建窗口(获取控制台窗口),基于窗口创建渲染器SDL_Window*   window = SDL_CreateWindowFrom(::GetConsoleWindow());SDL_Renderer* render = SDL_CreateRenderer(window, -1, 0);// 窗口宽高const int W = 1920;const int H = 1080;// 创建渲染器SDL_Texture*  texture = SDL_CreateTexture(render, SDL_PIXELFORMAT_YV12, SDL_TEXTUREACCESS_STREAMING, W, H);/// yuv 420P : planer   W * H * 1.5 (y: 1 uv: 0.5)static BYTE Yuv[W * H * 2];BYTE* pY = Yuv;BYTE* pU = Yuv + W * H;BYTE* pV = Yuv + W * H * 5 / 4;int index = 0;while (true){FillYuvImage(Yuv, W, H, index++);				// 填充随机颜色到YUV数组中// 更新纹理数据int e = SDL_UpdateYUVTexture(texture, NULL,pY, W,pU, W / 2,pV, W / 2);/// 刷新渲染器:三部曲: clear, copy, presentSDL_RenderClear(render);SDL_RenderCopy(render, texture, NULL, NULL);SDL_RenderPresent(render);Sleep(40);}// 释放资源,退出SDL_DestroyTexture(texture);SDL_DestroyRenderer(render);SDL_Quit();return 0;
}

 SDL播放YUV文件

#define  _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <stdlib.h>
#include <string.h>extern "C"
{
#include <SDL.h>
}
using namespace std;const int width = 640;	
const int height = 480;static SDL_Window *window = nullptr;
SDL_Renderer *ren = nullptr;#undef main
int main(int argc, char **argv)
{SDL_Event        event;SDL_bool         done = SDL_FALSE;Uint32           pixel_format = SDL_PIXELFORMAT_IYUV;	// yuv420pint frame_number = 0;// 如果去掉“b”,文本模式读取,遇到“\0”,就会自动退出FILE *fp = fopen("5s_yuv420p_640x480.yuv", "rb");		// 设置SDL日志优先级(日志分类,优先级)SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);// 1. 初始化SDLif (SDL_Init(SDL_INIT_VIDEO) != 0) {SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError());return 3;}// 2. 创建窗口SDL_Window *win = SDL_CreateWindow("Hello", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_SHOWN);if (win == nullptr){SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't set create window: %s\n", SDL_GetError());return 1;}// 3. 基于窗口创建渲染器ren = SDL_CreateRenderer(win, 0, 0); if (ren == nullptr){SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't set create renderer: %s\n", SDL_GetError());return 1;}// 4. 基于yuv格式创建纹理SDL_Texture *tex = SDL_CreateTexture(ren, pixel_format, SDL_TEXTUREACCESS_STREAMING, width, height);int len = height * width;Uint8* buf = (Uint8*)malloc(len *  2);				// 1.5倍w * h// SDL_BYTESPERPIXEL(pixel_format) 根据像素格式获取每个像素占用的字节数int iPitch = width * SDL_BYTESPERPIXEL(pixel_format);printf("IPath %d\n", iPitch);		// 640 一行像素数据字节数SDL_Rect rec;rec.x = 0;rec.y = 0;rec.w = width;rec.h = height;int nRets = 0;while (!done){while (SDL_PollEvent(&event)) {switch (event.type) {case SDL_KEYDOWN:if (event.key.keysym.sym == SDLK_ESCAPE) {done = SDL_TRUE;}break;case SDL_QUIT:done = SDL_TRUE;break;}}/// 注意:每次需要的字节数: width*height*1.5/// Y:  width * height Bytes/// cb: width * height / 4/// cr: width * height / 4nRets = fread(buf, 1, height * width * 3 / 2, fp);if (nRets < 0) {break;}// 用buf缓冲区数据 更新 纹理SDL_UpdateTexture(tex, NULL, buf, iPitch);/*	刷新渲染器:三部曲:clear, copy, present */SDL_RenderClear(ren);SDL_RenderCopy(ren, tex, NULL, &rec);SDL_RenderPresent(ren);frame_number++;/// 音视频同步实现原理: 休眠SDL_Delay(40);			// 1000 / 40 = 25fps(帧率:每秒25帧)}/// 退出:清理资源SDL_Delay(2000);SDL_DestroyTexture(tex);SDL_DestroyRenderer(ren);SDL_DestroyWindow(win);SDL_Quit();fclose(fp);return 0;
}

 SDL播放YUV文件(带缩放)

#include <stdio.h>
#include <string.h>
#include <math.h>extern "C"
{
#include <SDL.h>
}// 自定义事件
#define REFRESH_EVENT   (SDL_USEREVENT + 1)     // 请求画面刷新事件
#define QUIT_EVENT      (SDL_USEREVENT + 2)     // 退出事件// 定义YUV像素分辨率	    5s_yuv420p_640x480.yuv
#define YUV_WIDTH   640
#define YUV_HEIGHT  480// 定义YUV格式
#define YUV_FORMAT  SDL_PIXELFORMAT_IYUV        // 实际为YUV420Pint s_thread_exit = 0;              // 线程退出标志 1 退出// 线程函数
int refresh_video_timer(void *data)
{(void)data;while (!s_thread_exit){// 每隔40ms发送一次刷新事件SDL_Event event;event.type = REFRESH_EVENT;SDL_PushEvent(&event);SDL_Delay(40);}s_thread_exit = 0;// 发送退出事件SDL_Event event;event.type = QUIT_EVENT;SDL_PushEvent(&event);return 0;
}#undef main
int main()
{// 1. 初始化 SDLif (SDL_Init(SDL_INIT_VIDEO)){fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());return -1;}uint32_t pixformat = YUV_FORMAT;            // YUV420P,即是SDL_PIXELFORMAT_IYUV// YUV的分辨率640x480int video_width = YUV_WIDTH;int video_height = YUV_HEIGHT;// 显示窗口分辨率640x480int win_width = YUV_WIDTH;int win_height = YUV_WIDTH;FILE *video_fd = NULL;const char *yuv_path = "5s_yuv420p_640x480.yuv";// 我们测试的文件是YUV420P格式   640x480uint32_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;// 一帧YUV数据的长度uint32_t yuv_frame_len = y_frame_len + u_frame_len + v_frame_len;// 2. 创建窗口SDL_Window* window = SDL_CreateWindow("Simplest YUV Player",SDL_WINDOWPOS_UNDEFINED,SDL_WINDOWPOS_UNDEFINED,video_width, video_height,       // 320 240SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);if (!window){fprintf(stderr, "SDL: could not create window, err:%s\n", SDL_GetError());goto _FAIL;}// 2. 基于窗口创建渲染器SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, 0);// 3. 基于渲染器创建纹理SDL_Texture* texture = SDL_CreateTexture(renderer,pixformat,                      // 像素格式 yuv420pSDL_TEXTUREACCESS_STREAMING,    // 改变是否频繁video_width,video_height);// 分配一帧数据长度的空间uint8_t *video_buf = (uint8_t*)malloc(yuv_frame_len);if (!video_buf){fprintf(stderr, "Failed to alloce yuv frame space!\n");goto _FAIL;}// 4. 打开YUV文件(二进制方式打开)video_fd = fopen(yuv_path, "rb");if (!video_fd){fprintf(stderr, "Failed to open yuv file\n");goto _FAIL;}else{printf("open file success!\n");}// 创建刷新线程SDL_Thread* timer_thread = SDL_CreateThread(refresh_video_timer, NULL, NULL);SDL_Event event;SDL_Rect rect;size_t video_buff_len;						// 获取读取数据后buff的数据长度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;}// 设置纹理的数据 SDL_UpdateTexture(texture, NULL, video_buf, video_width);  // 参数四,一行像素数据字节数// 显示区域,可以通过修改w和h进行缩放rect.x = 0;rect.y = 0;float w_ratio = win_width  * 1.0 / video_width;           // 宽高缩放比例(倍数) 2 * 640 / 640 = 2float h_ratio = win_height * 1.0 / video_height;// 1280x960rect.w = video_width * w_ratio;rect.h = video_height * h_ratio;// 保持原视频的宽高比例(显示到窗口中间)// rect.x = fabs(video_width * w_ratio - video_width) / 2.0;// rect.y = fabs(video_height * h_ratio - video_height) / 2.0;// rect.w = video_width;// rect.h = video_height;// 渲染三部曲SDL_RenderClear(renderer);SDL_RenderCopy(renderer, texture, NULL, &rect);SDL_RenderPresent(renderer);}else if (event.type == SDL_WINDOWEVENT)	{// 如果窗口大小改变(会触发该事件获取到窗口的高度和宽度)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;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/722791.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Neo4j 新手教程 环境安装 基础增删改查 python链接 常用操作 纯新手向

Neo4j安装教程&#x1f680; 目前在学习知识图谱的相关内容&#xff0c;在图数据库中最有名的就是Neo4j,为了降低入门难度&#xff0c;不被网上很多华丽呼哨的Cypher命令吓退&#xff0c;故分享出该文档&#xff0c;为自己手动总结&#xff0c;包括安装环境&#xff0c;增删改查…

华为Web举例:私网用户通过三元组NAT访问Internet

Web举例&#xff1a;私网用户通过三元组NAT访问Internet 介绍私网用户通过三元组NAT访问Internet的配置举例。 组网需求 某公司在网络边界处部署了FW作为安全网关。为了使私网中10.1.1.0/24网段的用户可以正常访问Internet&#xff0c;需要在FW上配置源NAT策略。除了公网接口…

修改表中某个字段等于另一个字段减去 2 小时的 SQL

需求&#xff1a;将表中到达时间按照客户要求改为比赛时间的提前 N 小时&#xff0c;具体如下&#xff1a; 表结构 update contestSchedule SET mainRefereeArrivalTimeDATE_FORMAT(CONCAT(2024-03-04 ,gameTime)- INTERVAL 2 HOUR, %H:%i), assistantRefereeArrivalTimeDAT…

【Unity】UnityWebRequest time out 0 bytes received问题

关键词&#xff1a;UnityWebRequest、Http协议、Get请求、0 bytes received using Newtonsoft.Json; using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Networking;public class MyWebRequest : MonoBehavi…

2024关于idea激活码报This license xxxx has been suspended

HOSTS文件中增加 0.0.0.0 www.jetbrains.com 0.0.0.0 account.jetbrains.com 然后

代码随想录 二叉树第五周

目录 235.二叉搜索树的最近公共祖先 701.二叉搜索树的插入操作 450.删除二叉搜索树中的节点 669.修建二叉搜索树 108.将有序数组转换为二叉搜索树 538.把二叉搜索树转换为累加树 235.二叉搜索树的最近公共祖先 235. 二叉搜索树的最近公共祖先 中等 给定一个二叉搜索树,…

浅谈MySQL 索引

MySQL 索引类型 1&#xff1a;主键索引 索引列中的值必须是唯一的&#xff0c;不允许有空值。 2&#xff1a;普通索引 MySQL中基本索引类型&#xff0c;没有什么限制&#xff0c;允许在定义索引的列中插入重复值和空值。 3&#xff1a;唯一索引 索引列中的值必须是唯一的&…

App前端开发跨平台框架比较:React Native、Flutter、Xamarin等

引言 移动应用开发领域的跨平台框架正在不断演进&#xff0c;为开发者提供更多选择。在本文中&#xff0c;我们将比较几个流行的跨平台框架&#xff1a;React Native、Flutter和Xamarin等。讨论它们的优缺点、适用场景以及开发体验。 第一部分 React Native: 优缺点、适用场景…

Spring MVC BeanNameUrlHandlerMapping原理解析

在Spring MVC框架中&#xff0c;路由机制是实现请求到处理器映射的核心。其中&#xff0c;BeanNameUrlHandlerMapping是Spring MVC提供的一种基于bean名称的URL映射策略。本文将详细解析BeanNameUrlHandlerMapping的工作原理、特点、使用场景以及配置和使用方法。 一、BeanNam…

uniapp实现单选框卡片选择器,支持微信小程序、H5等多端

采用uniapp-vue3实现的一款单选框卡片选择器&#xff0c;纯CSS实现样式和交互&#xff0c;提供丝滑的动画选中效果&#xff0c;支持不同主题配置&#xff0c;适配多端 可到插件市场下载尝试&#xff1a; https://ext.dcloud.net.cn/plugin?id16901 使用示例 示例代码 <te…

Linux操作系统项目上传Github代码仓库指南

文章目录 1 创建SSH key2.本地git的用户名和邮箱设置3.测试连接4.创建仓库5.终端项目上传 1 创建SSH key 1.登录github官网,点击个人头像,点击Settings,然后点击SSH and GPG keys,再点击New SSH key。 Title 可以随便取&#xff0c;但是 key 需要通过终端生成。 Linux终端执行…

运用Tensorflow进行目标检测

对象检测是一种计算机视觉技术&#xff0c;它使软件系统能够从给定的图像或视频中检测、定位并跟踪物体。对象检测的一个特殊属性是它能识别对象的类别&#xff08;如人、桌子、椅子等&#xff09;并在给定图像中指出其具体位置坐标。这个位置通常通过在物体周围绘制一个边界框…

探究java反射取值与方法取值性能对比

探究java反射取值与方法取值性能对比 由于我开发框架时&#xff0c;经常需要对象取值。常用的取值方式有&#xff1a; 反射取值方法调用取值 环境 同一台电脑&#xff1a; jdk 21.0.2 idea 2023.3.3 1. 测试代码&#xff08;常用&#xff09; 1.1 反射取值 public stat…

u-boot增加自定义命令

0、说明 本文基于U-Boot 2022.01-v2.07版本进行分析。 1、u-boot编译流程简要分析 2、u-boot启动流程简要分析 3、u-boot增加自定义命令 3.1、u-boot命令行实现简要分析 1&#xff09;cli_init命令行初始化 cli_init定义在common\cli.c中&#xff1a;void cli_init(void) {…

C++基础入门 --- 练习案例【1-10】

文章目录 C基础入门 --- 练习案例1.三只小猪称体重2.猜数字3.水仙花数4.敲桌子5.乘法口诀表6.五只小猪称体重7.数组元素逆置8.考试成绩统计9.冒泡排序10.结构体数组排序 C基础入门 — 练习案例 1.三只小猪称体重 说明&#xff1a;有三只小猪分别为A、B、C,分别输入三只小猪的…

【Web】浅浅地聊JDBC java.sql.Driver的SPI后门

目录 SPI定义 SPI核心方法和类 最简单的SPIdemo演示 回顾JCBC基本流程 为什么JDBC要有SPI JDBC java.sql.Driver后门利用与验证 SPI定义 SPI&#xff1a; Service Provider Interface 官方定义&#xff1a; 直译过来是服务提供者接口&#xff0c;学名为服务发现机制 它通…

acme.sh申请ssl免费证书

参考 https://blog.csdn.net/fyhju1/article/details/120452141 获取域名服务商AccessKey ID及AccessKey Secret https://help.aliyun.com/zh/ram/user-guide/create-an-accesskey-pair 安装ACME curl https://get.acme.sh | sh source ~/.bashrc如果使用root用户进行安装&…

如何在windows上像linux的ssh一样远程访问其它windows

主要分成两部分&#xff1a; 1. 如何远程执行指令 使用psexec&#xff0c;示例如下&#xff1a; PsExec64.exe \\远程计算机ip -u 用户名 -p 密码 -i cmd.exe 这样你就能连接到远程计算机上执行命令了&#xff0c;效果如下 2. 如何远程拷贝文件 分成两步&#xff1a; net…

【语法基础练习】1.变量、输入输出、表达式与顺序语句

&#x1f338;博主主页&#xff1a;釉色清风&#x1f338;文章专栏&#xff1a;算法练习&#x1f338;今日语录&#xff1a;You don’t know until you try. 文章简介&#xff1a;下面的题目是AcWing网站语法基础练习篇的第一小节&#xff0c;内容基础&#xff0c;难度&#xf…

计算机组成原理-累加器实验——沐雨先生

一、实验目的 1.理解累加器的概念和作用 2.连接运算器、存储器和累加器&#xff0c;熟悉计算机的数据通路 3.掌握使用微命令执行各种操作的方法。 二、实验要求 1.做好实验预习&#xff0c;读懂实验电路图&#xff0c;熟悉实验元器件的功能特性和使用方法。在实验之前设计…