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.安装完毕

xxxx.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() //等待信号/发送信号

程序内容:

使用命令编译:

运行程序:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,298评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,701评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,078评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,687评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,018评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,410评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,729评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,412评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,124评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,379评论 2 242
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,903评论 1 257
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,268评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,894评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,014评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,770评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,435评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,312评论 2 260