FFmpeg + SDL的視訊播放器的製作(5)
阿新 • • 發佈:2018-12-15
FFmpeg + SDL的視訊播放器的製作(5)
SDL函式
進階練習
視窗可以移動
視窗可以調整大小
/** * 最簡單的SDL2播放視訊的例子(SDL2播放RGB/YUV) * Simplest Video Play SDL2 (SDL2 play RGB/YUV) * * 雷霄驊 Lei Xiaohua * [email protected] * 中國傳媒大學/數字電視技術 * Communication University of China / Digital TV Technology * http://blog.csdn.net/leixiaohua1020 * * 本程式使用SDL2播放RGB/YUV視訊畫素資料。SDL實際上是對底層繪圖 * API(Direct3D,OpenGL)的封裝,使用起來明顯簡單于直接呼叫底層 * API。 * * This software plays RGB/YUV raw video data using SDL2. * SDL is a wrapper of low-level API (Direct3D, OpenGL). * Use SDL is much easier than directly call these low-level API. */ #include <stdio.h> 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;//控制執行緒安全退出 //使得主迴圈main不再有延時,延時放到子執行緒中 int refresh_video(void *opaque){ thread_exit=0; while (thread_exit==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 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; } SDL_Rect sdlRect; SDL_Thread *refresh_thread = SDL_CreateThread(refresh_video,NULL,NULL);//建立一個執行緒,refresh_video是一個函式 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){//windows下自帶的事件。在來回拉伸視窗時候會觸發 //If Resize //從SDL window中,獲得當前視窗的寬和高,下一次迴圈會設定sdlRect.w和sdlRect.h SDL_GetWindowSize(screen,&screen_w,&screen_h); }else if(event.type==SDL_QUIT){//退出事件 thread_exit=1; }else if(event.type==BREAK_EVENT){ break; } } SDL_Quit(); return 0; }