FFmpeg + SDL的視訊播放器的製作(4)
阿新 • • 發佈:2018-12-15
FFmpeg + SDL的視訊播放器的製作(4)
SDL的函式和資料結構
二倍速度
二倍寬度
視窗大小固定為500X500
視訊周圍包圍10畫素的“黑框”
換一段測試YUV素材進行播放
示例程式:
/** * 最簡單的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; //原視窗為320*180 int screen_w=500,screen_h=500; const int pixel_w=640,pixel_h=360;//YUV資料的寬高 unsigned char buffer[pixel_w*pixel_h*bpp/8]; int main(int argc, char* argv[]) { if(SDL_Init(SDL_INIT_VIDEO)) { //初始化SDL系統 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);//建立視窗SDL_Window,指定視窗的寬screen_w和高screen_h if(!screen) { printf("SDL: could not create window - exiting:%s\n",SDL_GetError()); return -1; } SDL_Renderer* sdlRenderer = SDL_CreateRenderer(screen, -1, 0); //建立渲染器SDL_Renderer 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);//建立紋理SDL_Texture FILE *fp=NULL; fp=fopen("sintel_640_360.yuv","rb+");//開啟YUV檔案 if(fp==NULL){ printf("cannot open this file\n"); return -1; } SDL_Rect sdlRect; //一個簡單的矩形結構,決定圖形顯示螢幕在什麼位置上 while(1){ //bpp,每個畫素佔多少位元,pixel_w*pixel_h*bpp/8這是讀取一幀完整的YUV資料 //Y資料量:寬*高,U和V的資料量是寬*高/4,1+1/4+1/4=1.5 if (fread(buffer, 1, pixel_w*pixel_h*bpp/8, fp) != pixel_w*pixel_h*bpp/8){//讀一幀YUV資料到buffer裡面 // Loop fseek(fp, 0, SEEK_SET); fread(buffer, 1, pixel_w*pixel_h*bpp/8, fp); } SDL_UpdateTexture( sdlTexture, NULL, buffer, pixel_w); //設定或更新紋理的資料,YUV資料傳遞給了SDL_UpdateTexture //sdlRect的x和y是矩形左上角點的座標(全屏顯示(0,0)) //x,y相當於起始點 //視訊周圍包圍10畫素的黑邊,所以x,y為10 sdlRect.x = 10; sdlRect.y = 10; sdlRect.w = screen_w-20; //矩形兩邊,所以減20 sdlRect.h = screen_h-20; SDL_RenderClear( sdlRenderer ); SDL_RenderCopy( sdlRenderer, sdlTexture, NULL, &sdlRect); //將紋理的資料拷貝給渲染器 SDL_RenderPresent( sdlRenderer ); //顯示,渲染器把紋理渲染出來到視窗中 //Delay 40ms //顯示視訊,每秒顯示25幀 SDL_Delay(20);//延時40ms(25幀)。2倍的速度,除以2,改成20 } SDL_Quit();//退出SDL系統 return 0; }