[2] SDL的基础知识以及利用SDL播放视频

article/2025/10/11 15:47:32

此博文相关知识点从雷神的博客以及视频学习,截图也是用了他的课件,
雷神博客地址:http://blog.csdn.net/leixiaohua1020/


日期:2016.10.1
作者:isshe
github:github.com/isshe
邮箱:i.sshe@outlook.com


SDL基础知识

  • SDL结构图
    这里写图片描述

  • SDL函数调用的一般流程
    这里写图片描述

    • 最最主要操作的函数是SDL_texture();
    • 工作过程大致是:FFMpeg「Decode」解码一帧,交给SDL_texture(), 然后再复制给渲染器,渲染器再显示出来。以此循环。
    • 相关函数:待补充(不定期更新)
  • SDL的一些主要的数据结构
    这里写图片描述

    • SDL2支持多窗口显示,主要是依靠SDL_rect().
    • 相关数据结构:待补充(不定期更新)

示例代码1:

  • 代码
#include <stdio.h>#include "SDL2/SDL.h"#define SCREEN_W    640             //窗口的宽
#define SCREEN_H    360             //窗口的高
#define PIXEL_W     320             //视频像素的宽,要和视频文件相同才能显示正常
#define PIXEL_H     180             //像素的高
#define BPP         12              //像素深度:指存储每个像素所用的位数(bit)
#define BUF_LEN     ((PIXEL_W) * (PIXEL_H) * (BPP) / 8)     //存一帧的需要空间const int bpp = BPP;
int screen_w = SCREEN_W;
int screen_h = SCREEN_H;
const int pixel_w = PIXEL_W;
const int pixel_h = PIXEL_H;unsigned char buffer[BUF_LEN+1];int main(int argc, char* argv[])
{if(SDL_Init(SDL_INIT_VIDEO)) {printf( "Could not initialize SDL - %s\n", SDL_GetError());return -1;}SDL_Window *screen;//SDL 2.0 Support for multiple windows//画一个窗口,大小为screen_w * screen_hscreen = SDL_CreateWindow("Simplest Video Play SDL2", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
screen_w,screen_h,SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE);if(!screen) {printf("SDL: could not create window - exiting:%s\n",SDL_GetError());return -1;}//新建一个渲染器SDL_Renderer* sdlRenderer = SDL_CreateRenderer(screen, -1, 0);Uint32 pixformat=0;//IYUV: Y + U + V  (3 planes)//YV12: Y + V + U  (3 planes)pixformat= SDL_PIXELFORMAT_IYUV;        //???SDL_Texture* sdlTexture = SDL_CreateTexture(sdlRenderer,pixformat, SDL_TEXTUREACCESS_STREAMING,pixel_w,pixel_h);FILE *fp=NULL;fp=fopen("test_yuv420p_320x180.yuv","rb+");if(fp==NULL){printf("cannot open this file\n");return -1;}SDL_Rect sdlRect;int i = 5;while(i >= 0){//一次读1byte,总共读一帧if (fread(buffer, 1, pixel_w*pixel_h*bpp/8, fp) != pixel_w*pixel_h*bpp/8){// Loopfseek(fp, 0, SEEK_SET);
//              fread(buffer, 1, pixel_w*pixel_h*bpp/8, fp);i--;continue;}//更新纹理数据SDL_UpdateTexture( sdlTexture, NULL, buffer, pixel_w);//(x,y)是窗口左上边开始的点。//w,h是整个像素窗口宽和高(注意不是整个窗口)sdlRect.x = 0;sdlRect.y = 0;sdlRect.w = screen_w;sdlRect.h = screen_h;//清空渲染器//复制数据纹理给渲染器//显示SDL_RenderClear( sdlRenderer );SDL_RenderCopy( sdlRenderer, sdlTexture, NULL, &sdlRect);SDL_RenderPresent( sdlRenderer );//Delay 40ms,一般视频都是这个,25帧/s.SDL_Delay(40);}SDL_Quit();return 0;
}
  • 编译:
gcc1_SDL_create_window.c -o 1_SDL_create_window.out -O2 -Wall -g -lSDL2 -lSDL2main

结果截图:
这里写图片描述
* 注意,这个程序如果是在windows下面,窗口是不能移动的,鼠标放上去也是忙的状态。在下一个程序中修改程序,使它能移动,以及自动适应窗口大小。


示例程序2:

  • 代码:
