Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4027084
  • 博文数量: 366
  • 博客积分: 9916
  • 博客等级: 中将
  • 技术积分: 7195
  • 用 户 组: 普通用户
  • 注册时间: 2011-05-29 23:27
个人简介

简单!

文章分类

全部博文(366)

文章存档

2013年(51)

2012年(269)

2011年(46)

分类: LINUX

2013-01-13 22:24:27

SDL使用

       现在我们要做的就是替代掉Tutorial 1中的SaveFrame(),将图像的帧数据显示到屏幕上。第一步我们不得不开始学习如何使用SDL库文件,首先要包括该库的头文件及初始化该库。

  1. #include <SDL.h>
  2. #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,这样翻译感觉有点怪)。

  1. SDL_Surface *screen = NULL;

  2. #ifndef __DARWIN__
  3.     screen = SDL_SetVideoMode(pCodecCtx->width, pCodecCtx->height, 0, 0);
  4. #else
  5.     screen = SDL_SetVideoMode(pCodecCtx->width, pCodecCtx->height, 24, 0);
  6. #endif
  7.     if (!screen) {
  8.         fprintf(stderr, "SDL: could not set video mode - exiting\n");
  9.         exit(1);
  10.     }
       这根据给定的宽和高设置了一个显示屏幕。第三个参数表示图像显示时的色深,0是一个特殊的值,表示与当前的播放使用相同的色深。

       现在我们创建一个可以存放图像数据的区域,如此可以将图像数据覆盖到屏幕上。显示的图像使用YV12的格式。

  1. SDL_Overlay *bmp = NULL;

  2. bmp = SDL_CreateYUVOverlay(pCodecCtx->width,
  3.                              pCodecCtx->height, SDL_YV12_OVERLAY, screen);


显示图像

       是时候去显示图像了,要做的就是用新的代码去显示我们的图像数据帧,去除掉原先的SaveFrame(),创建一个AVPicture的结构体,然后初始化它的指针。

  1. if (frameFinished) {
  2.     SDL_LockYUVOverlay(bmp);

  3.     AVPicture pict;
  4.     pict.data[0] = bmp->pixels[0];
  5.     pict.data[1] = bmp->pixels[2];
  6.     pict.data[2] = bmp->pixels[1];

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

  10.     sws_scale(sws_ctx,
  11.                 (uint8_t const *const *)pFrame->data,
  12.                 pFrame->linesize,
  13.                 0, pCodecCtx->height, pict.data, pict.linesize);

  14.     SDL_UnlockYUVOverlay(bmp);
  15.     ...
  16. }
       首先我们锁住即将写数据的区域(这是一个很好的习惯,如此便不会给我们带来更多的麻烦)。这里处理的是YUV420P数据,只有3个通道,因此我们只需要设置3个相关的数据指针。如果是其它的格式的话可能需要为alpha通道初始化指针或其它的。


绘制图像

       但是,我们仍然需要告诉SDL如何来显示我们给定的数据。需要传递一个SDL_Rect结构体的数据,来告诉SDL具体在哪个位置显示图像。

  1. rect.x = 0;
  2. rect.y = 0;
  3. rect.w = pCodecCtx->width;
  4. rect.h = pCodecCtx->height;
  5. SDL_DisplayYUVOverlay(bmp, &rect);
       稍微介绍SDL的一些特性:它的事件系统。SDL被设置事件处理后,当输入数据,或移动鼠标,或发送信号给它,它会生成一个事件。程序然后检查这些事件,如果要处理用户的输入。程序也可以产生事件并且传递给SDL事件系统,在Tutorial 4中用SDL进行多线程编程时,这是特别有用的。在程序中,我们在处理完一个数据包后轮询事件。现在我们只是要处理SDL_QUIT事件,以便我们可以退出。

  1. SDL_PollEvent(&event);
  2. switch (event.type) {
  3.     case SDL_QUIT:
  4.         SDL_Quit();
  5.         exit(0);
  6.         break;
  7.     default:
  8.         break;
  9. }

     当你运行这个程序时,会发生什么情况?视频要疯了!事实上,我们只是以最快的速度显示所有的视频帧。   
阅读(2640) | 评论(4) | 转发(0) |
给主人留下些什么吧!~~

txgc_wm2013-05-10 22:56:28

xiaonia12:谢谢楼主,我的邮箱是274141663@qq.com

已发送!

回复 | 举报

xiaonia122013-05-03 09:57:08

txgc_wm:最近项目有些忙,暂时没有时间写这方面的。如果有需要的话,我可以提供较有质量的代码给你测试。

谢谢楼主,我的邮箱是274141663@qq.com

回复 | 举报

txgc_wm2013-05-02 19:38:55

xiaonia12:楼主,什么时候出tutorial 03?我最近在写与ffmpeg相关的论文,虽然有可以运行的代码,但是在播放视频时有杂音,tutorial 03没有介绍关于音频重采样的问题,希望楼主能解答这个问题

最近项目有些忙,暂时没有时间写这方面的。如果有需要的话,我可以提供较有质量的代码给你测试。

回复 | 举报

xiaonia122013-05-02 17:03:01

楼主,什么时候出tutorial 03?我最近在写与ffmpeg相关的论文,虽然有可以运行的代码,但是在播放视频时有杂音,tutorial 03没有介绍关于音频重采样的问题,希望楼主能解答这个问题