SDL开发笔记(初级)
SDL窗口渲染
SDL(Simple DirectMedia Layer)
由C语言实现的跨平台的媒体开源库
用于游戏开发、模拟器、媒体播放器等多媒体应用领域
注意: 安装步骤
1.下载SDK源代码 (http://www.libsdl.org/index.php)
2.解压源码 tar -zvxf SDL2-2.0.12.tar.gz
3. 编译与安装 ./configure --prefix=/usr/local (后面的路径表示安装路径)
4.安装 sudo make -j 8 && make install
5.安装完毕
![](https://img.haomeiwen.com/i1716313/526e6877ee4e9a73.png)
SDL简单用法
SDL_Init() //
SDL_CreateWindow() //
SDL_DestoryWindow() //
SDL_Quit() //
SDL_CreateRender/SDL_DestoryRenderer () //SDL 渲染器创建/销毁
SDL_RenderClear //清空上一次的render数据
SDL_RenderPresent //将数据显示出来
程序内容:
#include<SDL.h>
#include<stdio.h>
int main(int argc, char * argv[]){
SDL_Window *window = NULL;
SDL_Renderer *render = NULL;
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO);
/*SDL日志输出*/
SDL_Log("hello SDL");
/*title、坐标x、坐标y、宽、高、 参数*/
window = SDL_CreateWindow("SDL2 Window",
200,
400,
640,
680,
SDL_WINDOW_SHOWN);
if(!window){
SDL_Log("Fail to create SDL window\n");
goto __EXIT;
}
render = SDL_CreateRenderer(window,-1,0);
if(!render){
SDL_Log("Failed to create render\n");
goto __DESTORYWINDOW;
}
/* 渲染器、(255,0,0)红色、255 表示透明度*/
SDL_RenderClear(render);
SDL_SetRenderDrawColor(render,255,0,0,255);
SDL_RenderPresent(render);
SDL_Delay(30000);
__DESTORYWINDOW:
SDL_DestroyWindow(window);
__EXIT:
SDL_Quit();
return 0;
}
使用命令编译: clang -g -o firstsdl firstsdl.c pkg-config --cflags --libs sdl2
运行程序: ./firstsdl
SDL 处理事件
SDL_WindowEvent: //窗口事件
SDL_KeyboardEvent: //键盘事件
SDL_MouseMotionEvent: //鼠标事件
SDL_PollEvent //轮循触发机制
SDL_WaitEvent //事件触发机制
程序内容:
#include<SDL.h>
#include<stdio.h>
int main(int argc, char * argv[]){
int quit = 1;
SDL_Event event;
SDL_Window *window = NULL;
SDL_Renderer *render = NULL;
SDL_Init(SDL_INIT_VIDEO);
/*SDL日志输出*/
SDL_Log("hello SDL");
/*title、坐标x、坐标y、宽、高、 参数*/
window = SDL_CreateWindow("SDL2 Window",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
640,
480,
SDL_WINDOW_OPENGL);
if(!window){
SDL_Log("Fail to create SDL window\n");
goto __EXIT;
}
render = SDL_CreateRenderer(window,-1,0);
if(!render){
SDL_Log("Failed to create render\n");
goto __DESTORYWINDOW;
}
/* 渲染器、(255,0,0)红色、255 表示透明度*/
SDL_SetRenderDrawColor(render,255,0,0,255);
SDL_RenderClear(render);
SDL_RenderPresent(render);
//SDL_Delay(10000);
do {
SDL_WaitEvent(&event);
switch(event.type){
case SDL_QUIT:
quit =0;
break;
default:
SDL_Log("event type is %d",event.type);
}
}while(quit);
__DESTORYWINDOW:
SDL_DestroyWindow(window);
__EXIT:
SDL_Quit();
return 0;
}
使用命令编译: clang -g -o firstsdl firstsdl.c pkg-config --cflags --libs sdl2
运行程序: ./firstsdl
SDL理解纹理渲染
SDL_CreateTexture(format,access) //format:YUV,RGB 、access:Texture类型、Traget,Stream
SDL_DestoryTexture() //销毁
SDL_SetRenderTarget() //设置渲染的targe
SDL_RenderClear() //清屏
SDL_renderCopy() //将纹理数据copy
SDL_RenderPresent() //将计算好的图形投影到显示器上
程序内容:
#include<SDL.h>
#include<stdio.h>
int main(int argc, char * argv[]){
int quit = 1;
SDL_Event event;
SDL_Window *window = NULL;
SDL_Renderer *render = NULL;
SDL_Init(SDL_INIT_VIDEO);
/*SDL日志输出*/
SDL_Log("hello SDL");
/*title、坐标x、坐标y、宽、高、 参数*/
window = SDL_CreateWindow("SDL2 Window",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
640,
480,
SDL_WINDOW_OPENGL);
if(!window){
SDL_Log("Fail to create SDL window\n");
goto __EXIT;
}
render = SDL_CreateRenderer(window,-1,0);
if(!render){
SDL_Log("Failed to create render\n");
goto __DESTORYWINDOW;
}
/* 渲染器、(255,0,0)红色、255 表示透明度*/
SDL_SetRenderDrawColor(render,255,0,0,255);
SDL_RenderClear(render);
SDL_RenderPresent(render);
//SDL_Delay(10000);
SDL_Texture *texture = SDL_CreateTexture(render,
SDL_PIXELFORMAT_RGBA8888,
SDL_TEXTUREACCESS_TARGET,
640,480);
if(!texture){
SDL_Log("Failed to create texture");
goto __RENDER;
}
do {
SDL_WaitEvent(&event);
switch(event.type){
case SDL_QUIT:
quit =0;
break;
default:
SDL_Log("event type is %d",event.type);
}
/* 画一个随机小方块在画布中随机出现*/
SDL_Rect rect;
rect.w = 40;
rect.h = 40;
rect.x = rand()%640;
rect.y = rand()%480;
SDL_SetRenderTarget(render,texture);
SDL_SetRenderDrawColor(render,0,0,0,0);
SDL_RenderClear(render);
SDL_RenderDrawRect(render,&rect);
SDL_SetRenderDrawColor(render,255,0,0,0);
SDL_RenderFillRect(render,&rect);
SDL_SetRenderTarget(render,NULL);
SDL_RenderCopy(render,texture,NULL,NULL);
SDL_RenderPresent(render);
}while(quit);
__RENDER:
SDL_DestroyTexture(texture);
__DESTORYWINDOW:
SDL_DestroyWindow(window);
__EXIT:
SDL_Quit();
return 0;
}
使用命令编译: clang -g -o firstsdl firstsdl.c pkg-config --cflags --libs sdl2
运行程序: ./firstsdl
SDL 实现YUV播放器
SDL_CreateThread(fn,name,data) //fn:线程执行参数 name:线程名称,data:执行线程所需的参数
SDL_UpdateTexture() //更新SDL纹理
SDL_UpdateYUVTexture() //更新SDL的YUV纹理(效率更高)
程序内容:(程序有错误,需要调试)
#include <stdio.h>
#include <string.h>
#include <SDL.h>
const int bpp=12;
#define BLOCK_SIZE 4096000
//event message
#define REFRESH_EVENT (SDL_USEREVENT + 1)
#define QUIT_EVENT (SDL_USEREVENT + 2)
int thread_exit=0;
int refresh_video_timer(void *udata){
thread_exit=0;
while (!thread_exit) {
SDL_Event event;
event.type = REFRESH_EVENT;
SDL_PushEvent(&event);
SDL_Delay(40);
}
thread_exit=0;
//push quit event
SDL_Event event;
event.type = QUIT_EVENT;
SDL_PushEvent(&event);
return 0;
}
int main(int argc, char* argv[])
{
FILE *video_fd = NULL;
SDL_Event event;
SDL_Rect rect;
Uint32 pixformat = 0;
SDL_Window *win = NULL;
SDL_Renderer *renderer = NULL;
SDL_Texture *texture = NULL;
SDL_Thread *timer_thread = NULL;
Uint8 *video_buf = NULL;
int w_width = 640;
int w_height = 480;
const int video_width = 320, video_height = 180;
Uint8 *video_pos = NULL;
Uint8 *video_end = NULL;
unsigned int remain_len = 0;
unsigned int video_buff_len = 0;
unsigned int blank_space_len = 0;
Uint8 *video_buf[BLOCK_SIZE];
const char *path = "test_yuv420p_320x180.yuv";
/* 定义一个YUV数据包的缓冲区大小
YUV 表示 4:2:0 、4:0:2*/
const unsigned int yuv_frame_len = video_width * video_height * 12 / 8;
//initialize SDL
if(SDL_Init(SDL_INIT_VIDEO)) {
fprintf( stderr, "Could not initialize SDL - %s\n", SDL_GetError());
return -1;
}
//creat window from SDL
win = SDL_CreateWindow("YUV Player",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
w_width, w_height,
SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE);
if(!win) {
fprintf(stderr, "Failed to create window, %s\n",SDL_GetError());
goto __FAIL;
}
renderer = SDL_CreateRenderer(video_width, -1, 0);
//IYUV: Y + U + V (3 planes)s
//YV12: Y + V + U (3 planes)
pixformat= SDL_PIXELFORMAT_IYUV;
//create texture for render
texture = SDL_CreateTexture(renderer,
pixformat,
SDL_TEXTUREACCESS_STREAMING,
video_width,
video_height);
//open yuv file
video_fd = fopen(path, "r");
if( !video_fd ){
fprintf(stderr, "Failed to open yuv file\n");
goto __FAIL;
}
//read block data
video_buff_len = fread(video_buf, 1, BLOCK_SIZE, video_fd);
if(video_buff_len <= 0){
fprintf(stderr, "Failed to read data from yuv file!\n");
goto __FAIL;
}
/* 视频起始位*/
video_pos = video_buf;
video_end = video_buf + video_buff_len;
/* */
blank_space_len = BLOCK_SIZE - video_buff_len;
timer_thread = SDL_CreateThread(refresh_video_timer,
NULL,
NULL);
do {
//Wait
SDL_WaitEvent(&event);
if(event.type==REFRESH_EVENT){
//not enought data to render
if((video_pos + yuv_frame_len) > video_end){
//have remain data, but there isn't space
remain_len = video_end - video_pos;
if(remain_len && !black_space_len) {
//copy data to header of buffer
memcpy(video_buf, video_pos, remain_len);
blank_space_len = BLOCK_SIZE - remain_len;
video_pos = video_buf;
video_end = video_buf + remain_len;
}
//at the end of buffer, so rotate to header of buffer
if(video_end == (video_buf + BLOCK_SIZE)){
video_pos = video_buf;
video_end = video_buf;
blank_space_len = BLOCK_SIZE;
}
//read data from yuv file to buffer
if(video_buff_len = fread(video_end, 1, blank_space_len, video_fd) <= 0){
fprintf(stderr, "eof, exit thread!");
thread_exit = 1;
continue;// to wait event for exiting
}
//reset video_end
video_end += video_buff_len;
}
SDL_UpdateTexture( texture, NULL, video_pos, video_width);
//FIX: If window is resize
rect.x = 0;
rect.y = 0;
rect.w = w_width;
rect.h = w_height;
SDL_RenderClear( renderer );
SDL_RenderCopy( renderer, texture, NULL, &rect);
SDL_RenderPresent( renderer );
}else if(event.type==SDL_WINDOWEVENT){
//If Resize
SDL_GetWindowSize(win, &w_width, &w_height);
}else if(event.type==SDL_QUIT){
thread_exit=1;
}else if(event.type==QUIT_EVENT){
break;
}
}while ( 1 );
__FAIL:
//close file
if(video_fd){
fclose(video_fd);
}
SDL_Quit();
return 0;
}
使用命令编译: clang -g -o yuv_player yuv_player.c pkg-config --cflags --libs sdl2
运行程序:./yuv_player
SDL 实现音频播放器
SDL_CreateThread() //创建线程
SDL_WaitThread() //等待线程结束
SDL_CreateMutex/SDL_DestroyMutex() //创建互斥锁/销毁互斥锁
SDL_LockMutex/SDL_UnlockMutex() //锁住互斥量/打开互斥量
SDL_CreateCond/SDL_DestroyCond() //创建信号量/销毁信号量
SDL_CondWait/SDL_CondSignal() //等待信号/发送信号
程序内容:
使用命令编译:
运行程序: