(4) SDL视频显示-进阶
代码记录
#include
extern "C"
{
#include "sdl/SDL.h"
};
const int bpp=12;
int screen_w=500,screen_h=500;
const int pixel_w=320,pixel_h=180;
unsigned char buffer[pixel_w*pixel_h*bpp/8];
//Refresh Event
#define REFRESH_EVENT (SDL_USEREVENT + 1)
//Break
#define BREAK_EVENT (SDL_USEREVENT + 2)
int thread_exit=0;
int thread_pause=0;
int refresh_video(void *opaque){
thread_exit=0;
while (thread_exit==0) {
if(thread_pause==0){
SDL_Event event;
event.type = REFRESH_EVENT;
SDL_PushEvent(&event);
}
SDL_Delay(40);
}
thread_exit=0;
//Break
SDL_Event event;
event.type = BREAK_EVENT;
SDL_PushEvent(&event);
return 0;
}
int writeY(FILE *i_file,FILE *o_file,const int w,const int h){
//读取文件i_file
FILE* fp_yuv=i_file;
//写入文件o_file
FILE* fp_frame=o_file;
//开辟内存,与读取的文件的大小一致
char* buffer_y=(char*)malloc(sizeof(char)*w*h);
char* buffer_u=(char*)malloc(sizeof(char)*w*h/4);
char* buffer_v=(char*)malloc(sizeof(char)*w*h/4);
//读取函数,将i_file的第一帧存入buff指向的内存
for(int i=0;i<50;i++)//50:i_file文件一共有50帧
{
fread(buffer_y,w*h,1,fp_yuv);
fread(buffer_u,w*h/4,1,fp_yuv);
fread(buffer_v,w*h/4,1,fp_yuv);
/*memset():将buffer_u/buffer_v后面的w*h/4个字节用128替换*/
memset(buffer_u,128,w*h/4);//128:色度的值,取值0~255
memset(buffer_v,128,w*h/4);//128:饱和度的值,取值0~255
fwrite(buffer_y,w*h,1,fp_frame);
fwrite(buffer_u,w*h/4,1,fp_frame);
fwrite(buffer_v,w*h/4,1,fp_frame);
}
free(buffer_y);
free(buffer_u);
free(buffer_v);
return 0;
}
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 = 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;
}
//写入文件frame.yuv(亮度数据)
FILE* fp_frame=fopen("frame_320x180_out.yuv","wb");
writeY(fp,fp_frame,pixel_w,pixel_h);
fclose(fp_frame);
SDL_Rect sdlRect;
SDL_Thread *refresh_thread = SDL_CreateThread(refresh_video,NULL,NULL);
SDL_Event event;
while(1){
//Wait
SDL_WaitEvent(&event);
if(event.type==REFRESH_EVENT){
if (fread(buffer, 1, pixel_w*pixel_h*bpp/8, fp) != pixel_w*pixel_h*bpp/8){
// Loop
fseek(fp, 0, SEEK_SET);
fread(buffer, 1, pixel_w*pixel_h*bpp/8, fp);
}
SDL_UpdateTexture( sdlTexture, NULL, buffer, pixel_w);
//FIX: If window is resize
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){
//If Resize
SDL_GetWindowSize(screen,&screen_w,&screen_h);
}else if(event.type==SDL_KEYDOWN){
//Pause
if(event.key.keysym.sym==SDLK_SPACE)
thread_pause=!thread_pause;
}else if(event.type==SDL_QUIT){
thread_exit=1;
}else if(event.type==BREAK_EVENT){
break;
}
}
SDL_Quit();
return 0;
}