SDL显示YUV视频

文章目录

      • 1. **宏定义和初始化**
      • 2. **全局变量**
      • 3. **`refresh_video_timer` 函数**
      • 4. **`WinMain` 函数**
      • 主要功能及工作流程:
      • 总结:


1. 宏定义和初始化

#define REFRESH_EVENT   (SDL_USEREVENT + 1)     // 请求画面刷新事件
#define QUIT_EVENT      (SDL_USEREVENT + 2)     // 退出事件
  • REFRESH_EVENTQUIT_EVENT 是自定义的事件类型,用来触发画面刷新和退出操作。

2. 全局变量

int s_thread_exit = 0;  // 退出标志
  • s_thread_exit 标志用于控制视频播放线程的退出。

3. refresh_video_timer 函数

int refresh_video_timer(void *data)
{while (!s_thread_exit){SDL_Event event;event.type = REFRESH_EVENT;SDL_PushEvent(&event); // 触发刷新事件SDL_Delay(40); // 约每40ms触发一次}s_thread_exit = 0;//push quit eventSDL_Event event;event.type = QUIT_EVENT;SDL_PushEvent(&event);return 0;
}
  • refresh_video_timer 函数是一个线程函数,每隔 40 毫秒触发一次 REFRESH_EVENT,用于请求刷新画面。线程会一直运行,直到 s_thread_exit 被设置为 1。
  • 当播放完毕后,触发 QUIT_EVENT 以结束程序。

4. WinMain 函数

int WinMain(int argc, char* argv[])
{// 初始化 SDLif (SDL_Init(SDL_INIT_VIDEO)){fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());return -1;}SDL_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; // YUV格式// 视频文件路径const char *yuv_path = "H:/SDL/SDL_test/yuv420p_320x240.yuv";FILE *video_fd = NULL;uint8_t *video_buf = NULL; // 存储视频数据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, SDL_TEXTUREACCESS_STREAMING, video_width, video_height);// 分配内存用于存储 YUV 数据video_buf = (uint8_t*)malloc(yuv_frame_len);if (!video_buf){fprintf(stderr, "Failed to allocate 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_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);// 设置显示区域的矩形(缩放保持比例)rect.x = 0;rect.y = 0;float w_ratio = win_width * 1.0 / video_width;float h_ratio = win_height * 1.0 / video_height;rect.w = video_width * w_ratio;rect.h = video_height * h_ratio;// 清除当前渲染内容并渲染新帧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;
}

主要功能及工作流程:

  1. SDL 初始化:

    • SDL_Init(SDL_INIT_VIDEO) 初始化 SDL 的视频模块。
    • 创建一个窗口 (SDL_CreateWindow)、一个渲染器 (SDL_CreateRenderer) 和一个纹理 (SDL_CreateTexture) 来渲染 YUV 数据。
  2. 读取 YUV 数据:

    • 打开 YUV 文件并读取 YUV 数据到缓冲区 video_buf
    • YUV 数据根据视频的分辨率和 YUV420P 格式计算出每一帧的长度。
  3. 视频帧渲染:

    • 每次读取一帧数据后,使用 SDL_UpdateTexture 将 YUV 数据更新到纹理。
    • 通过渲染器 SDL_Renderer 渲染纹理到窗口。
  4. 刷新和退出事件:

    • 创建了一个独立的线程定时触发 REFRESH_EVENT,控制视频的刷新频率。
    • 如果读取到文件结尾或退出事件,程序会退出。
  5. 窗口大小调整:

    • 在窗口大小变化时,程序会自动调整渲染区域的比例,保持视频的宽高比。
  6. 资源释放:

    • 在退出程序时,确保释放所有分配的资源,包括 SDL 相关的资源(窗口、渲染器、纹理)以及 YUV 数据缓冲区。

总结:

这个程序通过 SDL2 创建一个视频播放窗口,读取并显示 YUV 文件的每一帧视频数据。它通过一个单独的线程来周期性触发视频帧的刷新,保持视频播放的流畅。

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

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

相关文章

AnimateCC基础教学:随机抽取花名册,不能重复

一.核心代码: this.btnStartObj.addEventListener("click", switchBtn); this.btnOkObj.addEventListener("click", oKBtn); createjs.Ticker.addEventListener("tick", updateRandom); var _this this; var nameArr ["张三", &quo…

软考 系统架构设计师系列知识点 —— 设计模式之抽象工厂模式

本文内容参考&#xff1a; 软考 系统架构设计师系列知识点之设计模式&#xff08;2&#xff09;_系统架构设计师中考设计模式吗-CSDN博客 https://baike.baidu.com/item/%E6%8A%BD%E8%B1%A1%E5%B7%A5%E5%8E%82%E6%A8%A1%E5%BC%8F/2361182 特此致谢&#xff01; Abstract Fac…

P2040 打开所有的灯

题目背景 pmshz在玩一个益(ruo)智(zhi)的小游戏&#xff0c;目的是打开九盏灯所有的灯&#xff0c;这样的游戏难倒了pmshz。。。 题目描述 这个灯很奇(fan)怪(ren)&#xff0c;点一下就会将这个灯和其周围四盏灯的开关状态全部改变。现在你的任务就是就是告诉pmshz要全部打开…

汉得企业级 PaaS 平台 H-ZERO 1.12.0 发布!四大维度升级,构建企业数字化新底座

汉得企业级 PaaS 平台&#xff08;以下简称"H-ZERO"&#xff09;是一款基于微服务架构的企业级数字化 PaaS 平台&#xff0c;可支持企业各类系统搭建、产品研发&#xff0c;帮助企业快速构架技术中台。 H-ZERO于2025年3月底正式发布 V1.12.0 &#xff0c;此次发布聚…

ReplicaSet、Deployment功能是怎么实现的?

在Kubernetes中&#xff0c;ReplicaSet 和 Deployment 是用于管理 Pod 副本的关键对象。它们各自的功能和实现机制如下&#xff1a; 1. ReplicaSet 功能 管理 Pod 副本&#xff1a;确保指定数量的 Pod 副本一直在运行。如果有 Pod 副本崩溃或被删除&#xff0c;ReplicaSet 会…

物联网外设管理服务平台

1 开发目标 1.1 架构图 操作系统&#xff1a;基于Linux5.10.10源码和STM32MP157开发板&#xff0c;完成tf-a(FSBL)、u-boot(SSBL)、uImage、dtbs的裁剪&#xff1b; 驱动层&#xff1a;为每个外设配置DTS并且单独封装外设驱动模块。其中电压ADC测试&#xff0c;采用linux内核…

PyTorch教程:如何读写张量与模型参数

本文演示了PyTorch中张量&#xff08;Tensor&#xff09;和模型参数的保存与加载方法&#xff0c;并提供完整的代码示例及输出结果&#xff0c;帮助读者快速掌握数据持久化的核心操作。 1. 保存和加载单个张量 通过torch.save和torch.load可以直接保存和读取张量。 import to…

持续集成:GitLab CI/CD 与 Jenkins CI/CD 的全面剖析

一、引言 在当今快速迭代的软件开发领域,持续集成(Continuous Integration,CI)已成为保障软件质量、加速开发流程的关键实践。通过频繁地将代码集成到共享仓库,并自动进行构建和测试,持续集成能够尽早发现并解决代码冲突和缺陷。而 GitLab CI/CD 和 Jenkins CI/CD 作为两…

Python 序列构成的数组(序列的增量赋值)

序列的增量赋值 增量赋值运算符 和 * 的表现取决于它们的第一个操作对象。简单起 见&#xff0c;我们把讨论集中在增量加法&#xff08;&#xff09;上&#xff0c;但是这些概念对 * 和其他 增量运算符来说都是一样的。 背后的特殊方法是 iadd &#xff08;用于“就地加法”&…

GEO, TCGA 等将被禁用?!这40个公开数据库可能要小心使用了

GEO, TCGA 等将被禁用&#xff1f;&#xff01;这40个公开数据库可能要小心使用了 最近NIH公共数据库开始对中国禁用的消息闹得风风火火&#xff1a; 你认为研究者上传到 GEO 数据库上的数据会被禁用吗&#xff1f; 单选 会&#xff0c;毕竟占用存储资源 不会&#xff0c;不…

【如何自建MCP服务器?从协议原理到实践的全流程指南】

文章目录 如何自建MCP服务器&#xff1f;从协议原理到实践的全流程指南一、MCP协议是什么&#xff1f;核心架构 二、为什么要自建MCP服务器&#xff1f;1. 突破LLM的固有局限2. 实现个性化功能扩展3. 确保数据隐私安全 三、手把手搭建MCP服务器&#xff08;Python示例&#xff…

鸿蒙开发_ARKTS快速入门_语法说明_渲染控制---纯血鸿蒙HarmonyOS5.0工作笔记012

然后我们再来看渲染控制 首先看条件渲染,其实就是根据不同的状态,渲染不同的UI界面 比如下面这个暂停 开启播放的 可以看到就是通过if 这种条件语句 修改状态变量的值 然后我们再来看这个, 下面点击哪个,上面横线就让让他显示哪个 去看一下代码 可以看到,有两个状态变量opt…

【Java设计模式】第3章 软件设计七大原则

3-1 本章导航 学习开辟原则(基础原则)依赖倒置原则单一职责原则接口隔离原则迪米特法则(最少知道原则)里氏替换原则合成复用原则(组合复用原则)核心思想: 设计原则需结合实际场景平衡,避免过度设计。设计模式中可能部分遵循原则,需灵活取舍。3-2 开闭原则讲解 定义 软…

JVM即时编译(JIT)

JVM基础回顾 Java 作为一门高级程序语言&#xff0c;由于它自身的语言特性&#xff0c;它并非直接在硬件上运行&#xff0c;而是通过编译器(前端编译器)将 Java 程序转换成该虚拟机所能识别的指令序列&#xff0c;也就是字节码&#xff0c;然后运行在虚拟机之上的&#xff1b;…

刚体碰撞检测与响应(C++实现)

本文实现一个经典的物理算法&#xff1a;刚体碰撞检测与响应。这个算法用于检测两个刚体&#xff08;如矩形或圆形&#xff09;是否发生碰撞&#xff0c;并在碰撞时更新它们的速度和位置。我们将使用C来实现这个算法&#xff0c;并结合**边界框&#xff08;Bounding Box&#x…

常用的国内镜像源

常见的 pip 镜像源 阿里云镜像&#xff1a;https://mirrors.aliyun.com/pypi/simple/ 清华大学镜像&#xff1a;https://pypi.tuna.tsinghua.edu.cn/simple 中国科学技术大学镜像&#xff1a;https://pypi.mirrors.ustc.edu.cn/simple/ 豆瓣镜像&#xff1a;https://pypi.doub…

鸿蒙小案例-京东登录

效果 代码实现 Entry Component struct Index {build() {Column() {Row() {Image($r(app.media.jd_cancel)).width(20)Text(帮助).fontSize(16).fontColor(#666)}.width(100%).justifyContent(FlexAlign.SpaceBetween)Image($r(app.media.jd_logo)).height(250).width(250)// …

《 Scikit-learn与MySQL的深度协同:构建智能数据生态系统的架构哲学》

在机器学习工程实践中&#xff0c;数据存储与模型训练的割裂始终是制约算法效能的关键瓶颈。Scikit-learn作为经典机器学习库&#xff0c;其与MySQL的深度协同并非简单的数据管道连接&#xff0c;而是构建了一个具备自组织能力的智能数据生态系统。这种集成突破了传统ETL流程的…

华为AI-agent新作:使用自然语言生成工作流

论文标题 WorkTeam: Constructing Workflows from Natural Language with Multi-Agents 论文地址 https://arxiv.org/pdf/2503.22473 作者背景 华为&#xff0c;北京大学 动机 当下AI-agent产品百花齐放&#xff0c;尽管有ReAct、MCP等框架帮助大模型调用工具&#xff0…

关于软件bug描述

软件缺陷&#xff08;Defect&#xff09;&#xff0c;常常又被叫做Bug。 所谓软件缺陷&#xff0c;即为计算机软件或程序中存在的某种破坏正常运行能力的问题、错误&#xff0c;或者隐藏的功能缺陷。缺陷的存在会导致软件产品在某种程度上不能满足用户的需要。IEEE729-1983对缺…