音视频-SDL的简单使用

使用SDL进行音视频的播放

SDL(Simple DirectMedia Layer)是一套开放源代码的跨平台多媒体开发库,使用C语言写成。SDL提供了数种控制图像、声音、输出入的函数,让开发者只要用相同或是相似的代码就可以开发出跨多个平台(Linux、Windows、Mac OS X等)的应用软件。目前SDL多用于开发游戏、模拟器、媒体播放器等多媒体应用领域。
SDL的下载地址: https://www.libsdl.org/
现在较为新的版本在main函数中需要添加#define SDL_MAIN_HANDLED定义, 初步代码如下:

#include <stdio.h>
#include <string.h>
#include <malloc.h>
#define SDL_MAIN_HANDLED
#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则退出int refresh_video_timer(void *data)
{while (!s_thread_exit){SDL_Event event;event.type = REFRESH_EVENT;SDL_PushEvent(&event);SDL_Delay(40);}s_thread_exit = 0;//push quit eventSDL_Event event;event.type = QUIT_EVENT;SDL_PushEvent(&event);return 0;
}int main()
{if (SDL_Init(SDL_INIT_VIDEO)) {fprintf(stderr, "Can't not initialize SDL, err: %s\n", SDL_GetError());}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;    // 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; // 420p是4个y对应一个uuint32_t v_frame_len = video_width * video_height / 4; // 420p是4个y对应一个vuint32_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) {printf("Can't 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);// 分配空间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_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;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;
}

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

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

相关文章

hnswlib报错ItemCannotBeInsertedIntoTheVectorSpaceException

异常信息 com.stepstone.search.hnswlib.jna.exception.ItemCannotBeInsertedIntoTheVectorSpaceExceptionat com.stepstone.search.hnswlib.jna.Index.checkResultCode(Index.java:247)at com.stepstone.search.hnswlib.jna.Index.addItem(Index.java:125)原因是初始化index环…

抖音SEO搜索排名优化培训教程课件

【干货资料持续更新&#xff0c;以防走丢】 抖音SEO搜索排名优化培训教程课件 部分资料预览 资料部分是网络整理&#xff0c;仅供学习参考。 抖音运营资料合集 &#xff08;完整资料包含以下内容&#xff09; 目录 抖音易爆单的商品特征 抖音作为一款短视频平台&#xff0c;…

【应用方案】基于MT7628 JN5169 和SUN724的4G-Zigbee智能网关方案

产品方案特性 - 4G-Zigbee智能网关扩展性强&#xff1b; - 百兆以太网接入&#xff1b; - 支持Zigbee 3.0智能家居产品和智能安防产品接入&#xff1b; - 实时检测烟感、气感&#xff0c;联动阀门控制器可自动关闭燃气阀门&#xff0c;并拨打报警电话&#xff0c;防止火灾&…

静态住宅代理与动态住宅代理的区别?如何选?

住宅代理ip分类两种类型&#xff1a;静态住宅代理和动态住宅代理&#xff0c;他们有什么区别又能用在什么场景呢&#xff1f;我们先从他们是如何运作开始。 一、什么是住宅代理ip isp住宅代理ip我们称为真人住宅代理&#xff0c;地址是从真人/家庭中出发&#xff0c;安全性更高…

游戏素材永不缺,免费在线AI工具Scenario功能齐全,简单易用

Scenario是一个在线的AI驱动的工具&#xff0c;主要用于游戏艺术创作。它提供了一套全面的功能&#xff0c;旨在帮助游戏开发者创建与其独特风格和艺术方向相符的独特、高质量的游戏艺术。Scenario的突出特点之一是它的微调能力&#xff0c;允许用户根据独特的风格和艺术方向训…

Qt单个字符判断

1.相关说明 字符的Unicode编码、单个字符的判断 2.界面绘制 3.相关主要代码 #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui;…

【AIGC入门一】Transformers 模型结构详解及代码解析

Transformers 开启了NLP一个新时代&#xff0c;注意力模块目前各类大模型的重要结构。作为刚入门LLM的新手&#xff0c;怎么能不感受一下这个“变形金刚的魅力”呢&#xff1f; 目录 Transformers ——Attention is all You Need 背景介绍 模型结构 位置编码 代码实现&…

Agent检索增强生成

检索增强生成(RAG)设计模式通常用于在特定数据域中开发大语言模型(LLM)应用。然而&#xff0c;RAG的过往的研究重点主要在于提高检索工具的效率&#xff0c;例如嵌入搜索、混合搜索和微调嵌入&#xff0c;而忽视了智能搜索。本文介绍了一种受人类研究方法启发的新方法&#xff…

for循环判断有几个偶数

num100 count0 for i in range(1,num):if i%20:print("为偶数")count1 print(f"1-100的范围内&#xff0c;有{count}个偶数") 运行结果如下&#xff1a;

