您的位置:首页 > 其它

ffmpeg tutorial2学习--使用SDL显示到屏幕上

2016-05-19 23:10 405 查看

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包含到工程的属性里面
我这里没有放到工程里,而是设置成全局的
方法参考
/article/2129062.html
其中那个菜单直接在“视图”菜单里面就有 ,即“属性管理器”
3.可能会出现错误 =====================

注意:

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

我在测试该例子的时候,专门下载了1.2.XXX版的

2.同教程1一样,需要把SDL的lib和include包含到工程的属性里面

我这里没有放到工程里,而是设置成全局的

方法参考

/article/2129062.html

其中那个菜单直接在“视图”菜单里面就有 ,即“属性管理器”

3.可能会出现错误

无法解析的外部符号 _main,该符号在函数 ___tmainCRTStartup 中被引用

这个原因是没有把SDLmain.lib 放进去,放到连接库 里面即可。

4.

无法解析的外部符号 _main,该符号在函数 ___tmainCRTStartup 中被引用

这个原因是没有把SDLmain.lib 放进去,放到连接库 里面即可。
4.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: