使用SDL2.0在mac OS上渲染視頻畫面
SDL下載:
使用 SDL 來渲染視頻到屏幕。SDL 是 Simple Direct Layer 的縮寫孟抗,是一個優(yōu)秀的跨平臺多媒體庫钻心,你可以從 http://www.libsdl.org 下載 SDL 的庫捷沸。需要講SDL導入/Library/Frameworks
目錄下狐史,否則在SDL編譯時會提示Image no found
.SDL 渲染的相關(guān)代碼
- 初始化
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {
fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());
exit(1);
}
- 創(chuàng)建一個screen,用來視頻的展示苍柏,一個texture用來加載視頻數(shù)據(jù)姜贡,一個渲染器用來渲染紋理。
//2. create window, Make a screen to put our video
screen = SDL_CreateWindow(
"FFmpeg Tutorial",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
pCodecCtx->width,
pCodecCtx->height,
0
);
if (!screen) {
fprintf(stderr, "SDL: could not create window - exiting\n");
exit(1);
}
// 3. create Render
renderer = SDL_CreateRenderer(screen, -1, 0);
if (!renderer) {
fprintf(stderr, "SDL: could not create renderer - exiting\n");
exit(1);
}
//4. create texture, Allocate a place to put our YUV image on that screen
texture = SDL_CreateTexture(
renderer,
SDL_PIXELFORMAT_YV12,
SDL_TEXTUREACCESS_STREAMING,
pCodecCtx->width,
pCodecCtx->height
);
if (!texture) {
fprintf(stderr, "SDL: could not create texture - exiting\n");
exit(1);
}
-
YUV數(shù)據(jù)處理熄捍,SDL 創(chuàng)建紋理時使用YV12是最快的,ffmpeg 解碼出來的視頻數(shù)據(jù)默認是YUV420p余耽,需要使用
sws_scale
函數(shù)講420p轉(zhuǎn)化為YV12.SDL 的 YUV overlay 可以接收一組 YUV 數(shù)據(jù)然后顯示它。它支持 4 種不同的 YUV 格式碟贾,其中 「YV12」 是最快的袱耽。另一種 YUV 格式是 「YUV420P」也叫 「I420」,基本上和 「YV12」 是一樣的扛邑,就是把 U 和 V 數(shù)組換了一下位置。
- YV12:亮度(行×列) + U(行×列/4) + V(行×列/4)
- I420:亮度(行×列) + V(行×列/4) + U(行×列/4)
sws_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height,
pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height,
PIX_FMT_YUV420P,
SWS_BILINEAR,
NULL,
NULL,
NULL);
// set up YV12 pixel array (12 bits per pixel)
yPlaneSz = pCodecCtx->width * pCodecCtx->height;
uvPlaneSz = pCodecCtx->width * pCodecCtx->height / 4;
yPlane = (Uint8*)malloc(yPlaneSz);
uPlane = (Uint8*)malloc(uvPlaneSz);
vPlane = (Uint8*)malloc(uvPlaneSz);
if (!yPlane || !uPlane || !vPlane) {
fprintf(stderr, "Could not allocate pixel buffers - exiting\n");
exit(1);
}
- 創(chuàng)建一個
AVPicture
,給pict賦值恶座,將解碼后的pFrame中的數(shù)據(jù)填充給pict
AVPicture pict;
uvPitch = pCodecCtx->width / 2;
pict.data[0] = yPlane;
pict.data[1] = uPlane;
pict.data[2] = vPlane;
pict.linesize[0] = pCodecCtx->width;
pict.linesize[1] = uvPitch;
pict.linesize[2] = uvPitch;
// Convert the image into YUV format that SDL uses
sws_scale(sws_ctx, (uint8_t const * const *) pFrame->data,
pFrame->linesize, 0, pCodecCtx->height, pict.data,
pict.linesize);
- 將視頻數(shù)據(jù)轉(zhuǎn)化為一張紋理圖沥阳,并且在屏幕中展示出來
// 紋理繪制
SDL_UpdateYUVTexture(
texture,
NULL,
yPlane,
pCodecCtx->width,
uPlane,
uvPitch,
vPlane,
uvPitch
);
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, texture, NULL, NULL);
// 紋理填充到屏幕
SDL_RenderPresent(renderer);
- 最終的效果圖
測試代碼:https://github.com/zjunchao/ffmpeg_tutorial/tree/master/tutorial02