代码随想录Day21 | 530.二叉搜索树的最小绝对差 501.二叉搜索树中的众数 236. 二叉树的最近公共祖先

代码随想录Day21 | 530.二叉搜索树的最小绝对差 501.二叉搜索树中的众数 236. 二叉树的最近公共祖先 二叉搜索树的最小绝对差二叉搜索树中的众数二叉树的最近公共祖先 二叉搜索树的最小绝对差 文档讲解&#xff1a;代码随想录 视频讲解&#xff1a; 二叉搜索树中&#xff0c;需…

Nginx Ingress轻松上手 | Kubernetes服务管理指南

1. 揭秘Nginx Ingress的魔力 Nginx Ingress是你Kubernetes集群中的得力助手&#xff0c;无需额外安装&#xff0c;已内置于K8s。作为基于Nginx的扩展&#xff0c;它担任负载均衡器和入口控制器的重要角色。 2. 为何选择Nginx Ingress&#xff1f; 2.1 服务曝露的便利 通过简…

Kaggle之旅1

Kaggle之旅1 文章目录 Kaggle之旅1前言一、目标&#xff1f;二、课程1 pandas1. 学和练2. 一些关键摘要 总结 前言 Kaggle是一个以数据科学竞赛为主题的在线平台。它提供了一个数据科学社区&#xff0c;让数据科学家和机器学习专家可以在这里交流、学习和竞争。Kaggle上有大量…

深度掌握 Nginx Ingress:解锁高级功能,打造 Kubernetes 中的流量掌控艺术

前言 在 Kubernetes 的世界里&#xff0c;Nginx Ingress 不仅是流量的门卫&#xff0c;更是一把强大的调控利器。我们已经领略了其基础面貌&#xff0c;现在让我们踏上深度之旅&#xff0c;揭示 Nginx Ingress 的高级功能&#xff0c;助你在 Kubernetes 中创造流量掌控的艺术。…

2024秋招,深信服测试开发工程师一面

前言 回顾一下我秋招参加的第一次线下面试 这个面试体现出了我的很多弱点&#xff0c;也为我后面的改进起着很重要的作用 时间&#xff1a;40min 平台&#xff1a;线下面试 过程 1、个人介绍 2、项目经历 3、团队项目中负责的模块&#xff0c;队友都负责哪些工作&#x…

使用免费敏捷工具Leangoo领歌管理Sprint Backlog

什么是Sprint Backlog&#xff1f; Sprint Backlog是Scrum的主要工件之一。在Scrum中&#xff0c;团队按照迭代的方式工作&#xff0c;每个迭代称为一个Sprint。在Sprint开始之前&#xff0c;PO会准备好产品Backlog&#xff0c;准备好的产品Backlog应该是经过梳理、估算和优先…

C语言编译链接

1.翻译环境和运⾏环境 在ANSI C的任何⼀种实现中&#xff0c;存在两个不同的环境。 第1种是翻译环境&#xff0c;在这个环境中源代码被转换为可执⾏的机器指令。 第2种是执⾏环境&#xff0c;它⽤于实际执⾏代码。 2. 翻译环境 翻译环境是由编译和链接两个⼤的过程组成的&…

Spring环境搭配

概述 Spring 是一个开源框架&#xff0c;Spring 是于2003 年兴起的一个轻量级的Java 开发框架&#xff0c;由 RodJohnson 在其著作 Expert One-On-One J2EE Development and Design 中阐述的部分理念和原型衍生而来。它是 为了解决企业应用开发的复杂性而创建的。框架的主要优势…

mockjs使用1

mockjs使用 1、定义 Mock.js 是一款模拟数据生成器&#xff0c;旨在帮助前端攻城师独立于后端进行开发&#xff0c;帮助编写单元测试。提供了以下模拟功能&#xff1a; 根据数据模板生成模拟数据模拟 Ajax 请求&#xff0c;生成并返回模拟数据基于 HTML 模板生成模拟数据 2…

软件测试|SQLAlchemy query() 方法查询数据

简介 上一篇文章我们介绍了SQLAlchemy 的安装和基础使用&#xff0c;本文我们来详细介绍一下如何使用SQLAlchemy的query()方法来高效的查询我们的数据。 创建模型 我们可以先创建一个可供我们查询的模型&#xff0c;也可以复用上一篇文章中我们创建的模型&#xff0c;代码如…

Python字典,什么是字典、增删改查、属性操作和遍历

Python字典是一种无序的、可变的数据类型&#xff0c;它可以存储任意类型的数据&#xff0c;通过键值对的方式进行存储和访问。 字典的增&#xff1a; 使用键值对的方式&#xff0c;将数据添加到字典中。可以通过以下两种方式进行增加&#xff1a; 使用索引表达式&#xff08…