SDL使用 现在我们要做的就是替代掉Tutorial 1中的SaveFrame(),将图像的帧数据显示到屏幕上。第一步我们不得不开始学习如何使用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()动态的加载和初始化SDL库,该函数带有一组标记来表示哪部分需要激活。标记有SDL_INIT_AUDIO、SDL_INIT_VIDEO、SDL_INIT_TIMER、SDL_INIT_CDROM,当然我们也可以使用SDL_INIT_EVERYTHING来表明加载所有的部分。使用SDL_GetError()可以获取到相应的出错信息。 使用完毕后调用SDL_Quit()来释放资源。
创建一个显示 在屏幕上我们需要一个地方能够显示图像数据。在SDL中能够展现图像数据的区域叫做表面(surface,这样翻译感觉有点怪)。
- SDL_Surface *screen = NULL;
- #ifndef __DARWIN__
- screen = SDL_SetVideoMode(pCodecCtx->width, pCodecCtx->height, 0, 0);
- #else
- screen = SDL_SetVideoMode(pCodecCtx->width, pCodecCtx->height, 24, 0);
- #endif
- if (!screen) {
- fprintf(stderr, "SDL: could not set video mode - exiting\n");
- exit(1);
- }
这根据给定的宽和高设置了一个显示屏幕。第三个参数表示图像显示时的色深,0是一个特殊的值,表示与当前的播放使用相同的色深。
现在我们创建一个可以存放图像数据的区域,如此可以将图像数据覆盖到屏幕上。显示的图像使用YV12的格式。
- SDL_Overlay *bmp = NULL;
- bmp = SDL_CreateYUVOverlay(pCodecCtx->width,
- pCodecCtx->height, SDL_YV12_OVERLAY, screen);
显示图像 是时候去显示图像了,要做的就是用新的代码去显示我们的图像数据帧,去除掉原先的SaveFrame(),创建一个AVPicture的结构体,然后初始化它的指针。
- 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];
- sws_scale(sws_ctx,
- (uint8_t const *const *)pFrame->data,
- pFrame->linesize,
- 0, pCodecCtx->height, pict.data, pict.linesize);
- SDL_UnlockYUVOverlay(bmp);
- ...
- }
首先我们锁住即将写数据的区域(这是一个很好的习惯,如此便不会给我们带来更多的麻烦)。这里处理的是YUV420P数据,只有3个通道,因此我们只需要设置3个相关的数据指针。如果是其它的格式的话可能需要为alpha通道初始化指针或其它的。
绘制图像 但是,我们仍然需要告诉SDL如何来显示我们给定的数据。需要传递一个SDL_Rect结构体的数据,来告诉SDL具体在哪个位置显示图像。
- rect.x = 0;
- rect.y = 0;
- rect.w = pCodecCtx->width;
- rect.h = pCodecCtx->height;
- SDL_DisplayYUVOverlay(bmp, &rect);
稍微介绍SDL的一些特性:它的事件系统。SDL被设置事件处理后,当输入数据,或移动鼠标,或发送信号给它,它会生成一个事件。程序然后检查这些事件,如果要处理用户的输入。程序也可以产生事件并且传递给SDL事件系统,在Tutorial 4中用SDL进行多线程编程时,这是特别有用的。在程序中,我们在处理完一个数据包后轮询事件。现在我们只是要处理SDL_QUIT事件,以便我们可以退出。
- SDL_PollEvent(&event);
- switch (event.type) {
- case SDL_QUIT:
- SDL_Quit();
- exit(0);
- break;
- default:
- break;
- }
当你运行这个程序时,会发生什么情况?视频要疯了!事实上,我们只是以最快的速度显示所有的视频帧。
阅读(2649) | 评论(4) | 转发(0) |