Chinaunix首页 | 论坛 | 博客
  • 博客访问: 312147
  • 博文数量: 78
  • 博客积分: 3635
  • 博客等级: 中校
  • 技术积分: 1115
  • 用 户 组: 普通用户
  • 注册时间: 2010-10-28 09:35
文章分类

全部博文(78)

文章存档

2011年(13)

2010年(65)

我的朋友

分类:

2010-12-20 09:33:04

http://fanwei51880.blog.163.com/blog/static/3240674020097232647417/

在 很多应用中的图形输出数据是存放在一些指定的内存区域的,比如说我现在实现的基于minigui图形中间件的mplayer播放器的,在播放前需要告诉 mplayer当前播放窗口所在的内存地址和当前的屏幕像素深度,bpp,窗口大小等等一系列的信息,这就有必要给mplayer写个自己的 video_out driver了。
和大多数驱动一样,mplayer也提供了一个驱动函数结构体,其结构体定义如下(在libvo/video_out.h文件中定义):

typedef struct vo_functions_s
{
vo_info_t *info;
/*
* Preinitializes driver (real INITIALIZATION)
*   arg - currently it's vo_subdevice
*   returns: zero on successful initialization, non-zero on error.
*/
int (*preinit)(const char *arg);
/*
* Initialize (means CONFIGURE) the display driver.
* params:
*   width,height: image source size
*   d_width,d_height: size of the requested window size, just a hint
*   fullscreen: flag, 0=windowd 1=fullscreen, just a hint
*   title: window title, if available
*   format: fourcc of pixel format
* returns : zero on successful initialization, non-zero on error.
*/
int (*config)(uint32_t width, uint32_t height, uint32_t d_width,
uint32_t d_height, uint32_t fullscreen, char *title,
uint32_t format);

/*
* Control interface
*/
int (*control)(uint32_t request, void *data, ...);

/*
* Display a new RGB/BGR frame of the video to the screen.
* params:
* src[0] - pointer to the image
*/
int (*draw_frame)(uint8_t *src[]);

/*
* Draw a planar YUV slice to the buffer:
* params:
*   src[3] = source image planes (Y,U,V)
   *   stride[3] = source image planes line widths (in bytes)
*   w,h = width*height of area to be copied (in Y pixels)
*   x,y = position at the destination image (in Y pixels)
*/
int (*draw_slice)(uint8_t *src[], int stride[], int w,int h, int x,int y);

/*
   * Draws OSD to the screen buffer
   */
   void (*draw_osd)(void);

   /*
   * Blit/Flip buffer to the screen. Must be called after each frame!
   */
   void (*flip_page)(void);

   /*
   * This func is called after every frames to handle keyboard and
   * other events. It's called in PAUSE mode too!
    */
    void (*check_events)(void);

    /*
    * Closes driver. Should restore the original state of the system.
    */
    void (*uninit)(void);

} vo_functions_t;

1:初始化驱动(preinit 函数、config函数和 uninit 函数):
当驱动初始化时将调用preinit ,退出时则调用uninit函数(注意:播放器在每播放一个媒体文件时都会初始化一次video驱动的)。
在preinit函数和config函数里可以做我们一些初始化工作,比如指定存放音频的内存地址,当前设备支持的像素,窗口大小,和bpp(每像素点需要用多少bit存储))等工作。
而uninit 函数则可以做些收尾工作了....

2:告诉mplayer设备支持的图形显示格式
在 mplayer调用完preinit 函数后, 它就要开始输出数据啦。 它在输出前会去查询下驱动支持的像素格式等一些大小,这时候它将调用驱动的control函数,并且传递 VOCTRL_QUERY_FORMAT参数, 这时候我们就应该把preinit函数中设置的参数告诉mplayer,然后mplayer就按设备支持的格式输出数据,

3:获取mplayer图形数据:
获取mplayer数据有很多种方法,这些方法可以根据设备来选择,这里我们只使用最简单的方法VOCTRL_DRAW_IMAGE。
同 样还是在control函数中,当mplayer输出数据将会调用control函数并传递VOCTRL_DRAW_IMAGE参数和 mp_image_t指针,我们可以通过mp_image_t指针来获取图像数据的大小,存放的位置等必要信息,然后将这些存放在显示内存中显示出 来...
int dx = mpi->w
int dy = mpi->h
uint8_t *buf = mpi->planes[0]
int stride = mpi->stride[0]

4:其它:
config函数:
mplayer将调用config函数来通知驱动,mplayer显示图形的原始大小,和播放的最佳大小,和影片标题等信息,这些信息只是给驱动提供参考值的.
还有其它draw_frame,draw_slice,draw_osd,flip_page等接口可以按需使用,充分利用mplayer提供的接口可以打造一个性能较优的video_out驱动的。

5:结尾
现在只是使用了简单的mplayer驱动的方法,其实还有很多点可以去优化的,比如说让mplayer直接将数据写到显示内存中,而不再先放入mp_image_t结构体中,充分利用其它的几个接口来提高驱动的性能。

阅读(1367) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~