ffmpeg tutorial2學習--使用SDL顯示到屏幕上


SDL的YUV接受4種YUV格式,最快的就是YV12,這和 YUV420P相似,只是UV被交換了。
420 表示是以4:2:0的比例來採樣,
P planar 表示YUV在不同的數組中,即是分開放的。

======下面是如何使用SDL的簡單說明
1.先include進文件,初始化SDL
    #include <SDL.h>
    #include <SDL_thread.h>
  if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO| SDL_INIT_TIMER))
{
fprintf(stderr, "could not initialize SDL--%s\n", SDL_GetError());
exit(1);
}
SDL_Init() 告訴庫我們將要使用哪些特性
2.創建一個Display
現在我們需要一個填充的screen,顯示圖像的區域叫做“surface”
SDL_Surface *screen;
screen = SDL_SetVideoMode(pCodecCtx->width, pCodecCtx->height, 0, 0);
if(!screen)
{
    fprintf(stderr, "SDL:could not set video mode-- exiting\n");
    exit(1);
}
z到這裏,用寬度和高度建立了一個screen。
SDL_SetVideoMode的第三個參數表示screen的深度--0是一個特殊的值,表示與當前display的值一樣。
現在我們要在screen的上面創建一個YUV overlay,這樣我們可以把視頻放進去,並且創建一個SWSContext來把圖像數據轉換成YUV420;
SDL_Overlay     *bmp = NULL;
    struct SWSContext *sws_ctx = NULL;
bmp = SDL_CreateYUVOverlay(pCodecCtx->width, pCodecCtx->height,
                               SDL_YV12_OVERLAY, screen);

    // initialize SWS context for software scaling
    sws_ctx = sws_getContext(pCodecCtx->width,
                             pCodecCtx->height,
                 pCodecCtx->pix_fmt,
                 pCodecCtx->width,
                 pCodecCtx->height,
                 PIX_FMT_YUV420P,
                 SWS_BILINEAR,
                 NULL,
                 NULL,
                 NULL
                 );
就像我們所說的,我們使用了YV12來顯示圖像,並從ffmpeg中得到YUV420數據。

### 顯示圖像
爲了顯示圖像,我們創建一個AVPicture結構體,設置它的數據指針和linesize到YUV overlay
if(frameFinished)
{
SDL_LockYUVOverlay(bmp);
AVPicture pict;
pict.data[0] = bmp->pixels[0];
pict.data[1] = bmp->pixels[2];
pict.data[2] = bmp->pixels[1];

pict.linesize[0] = bmp->pitches[0];
pict.linesize[1] = bmp->pitches[2];
pict.linesize[2] = bmp->pitches[1];

//Convert the image into YUV format taht sdl uses
sws_scale(sws_ctx, (uint8_t const* const *)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pict.data, pict.linesize);
SDL_UnlockYUVOverlay(bmp);
}
首先,我們lock了overlay,因爲我們要往裏面寫。AVPicture結構體,有一個data指針,是一個4個指針的數組。我們在處理YUV420P,所以只用了3個通道。linesize,就像名字表示的那樣。在YUV中相對應的名字是‘pixels` and `pitches。 pitches指的是一個給定line的寬度。
我們給pict寫數據,實際就是給ovelay來寫。 

### 畫圖像
我們仍舊需要告訴SDL來實際顯示我們給他的數據。我們要給這個函數傳遞一個矩形,以便告訴它視頻在哪裏顯示以及高度和寬度。這樣,SDL就能做scale,並且這可以得到GPU的協助以便更快的scale。
SDL_Rect rect;
if(frameFinished)
{
......
SDL_UnlockYUVOverlay(bmp);
rect.x = 0;
rect.y = 0;
rect.w = pCodecCtx->width;
rect.h = pCodecCtx->height;
SDL_DisplayYUVOverlay(bmp, &rect);
}
到此爲止,視頻能夠顯示了。

我們來看一下SDL 的另外一個特性:它的event 系統。當你在SDL 程序裏面,打字,或者移動鼠標的時候,或者給它發送一個信號,它會產生一個事件 **event**.你的程序 會檢查這些事件是否需要處理。你的程序也可以自己生成事件來發送給SDL event系統。這在SDL多線程編程時尤其有用,我們將在tutorial4看到。在這個程序中,我們在處理完一個packet後獲取事件。現在,我們要處理SDL_QUIT事件,這樣可以退出。
SDL_Event event;
av_free_packet(&packet);
SDL_PollEvent(&event);
witch(event.type){
case SDL_Quit:
SDL_Quit();
exit(0);
break;
default:
break;
}

=====================
注意:
1.本例子中使用的SDL是用的1.2.xxx版本的,目前最新的是2.X版,有很大的不同,
我在測試該例子的時候,專門下載了1.2.XXX版的
2.同教程1一樣,需要把SDL的lib和include包含到工程的屬性裏面
我這裏沒有放到工程裏,而是設置成全局的
方法參考
其中那個菜單直接在“視圖”菜單裏面就有 ,即“屬性管理器”
3.可能會出現錯誤 =====================

注意:

1.本例子中使用的SDL是用的1.2.xxx版本的,目前最新的是2.X版,有很大的不同,

我在測試該例子的時候,專門下載了1.2.XXX版的

2.同教程1一樣,需要把SDL的lib和include包含到工程的屬性裏面

我這裏沒有放到工程裏,而是設置成全局的

方法參考

http://blog.csdn.net/chaijunkun/article/details/6658923

其中那個菜單直接在“視圖”菜單裏面就有 ,即“屬性管理器”

3.可能會出現錯誤


無法解析的外部符號 _main,該符號在函數 ___tmainCRTStartup 中被引用

這個原因是沒有把SDLmain.lib 放進去,放到連接庫 裏面即可。

4.

無法解析的外部符號 _main,該符號在函數 ___tmainCRTStartup 中被引用

這個原因是沒有把SDLmain.lib 放進去,放到連接庫 裏面即可。

4.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章