#include <stdio.h>
#include <errno.h>
#include <string.h>#include <SDL2/SDL.h>#define SCREEN_W    640             //窗口的宽
#define SCREEN_H    360             //窗口的高
#define PIXEL_W     320             //视频像素的宽,要和视频文件相同才能显示正常
#define PIXEL_H     180             //像素的高
#define BPP         12              //像素深度:指存储每个像素所用的位数(bit)
#define BUF_LEN     ((PIXEL_W) * (PIXEL_H) * (BPP) / 8)     //存一帧的需要空间
#define FILENAME    "test_yuv420p_320x180.yuv"
#define MY_DEFINE_REFRESH_EVENT     (SDL_USEREVENT + 1)
#define MY_DEFINE_BREAK_EVENT       (SDL_USEREVENT + 2)int thread_exit = 0;
static int refresh_func(void *arg)
{SDL_Event   event;thread_exit = 0;while(0 == thread_exit){event.type = MY_DEFINE_REFRESH_EVENT;SDL_PushEvent(&event);      //发送一个事件,使主线程继续运行SDL_Delay(40);}//子线程退出后发送事件给主线程,使主线程也退出thread_exit = 0;event.type = MY_DEFINE_BREAK_EVENT;SDL_PushEvent(&event);return 0;
}const int bpp = BPP;int main(int argc, char *argv[])
{int screen_w = SCREEN_W;int screen_h = SCREEN_H;const int pixel_w = PIXEL_W;const int pixel_h = PIXEL_H;unsigned char buffer[BUF_LEN + 1];      //注意类型char            filename[256] = FILENAME;SDL_Window      *screen = NULL;         //窗口数据结构SDL_Renderer    *sdlRenderer = NULL;    //渲染器数据结构Uint32          pixformat = 0;SDL_Texture     *sdlTexture = NULL;     //主要操作的FILE            *fp = NULL;SDL_Rect        sdlRect;
//    SDL_Thread      *refresh_thread = NULL; //线程数据结构SDL_Event       event;                  //事件数据结构//注意:可以把文件传进来了,但是如果不使用ffmmpeg的函数还不知道怎么改像素值,以使视频正常显示!!!!!if (argc > 2){printf("Usage: ./*.out videofile.yuv\n");return 0;}else if (argc == 2){memcpy(filename, argv[1], strlen(argv[1]) + 1);
//         filename[strlen(argv[1])] = '\0';}printf("video file name: %s\n", filename);if (SDL_Init(SDL_INIT_VIDEO)){printf("Couldn't initialize SDL - %s\n", SDL_GetError());return (-1);}screen = SDL_CreateWindow("isshe Video Player SDL2",SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,screen_w, screen_h,SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);if (!screen){printf("SDL:Couldn't not create window error: %s\n", SDL_GetError());return (-1);}//创建渲染器,-1,0不懂什么意思,再看这个函数的定义sdlRenderer = SDL_CreateRenderer(screen, -1, 0);//在pixels.h中,大概是指定输入数据格式?不懂!pixformat = SDL_PIXELFORMAT_IYUV;sdlTexture = SDL_CreateTexture(sdlRenderer, pixformat,SDL_TEXTUREACCESS_STREAMING, pixel_w, pixel_h);//打开文件fp = fopen(filename, "r");if (NULL == fp){printf("Open file error:%s\n", strerror(errno));return (-1);}//新建线程
//    refresh_thread =SDL_CreateThread(refresh_func, NULL, NULL);while(1){//等待一个事件SDL_WaitEvent(&event);     //事件的信息存到结构中了//处理事件, 尝试使用自定义的事件if (event.type == MY_DEFINE_REFRESH_EVENT){//读一帧if (fread(buffer, 1, BUF_LEN, fp) != BUF_LEN) //出错或结尾{//重定位会文件头部fseek(fp, 0, SEEK_SET);continue;         //}//更新纹理,但是不懂最后一个参数,是一次更新一行吗?SDL_UpdateTexture(sdlTexture, NULL, buffer, pixel_w);sdlRect.x = 0;sdlRect.y = 0;sdlRect.w = screen_w;sdlRect.h = screen_h;SDL_RenderClear(sdlRenderer);//把数据从第二个参数复制到第一个参数SDL_RenderCopy(sdlRenderer, sdlTexture, NULL, &sdlRect);SDL_RenderPresent(sdlRenderer);}else if (event.type == SDL_WINDOWEVENT){//获取像素窗口的大小,窗口拉伸的时候用这个则会自动调整SDL_GetWindowSize(screen, &screen_w, &screen_h);}else if (event.type == SDL_QUIT){thread_exit = 1;}else if (event.type == MY_DEFINE_BREAK_EVENT)    //线程结束,主线程也结束{break;}}fclose(fp);SDL_Quit();return 0;
}
  • 程序中主线程阻塞等待事件,子线程发送事件后主线程继续运行。
  • 程序中自定义了两个事件类型,用以说明事件类型可自定义。

  • 编译:

gcc  2_SDL_pthread_event.c -o 2_SDL_pthread_event.out -O2 -Wall -g -lSDL2 -lSDL2main
  • 运行结果:
    这里写图片描述
    • 可以随意拉伸窗口。
    • 可以关闭。

参考资料:

  • 雷神的视频
  • SDL2.0 源码

资料下载:http://download.csdn.net/detail/i_scream_/9644380


http://chatgpt.dhexx.cn/article/PX8PiX7G.shtml

相关文章

Start Game:SDL2简介

Start Game&#xff1a;SDL2简介 官网简介&#xff1a; Simple DirectMedia Layer是一个跨平台开发库&#xff0c;旨在通过OpenGL和Direct3D提供对音频、键盘、鼠标、操纵杆和图形硬件的低级别访问。它被视频播放软件、模拟器和流行游戏使用&#xff0c;包括Valve的获奖目录和许…

SDL2的学习之路<三>显示文字

前言 上节介绍了怎么利用SDL接口去显示图片&#xff0c;这节主要介绍怎么去显示文本信息。 SDL2展示文字需要在官网下载SDL2_ttf的扩展库。这个第一节已经讲过了。 使用时需要先初始化库&#xff0c;使用结束时释放库资源。 TTF_Init(); //初始化库 … TTF_Quit(); //释放 显…

VS2019配置SDL2库

“SDL&#xff08;Simple DirectMedia Layer&#xff09;是一套开放源代码的跨平台多媒体开发库&#xff0c;使用C语言写成。SDL提供了数种控制图像、声音、输出入的函数&#xff0c;让开发者只要用相同或是相似的代码就可以开发出跨多个平台&#xff08;Linux、Windows、MacOS…

SDL系列教程(一):SDL简介

SDL教程&#xff08;一&#xff09; 作者&#xff1a;akinggw 在阔别半年后&#xff0c;我又回来了。这次回来&#xff0c;首先要向大家问声好&#xff0c;然后继续我们的游戏开发之旅。在以前的日子里&#xff0c;我主要在翻译一些游戏开发方面的文章&#xff0c;而现在&…

SDL2源代码分析1:初始化(SDL_Init())

SDL源代码分析系列文章列表&#xff1a; SDL2源代码分析1&#xff1a;初始化&#xff08;SDL_Init()&#xff09; SDL2源代码分析2&#xff1a;窗口&#xff08;SDL_Window&#xff09; SDL2源代码分析3&#xff1a;渲染器&#xff08;SDL_Renderer&#xff09; SDL2源代码…

SDL2入门教程(01_hello_SDL)

注&#xff1a; 本教程翻译自 lazyfoo的教程&#xff0c;原网址戳这里。翻译目的为鼓励自己坚持下去&#xff0c;可能语言不准确&#xff0c;仅供参考。 Hello SDL: 你的第一个图形窗口 这一篇教程包含最主要也最基础的一步——弹出一个窗口&#xff08;Window&#xff09; …

SDL2源代码分析2:窗口(SDL_Window)

SDL源代码分析系列文章列表&#xff1a; SDL2源代码分析1&#xff1a;初始化&#xff08;SDL_Init()&#xff09; SDL2源代码分析2&#xff1a;窗口&#xff08;SDL_Window&#xff09; SDL2源代码分析3&#xff1a;渲染器&#xff08;SDL_Renderer&#xff09; SDL2源代码…

SDL2使用简介

转自我的Gitee项目 SDL2使用简介 SDL2使用简介开发环境搭建WindowsVisual StudioCode::BlocksDev-Cpp CMake(CLion)问题总结 SDL2库使用介绍初始化创建窗口绘制矩形刷新屏幕读取输入直接扫描键盘读取系统事件 实例 绘制图片 SDL2使用简介 开发环境搭建 Windows Visual Stud…

SDL2 简明教程(二):创建一个空的窗口

系列文章目录 SDL2 简明教程&#xff08;一&#xff09;&#xff1a;使用 Cmake 和 Conan 构建 SDL2 编程环境 SDL2 简明教程&#xff08;二&#xff09;&#xff1a;创建一个空的窗口 文章目录 系列文章目录创建空窗口总结 创建空窗口 在上一篇文章中&#xff0c;我们了解…

强大无比的嵌入式多媒体开发神器:SDL2

SDL 是什么&#xff1f; SDL&#xff08;Simple DirectMedia Layer&#xff09;是一套开源的跨平台多媒体开发库&#xff0c;使用 C 语言写成。 它提供了绘制图像、播放声音、获取键盘输入等相关的 API&#xff0c;大大降低多媒体应用开发难度的同时&#xff0c;也让开发者只要…

SDL2 简明教程(五):OpenGL 绘制

系列文章目录 SDL2 简明教程&#xff08;一&#xff09;&#xff1a;使用 Cmake 和 Conan 构建 SDL2 编程环境 SDL2 简明教程&#xff08;二&#xff09;&#xff1a;创建一个空的窗口 SDL2 简明教程&#xff08;三&#xff09;&#xff1a;显示图片 SDL2 简明教程&#xf…

SDL —— SDL2及API简介

SDL2框架 SDL&#xff08; Simple DirectMedia Layer&#xff09; 是一套开放源代码的跨平台多媒体开发库&#xff0c; 使用 C 语 言写成。 SDL 提供了数种控制图像、 声音、 输出入的函数&#xff0c; 让开发者只要用相同或是相似的 代码就可以开发出跨多个平台&#xff08; L…

SDL2学习笔记(一):SDL2初步

一、Windows系统下的安装 MinGW ①安装MinGW并配置好环境变量&#xff1b; ②官网下载SDL for MinGW&#xff1b; ③将解压文件中的 .\i686-w64-mingw32\include\SDL2 复制到 .\MinGW\include &#xff1b; //有的设备需要用x86_64-w64-mingw32中的文件&#xff0c;下同 ④将解…

ISCC2021—ISCC客服一号冲冲冲(二)

ISCC客服一号冲冲冲&#xff08;二&#xff09; 呦&#xff0c;又见面了&#xff0c;狗子 打开链接&#xff0c;发现登录接口似乎是个图片截了一块啊&#xff0c;把图片下载下来&#xff0c;lsp隐写发现源代码&#xff0c;同时php弱比较登录页面 &#xff08;都看到这里啦&a…

ISCC2021——web部分

练武 ISCC客服冲冲冲&#xff08;一&#xff09; 该题目需要左边的客服票数高于右边的 我会的就两种方法&#xff0c;毕竟是废物嘛&#xff0c;允许 1、 把左右按钮换一下 然后就 2、在控制台输入 回车&#xff0c;走你 你涨啊&#xff0c;涨啊&#xff0c;接着涨啊…没吃…

ISCC,Misc:隐秘的信息

解码得到解压密码 解压出一张图&#xff0c;低位时头部显示有一串字符被 f f f f f 包裹&#xff0c;将可疑的字符单独拿出来 由于单个字符可能是由二进制错位导致的 fffffa4a9a1a1bd9 9b7a1a9ba34b127a 0b8abbc20b7a2b7a 2b524b43e9f8007f fffc7e3fe00fff00 71fffffffffffff…

ISCC理论题小解

B 域、工作组和家庭组表示在网络中组织计算机的不同方法。它们之间的主要区别是对网络中的计算机和其他资源的管理方式。 网络中运行 Windows 的计算机必须属于某个工作组或某个域。家庭网络中运行 Windows 的计算机也可以属于某个家庭组&#xff0c;但这不是必需的。 家庭网络…

ISCC web4

ISCC web4 打开网页看到&#xff1a; 代码审计。。。。。。。。。 一开始以为是sha256解密&#xff0c;结果半天搞不出来 后来才知道parse_url函数存在变量覆盖漏洞 因为要存在action参数&#xff0c;传入actionauth key也要传入key0 由于key是要被sha256加密的 传入一个has…

ISCC2022 擂台misc

文章目录 666扫&#xff01;弱雪真扫黑暗森林PNGstego这是压缩包吗&#xff1f;小 数 学习了 P.S&#xff1a;抬杠就是你对 666 考查知识点:伪加密、猜谜的steghide弱口令爆破、流量分析、gif帧、键盘密码、AES 下载下来是一个压缩包&#xff0c;但是图片显示需要密码&#xf…

ISCC-2022 部分wp

目录 Web冬奥会解题步骤详细描述解题收获 Easy_sql解题步骤详细描述解题收获 Pop2022解题步骤详细描述解题收获 findme解题步骤详细描述 爱国敬业好青年-2解题步骤详细描述解题收获 这是一道代码审计题 Misc单板小将苏翊鸣解题步骤详细描述解题收获 2022冬奥会解题步骤详细描述…