[SimplePlayer] 2. 在屏幕上显示视频图像
我們這里采用SDL(本文所用版本為SDL2.0.5)來進行圖像輸出,SDL在進行圖像渲染時一般采用的會是direct3D或者opengl,SDL對它們進行了封裝,不過我們這里只討論SDL的使用,并不會去涉及這些底層實現。盡管如此,我們還是有必要了解其中一些基本概念,這些概念能幫助我們很好地理解所使用的SDL api的實際作用。
其中最重要的一個概念就是render,中文譯為渲染,rendering在計算機圖像領域指的就是圖像合成(image synthesis)。通俗一點的解釋就是:render指的是把2D圖像(圖形)或者3D模型變成所展示出來的圖像的過程,實際進行這種轉換操作的物件被稱為renderer(渲染器)。在SDL中,renderer主要處理的是2D的數據,其中包括
不過本文只用到renderer最基本的功能,即把圖像輸出到窗口。在SDL中,為了方便renderer的實現,renderer所處理的對象被規(guī)定為texture(紋理),因此圖像需要先被包裝成texture,texture會被render成rendered image,然后就可以輸出到window。
?
?
初始化
在使用SDL的函數之前,需要先調用SDL_Init來進行初始化,由于本文的目的是進行視頻圖像輸出,因此需要指定flag為SDL_INIT_VIDEO來初始化視頻子系統。
if(SDL_Init(SDL_INIT_VIDEO)){fprintf(stderr, "SDL init video failed\n");return -1;}?
接下來創(chuàng)建window、renderer、texture。在創(chuàng)建texture時需要指定輸入的圖像像素格式,通常視頻的像素格式都是yuv420p,對應的flag為SDL_PIXELFORMAT_IYUV。對于會頻繁更換的視頻圖像,還需要指定texture為SDL_TEXTUREACCESS_STREAMING。
window = SDL_CreateWindow("Simple Player", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, DEF_WIDTH, DEF_HEIGHT, 0);if(!window){fprintf(stderr, "SDL create window failed\n");return -1;}renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);if(!renderer){fprintf(stderr, "SDL create renderer failed\n");return -1;}texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_STREAMING, DEF_WIDTH, DEF_HEIGHT);if(!renderer){fprintf(stderr, "SDL create renderer failed\n");return -1;}SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_NONE);SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);SDL_RenderClear(renderer);?
創(chuàng)建用于存儲圖像像素數據的緩沖區(qū),并打開yuv文件,以供后續(xù)讀取圖像
YPlane = (unsigned char *)malloc(DEF_WIDTH*DEF_HEIGHT);UPlane = (unsigned char *)malloc(DEF_WIDTH*DEF_HEIGHT/4);VPlane = (unsigned char *)malloc(DEF_WIDTH*DEF_HEIGHT/4);pFile = fopen(argv[1], "rb");if(pFile==NULL)return -1;?
?
顯示
循環(huán)讀取圖像進入緩沖區(qū),然后把圖像傳入texture進行包裝、渲染、最后輸出,每幀間隔為1/24秒。對于視頻子系統來說,還有一個必不可少的步驟,就是在循環(huán)中調用SDL_PumpEvents。SDL_PumpEvents如其名稱,主要的功能是推動event隊列以進行隊列狀態(tài)的更新,不過它還有一個作用是進行視頻子系統的設備狀態(tài)更新,如果不調用這個函數,所顯示的視頻會在大約10秒后丟失色彩。
while(1){sizeY = fread(YPlane, 1, DEF_WIDTH*DEF_HEIGHT, pFile);sizeU = fread(UPlane, 1, DEF_WIDTH*DEF_HEIGHT/4, pFile);sizeV = fread(VPlane, 1, DEF_WIDTH*DEF_HEIGHT/4, pFile);if(!sizeY||!sizeU||!sizeV)break;if(0!=SDL_UpdateYUVTexture(texture, NULL, YPlane, DEF_WIDTH, UPlane, DEF_WIDTH/2, VPlane, DEF_WIDTH/2)){fprintf(stdout, "Render Update Texture failed, reason: %s\n", SDL_GetError());}SDL_RenderCopyEx(renderer, texture, NULL, NULL, 0, NULL, 0);SDL_RenderPresent(renderer);SDL_Delay(1000/FRAMERATE);SDL_PumpEvents();}?
?
退出
退出前的收尾處理
SDL_DestroyTexture(texture);SDL_DestroyRenderer(renderer);SDL_DestroyWindow(window);free(YPlane);free(UPlane);free(VPlane);fclose(pFile);轉載于:https://www.cnblogs.com/TaigaCon/p/9622016.html
總結
以上是生活随笔為你收集整理的[SimplePlayer] 2. 在屏幕上显示视频图像的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Val编程-速度因子
- 下一篇: SQL笔试经典50题