MAC
//./configure --prefix=/usr/local/
//
? 1.添加头文件#include<sdl.h>
? 2.初始化SDL
? 3.退出SDL
SDL_INIT/SDL_Quit()
SDL_Createwindow()/SDL_DestroyWindow()
SDL_CreateRender()
sdl 窗口打开demo?
void sdl_test() {
SDL_Window * window = NULL;
SDL_Renderer *render = NULL;
SDL_Event event;
int quit = 1;
SDL_Init(SDL_INIT_VIDEO);
window = SDL_CreateWindow("SDL2 WINDOW", 100, 100,640, 480, SDL_WINDOW_ALWAYS_ON_TOP);
if (!window) {
SDL_LogInfo(1, "sdl window create failed");
goto __ERROR;
}
render = SDL_CreateRenderer(window, -1, 0);
if (!render) {
SDL_Log("render create failed");
goto __DWINDOW;
}
SDL_RenderClear(render);
SDL_SetRenderDrawColor(render, 255, 0, 0, 0);
SDL_RenderPresent(render);
SDL_Event e;
// while (!quit) {
// while (SDL_PollEvent(&e)) {
// if (e.type == SDL_QUIT) {
// quit = 1;
// }
// }
// }
do{
SDL_WaitEvent(&event);
switch(event.type) {
case SDL_QUIT:
quit = 0;
break;
default:
SDL_Log("EVENT TYPE = %d",event.type);
}
}while(quit);
__DWINDOW:
SDL_DestroyWindow(window);
__ERROR:
SDL_Quit();
}
sdl 渲染
// 内存图像->渲染器->纹理->交换->窗口展示
void sdl_texture(){
//SDL_CreateTexture();
//format:YUV RGB
//access Texture Target stream
//SDL_DestroyTexture();
// SDL_SetRenderTarget(<#SDL_Renderer *renderer#>, <#SDL_Texture *texture#>)
// SDL_RenderClear(<#SDL_Renderer *renderer#>)
// SDL_RenderCopy(<#SDL_Renderer *renderer#>, <#SDL_Texture *texture#>, <#const SDL_Rect *srcrect#>, <#const SDL_Rect *dstrect#>)
// SDL_RenderPresent(<#SDL_Renderer *renderer#>)
SDL_Window * window = NULL;
SDL_Renderer *render = NULL;
SDL_Texture *texture = NULL;
SDL_Event event;
int quit = 1;
SDL_Rect rect;
rect.w = 30;
rect.h = 30;
SDL_Init(SDL_INIT_VIDEO);
window = SDL_CreateWindow("SDL2 WINDOW", 100, 100,640, 480, SDL_WINDOW_ALWAYS_ON_TOP);
if (!window) {
SDL_LogInfo(1, "sdl window create failed");
goto __ERROR;
}
render = SDL_CreateRenderer(window, -1, 0);
if (!render) {
SDL_Log("render create failed");
goto __DWINDOW;
}
SDL_RenderClear(render);
SDL_SetRenderDrawColor(render, 255, 0, 0, 0);
SDL_RenderPresent(render);
texture = SDL_CreateTexture(render, SDL_PIXELFORMAT_RGB888, SDL_TEXTUREACCESS_TARGET, 640,480);
if (!texture) {
SDL_Log("texture create failed");
goto __RENDER;
}
do{
SDL_PollEvent(&event);
switch(event.type) {
case SDL_QUIT:
quit = 0;
break;
default:
SDL_Log("EVENT TYPE = %d",event.type);
}
rect.x = rand() % 600;
rect.y = rand() % 450;
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, 0);
SDL_RenderFillRect(render, &rect);
SDL_SetRenderTarget(render, NULL);
SDL_RenderCopy(render, texture, NULL, NULL);
SDL_RenderPresent(render);
}while(quit);
SDL_DestroyTexture(texture);
__RENDER:
SDL_DestroyRenderer(render);
__DWINDOW:
SDL_DestroyWindow(window);
__ERROR:
SDL_Quit();
}
sdl 播放yuv
#include <stdio.h>
#include <string.h>
#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;
}
void sdl_yuv_player() {
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;
int w_width = 640, w_height = 480;
const int video_width = 608, video_height = 368;
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 = "/Users/king/Desktop/ffmpeg/video/01.yuv";
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;
}
//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(win, -1, 0);
//IYUV: Y + U + V (3 planes)
//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
if((video_buff_len = fread(video_buf, 1, BLOCK_SIZE, video_fd)) <= 0){
fprintf(stderr, "Failed to read data from yuv file!\n");
goto __FAIL;
}
//set video positon
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 && !blank_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;
blank_space_len -= video_buff_len;
printf("not enought data: pos:%p, video_end:%p, blank_space_len:%d\n", video_pos, video_end, blank_space_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 );
printf("not enought data: pos:%p, video_end:%p, blank_space_len:%d\n", video_pos, video_end, blank_space_len);
video_pos += yuv_frame_len;
}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();
}
sdl播放pcm
#define BLOCK_SIZE 4096000
static Uint8 *audio_bufer = NULL;
static Uint8 *audio_pos = NULL;
static size_t buffer_len = 0;
void read_audio_data(void *data, Uint8 *stream, int len) {
if(buffer_len == 0) {
return;
}
SDL_memset(stream, 0, len);
len = (len < buffer_len) ? len : buffer_len;
SDL_MixAudio(stream, audio_pos, len, SDL_MIX_MAXVOLUME);
audio_pos+=len;
buffer_len-=len;
}
void audio_player() {
char *path = "/Users/king/Desktop/ffmpeg/audio/test.pcm";
FILE *audio_fd = NULL;
int result = SDL_Init(SDL_INIT_AUDIO | SDL_INIT_TIMER);
if (result) {
SDL_Log("init failed");
return;
}
audio_fd = fopen(path, "rb+");
if (!audio_fd) {
SDL_Log("failed to pcm file");
goto __FAIL;
}
audio_bufer = (Uint8 *)malloc(BLOCK_SIZE);
if (!audio_bufer) {
SDL_Log("dailed to alloc buffer");
}
SDL_AudioSpec spec;
spec.freq = 44100;
spec.channels = 2;
spec.format = AUDIO_S16SYS;
spec.callback = read_audio_data;
spec.silence = 0;
spec.userdata = NULL;
if (SDL_OpenAudio(&spec, NULL)) {
SDL_Log("Failed to open audio device");
goto __FAIL;
}
SDL_PauseAudio(0);
/// 从文件读取数据到buffer。声卡需要多少再从缓存中给多少
do{
buffer_len = fread(audio_bufer, 1, BLOCK_SIZE, audio_fd);
audio_pos = audio_bufer;
while (audio_pos < (audio_bufer + buffer_len)) {
/// 这个时候buffer里面有数据 就先不读
SDL_Delay(1);
}
} while(buffer_len != 0);
SDL_CloseAudio();
__FAIL:
if (audio_bufer) {
free(audio_bufer);
}
if(audio_fd) {
fclose(audio_fd);
}
SDL_Quit();
}